From 77ab8327e026cf9b1357b87572a4abb25eba1885 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konrad=20Go=C5=82awski?= Date: Sun, 27 Oct 2024 17:58:05 +0100 Subject: [PATCH] Add async support for Tokio runtime --- .cargo/README.md | 2 +- CHANGELOG.md | 7 + Cargo.toml | 11 +- README.md | 2 +- src/lib.rs | 63 ++++++++- src/reader.rs | 28 ++-- src/writer.rs | 18 +++ tests/sha2_512.rs | 322 ++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 439 insertions(+), 14 deletions(-) diff --git a/.cargo/README.md b/.cargo/README.md index eb33162..d52bfeb 100644 --- a/.cargo/README.md +++ b/.cargo/README.md @@ -27,7 +27,7 @@ cargo add chksum-sha2-512 ## Usage -Use the `chksum` function to calcualate digest of file, directory and so on. +Use the `chksum` function to calculate digest of file, directory and so on. ```rust use chksum_sha2_512 as sha2_512; diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c0c1a9..b0a26d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- Added async support for Tokio runtime. + ## [0.0.0] - 2023-12-21 ### Added - Initial release. +[Unreleased]: https://github.com/chksum-rs/sha2-512/compare/v0.0.0...HEAD [0.0.0]: https://github.com/chksum-rs/sha2-512/releases/tag/v0.0.0 diff --git a/Cargo.toml b/Cargo.toml index 6acf464..b74a7e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,16 +16,21 @@ all-features = true rustdoc-args = ["--cfg", "docsrs"] [dependencies] -chksum-core = "0.0.0" +chksum-core = "0.1.0" chksum-hash-sha2-512 = "0.0.0" -chksum-reader = { version = "0.0.0", optional = true } -chksum-writer = { version = "0.0.0", optional = true } +chksum-reader = { version = "0.1.0", optional = true } +chksum-writer = { version = "0.1.0", optional = true } +tokio = { version = "1.37.0", features = ["io-util"], optional = true } [dev-dependencies] assert_fs = { version = "1.0.13", features = ["color-auto"] } thiserror = "1.0.51" +tokio = { version = "1.37.0", features = ["macros", "rt", "rt-multi-thread"] } [features] default = [] reader = ["chksum-reader"] writer = ["chksum-writer"] + +# async runtimes +async-runtime-tokio = ["chksum-core/async-runtime-tokio", "chksum-reader?/async-runtime-tokio", "chksum-writer?/async-runtime-tokio", "tokio"] diff --git a/README.md b/README.md index 548a8a4..d992df7 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ cargo add chksum-sha2-512 ## Usage -Use the `chksum` function to calcualate digest of file, directory and so on. +Use the `chksum` function to calculate digest of file, directory and so on. ```rust use chksum_sha2_512 as sha2_512; diff --git a/src/lib.rs b/src/lib.rs index ae0c237..e2e5a7a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -19,7 +19,7 @@ //! //! # Usage //! -//! Use the [`chksum`] function to calcualate digest of file, directory and so on. +//! Use the [`chksum`] function to calculate digest of file, directory and so on. //! //! ```rust //! # use std::path::Path; @@ -39,6 +39,30 @@ //! # } //! ``` //! +//! ## Asynchronous Runtime +//! +//! Use the [`async_chksum`] function to calculate digest of file, directory and so on. +//! +//! ```rust +//! # #[cfg(feature = "async-runtime-tokio")] +//! # { +//! # use std::path::Path; +//! # use chksum_sha2_512::Result; +//! use chksum_sha2_512 as sha2_512; +//! use tokio::fs::File; +//! +//! # async fn wrapper(path: &Path) -> Result<()> { +//! let file = File::open(path).await?; +//! let digest = sha2_512::async_chksum(file).await?; +//! assert_eq!( +//! digest.to_hex_lowercase(), +//! "ed59c5759a9ece516cec0c0623142d0e9fe70a27d750eee7fd38f4550d50addd873d0fa1a51fc823c1e3d5cada203f4a05d8325caacb7d3e0727a701f3f07e5f" +//! ); +//! # Ok(()) +//! # } +//! # } +//! ``` +//! //! # Input Types //! //! ## Bytes @@ -231,6 +255,12 @@ //! cargo add chksum-sha2-512 --features reader,writer //! ``` //! +//! ## Asynchronous Runtime +//! +//! * `async-runtime-tokio`: Enables async interface for Tokio runtime. +//! +//! By default, neither of these features is enabled. +//! //! # License //! //! This crate is licensed under the MIT License. @@ -246,14 +276,23 @@ pub mod writer; use std::fmt::{self, Display, Formatter, LowerHex, UpperHex}; use chksum_core as core; +#[cfg(feature = "async-runtime-tokio")] +#[doc(no_inline)] +pub use chksum_core::AsyncChksumable; #[doc(no_inline)] pub use chksum_core::{Chksumable, Error, Hash, Hashable, Result}; #[doc(no_inline)] pub use chksum_hash_sha2_512 as hash; +#[cfg(all(feature = "reader", feature = "async-runtime-tokio"))] +#[doc(inline)] +pub use crate::reader::AsyncReader; #[cfg(feature = "reader")] #[doc(inline)] pub use crate::reader::Reader; +#[cfg(all(feature = "writer", feature = "async-runtime-tokio"))] +#[doc(inline)] +pub use crate::writer::AsyncWriter; #[cfg(feature = "writer")] #[doc(inline)] pub use crate::writer::Writer; @@ -335,6 +374,28 @@ pub fn chksum(data: impl core::Chksumable) -> Result { core::chksum::(data) } +/// Computes the hash of the given input. +/// +/// # Example +/// +/// ```rust +/// use chksum_sha2_512 as sha2_512; +/// +/// # async fn wrapper() { +/// let data = b"example data"; +/// if let Ok(digest) = sha2_512::async_chksum(data).await { +/// assert_eq!( +/// digest.to_hex_lowercase(), +/// "ed59c5759a9ece516cec0c0623142d0e9fe70a27d750eee7fd38f4550d50addd873d0fa1a51fc823c1e3d5cada203f4a05d8325caacb7d3e0727a701f3f07e5f" +/// ); +/// } +/// # } +/// ``` +#[cfg(feature = "async-runtime-tokio")] +pub async fn async_chksum(data: impl core::AsyncChksumable) -> Result { + core::async_chksum::(data).await +} + /// The SHA-2 512 hash instance. #[derive(Clone, Debug, Default, PartialEq, Eq)] pub struct SHA2_512 { diff --git a/src/reader.rs b/src/reader.rs index e1a6d35..3648af2 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -47,24 +47,36 @@ use std::io::Read; use chksum_reader as reader; +#[cfg(feature = "async-runtime-tokio")] +use tokio::io::AsyncRead; use crate::SHA2_512; /// A specialized [`Reader`](reader::Reader) type with the [`SHA2_512`] hash algorithm. pub type Reader = reader::Reader; +#[cfg(feature = "async-runtime-tokio")] +/// A specialized [`AsyncReader`](reader::AsyncReader) type with the [`SHA2_512`] hash algorithm. +pub type AsyncReader = reader::AsyncReader; + /// Creates new [`Reader`]. -pub fn new(inner: R) -> Reader -where - R: Read, -{ +pub fn new(inner: impl Read) -> Reader { reader::new(inner) } /// Creates new [`Reader`] with provided hash. -pub fn with_hash(inner: R, hash: SHA2_512) -> Reader -where - R: Read, -{ +pub fn with_hash(inner: impl Read, hash: SHA2_512) -> Reader { reader::with_hash(inner, hash) } + +#[cfg(feature = "async-runtime-tokio")] +/// Creates new [`AsyncReader`]. +pub fn async_new(inner: impl AsyncRead) -> AsyncReader { + reader::async_new(inner) +} + +#[cfg(feature = "async-runtime-tokio")] +/// Creates new [`AsyncReader`] with provided hash. +pub fn async_with_hash(inner: impl AsyncRead, hash: SHA2_512) -> AsyncReader { + reader::async_with_hash(inner, hash) +} diff --git a/src/writer.rs b/src/writer.rs index 636535f..1f01fb3 100644 --- a/src/writer.rs +++ b/src/writer.rs @@ -45,12 +45,18 @@ use std::io::Write; use chksum_writer as writer; +#[cfg(feature = "async-runtime-tokio")] +use tokio::io::AsyncWrite; use crate::SHA2_512; /// A specialized [`Writer`](writer::Writer) type with the [`SHA2_512`] hash algorithm. pub type Writer = writer::Writer; +#[cfg(feature = "async-runtime-tokio")] +/// A specialized [`AsyncWriter`](writer::AsyncWriter) type with the [`SHA2_512`] hash algorithm. +pub type AsyncWriter = writer::AsyncWriter; + /// Creates new [`Writer`]. pub fn new(inner: impl Write) -> Writer { writer::new(inner) @@ -60,3 +66,15 @@ pub fn new(inner: impl Write) -> Writer { pub fn with_hash(inner: impl Write, hash: SHA2_512) -> Writer { writer::with_hash(inner, hash) } + +#[cfg(feature = "async-runtime-tokio")] +/// Creates new [`AsyncWriter`]. +pub fn async_new(inner: impl AsyncWrite) -> AsyncWriter { + writer::async_new(inner) +} + +#[cfg(feature = "async-runtime-tokio")] +/// Creates new [`AsyncWriter`] with provided hash. +pub fn async_with_hash(inner: impl AsyncWrite, hash: SHA2_512) -> AsyncWriter { + writer::async_with_hash(inner, hash) +} diff --git a/tests/sha2_512.rs b/tests/sha2_512.rs index 68a7090..c5ec165 100644 --- a/tests/sha2_512.rs +++ b/tests/sha2_512.rs @@ -4,7 +4,11 @@ use std::io::Error as IoError; use assert_fs::fixture::FixtureError; use assert_fs::prelude::{FileTouch, FileWriteBin, PathChild}; use assert_fs::TempDir; +#[cfg(feature = "async-runtime-tokio")] +use chksum_sha2_512::async_chksum; use chksum_sha2_512::{chksum, Error as ChksumError}; +#[cfg(feature = "async-runtime-tokio")] +use tokio::fs::{read_dir as tokio_read_dir, File as TokioFile}; #[derive(Debug, thiserror::Error)] enum Error { @@ -27,6 +31,21 @@ fn empty_directory_as_path() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_directory_as_path() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + + let dir = temp_dir.path(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn empty_directory_as_pathbuf() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -42,6 +61,25 @@ fn empty_directory_as_pathbuf() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_directory_as_pathbuf() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + + let dir = temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + + let dir = &temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn empty_directory_as_readdir() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -53,6 +91,21 @@ fn empty_directory_as_readdir() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_directory_as_readdir() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + + let dir = tokio_read_dir(temp_dir.path()).await?; + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_empty_file_as_path() -> Result<(), Error> { let temp_dir = { @@ -68,6 +121,25 @@ fn non_empty_directory_with_empty_file_as_path() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_empty_file_as_path() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + temp_dir.child("file.txt").touch()?; + temp_dir + }; + + let dir = temp_dir.path(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_empty_file_as_pathbuf() -> Result<(), Error> { let temp_dir = { @@ -87,6 +159,29 @@ fn non_empty_directory_with_empty_file_as_pathbuf() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_empty_file_as_pathbuf() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + temp_dir.child("file.txt").touch()?; + temp_dir + }; + + let dir = temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + + let dir = &temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_empty_file_as_readdir() -> Result<(), Error> { let temp_dir = { @@ -102,6 +197,25 @@ fn non_empty_directory_with_empty_file_as_readdir() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_empty_file_as_readdir() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + temp_dir.child("file.txt").touch()?; + temp_dir + }; + + let dir = tokio_read_dir(temp_dir.path()).await?; + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_non_empty_file_as_path() -> Result<(), Error> { let temp_dir = { @@ -119,6 +233,27 @@ fn non_empty_directory_with_non_empty_file_as_path() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_non_empty_file_as_path() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + temp_dir + }; + + let dir = temp_dir.path(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_non_empty_file_as_pathbuf() -> Result<(), Error> { let temp_dir = { @@ -140,6 +275,31 @@ fn non_empty_directory_with_non_empty_file_as_pathbuf() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_non_empty_file_as_pathbuf() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + temp_dir + }; + + let dir = temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + + let dir = &temp_dir.to_path_buf(); + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +} + #[test] fn non_empty_directory_with_non_empty_file_as_readdir() -> Result<(), Error> { let temp_dir = { @@ -157,6 +317,27 @@ fn non_empty_directory_with_non_empty_file_as_readdir() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_directory_with_non_empty_file_as_readdir() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = { + let temp_dir = TempDir::new()?; + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + temp_dir + }; + + let dir = tokio_read_dir(temp_dir.path()).await?; + let digest = async_chksum(dir).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +} + #[test] fn empty_file_as_path() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -173,6 +354,26 @@ fn empty_file_as_path() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_file_as_path() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file + }; + + let file = child.path(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn empty_file_as_pathbuf() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -193,6 +394,30 @@ fn empty_file_as_pathbuf() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_file_as_pathbuf() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file + }; + + let file = child.to_path_buf(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + + let file = &child.to_path_buf(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn empty_file_as_file() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -213,6 +438,31 @@ fn empty_file_as_file() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_empty_file_as_file() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file + }; + + let file = TokioFile::open(child.path()).await?; + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + + // TODO: missing `&File` implementation + // let file = &TokioFile::open(child.path()).await?; + // let digest = async_chksum(file).await?.to_hex_lowercase(); + // assert_eq!(digest, "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"); + } + + Ok(()) +} + #[test] fn non_empty_file_as_path() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -230,6 +480,27 @@ fn non_empty_file_as_path() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_file_as_path() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + file + }; + + let file = child.path(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +} + #[test] fn non_empty_file_as_pathbuf() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -251,6 +522,31 @@ fn non_empty_file_as_pathbuf() -> Result<(), Error> { Ok(()) } +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_file_as_pathbuf() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + file + }; + + let file = child.to_path_buf(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + + let file = &child.to_path_buf(); + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +} + #[test] fn non_empty_file_as_file() -> Result<(), Error> { let temp_dir = TempDir::new()?; @@ -271,3 +567,29 @@ fn non_empty_file_as_file() -> Result<(), Error> { Ok(()) } + +#[cfg_attr(not(feature = "async-runtime-tokio"), ignore)] +#[tokio::test] +async fn async_runtime_tokio_non_empty_file_as_file() -> Result<(), Error> { + #[cfg(feature = "async-runtime-tokio")] + { + let temp_dir = TempDir::new()?; + let child = { + let file = temp_dir.child("file.txt"); + file.touch()?; + file.write_binary(b"data")?; + file + }; + + let file = TokioFile::open(child.path()).await?; + let digest = async_chksum(file).await?.to_hex_lowercase(); + assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + + // TODO: missing `&File` implementation + // let file = &TokioFile::open(child.path()).await?; + // let digest = async_chksum(file).await?.to_hex_lowercase(); + // assert_eq!(digest, "77c7ce9a5d86bb386d443bb96390faa120633158699c8844c30b13ab0bf92760b7e4416aea397db91b4ac0e5dd56b8ef7e4b066162ab1fdc088319ce6defc876"); + } + + Ok(()) +}