From 0808ca673f224a0d74d040bdf82df01d98ff46d1 Mon Sep 17 00:00:00 2001 From: laerling Date: Fri, 5 Apr 2024 01:24:09 +0200 Subject: [PATCH 1/3] Move async_digest module to separate file --- src/async_digest.rs | 76 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 82 ++------------------------------------------- 2 files changed, 79 insertions(+), 79 deletions(-) create mode 100644 src/async_digest.rs diff --git a/src/async_digest.rs b/src/async_digest.rs new file mode 100644 index 0000000..e2bd1ae --- /dev/null +++ b/src/async_digest.rs @@ -0,0 +1,76 @@ +use crate::{CalculatorSelector, TrySha256Digest}; +use bytes::BytesMut; +use std::io; + +/// sha256 digest file +/// +/// # Examples +/// +/// ```rust +/// use sha256::{try_async_digest}; +/// use std::path::Path; +/// let input = Path::new("./foo.file"); +/// tokio_test::block_on(async{ +/// let val = try_async_digest(input).await.unwrap(); +/// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1") +/// }); +/// +/// ``` +pub async fn try_async_digest(input: D) -> Result { + input.async_digest().await +} + +/// sha256 digest file +/// +/// # Examples +/// +/// ```rust +/// use sha256::{try_async_openssl_digest}; +/// use std::path::Path; +/// let input = Path::new("./foo.file"); +/// tokio_test::block_on(async{ +/// let val = try_async_openssl_digest(input).await.unwrap(); +/// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1") +/// }); +/// ``` +#[cfg(feature = "native_openssl")] +pub async fn try_async_openssl_digest( + input: D, +) -> Result { + input.async_openssl_digest().await +} + +#[async_trait::async_trait] +pub trait AsyncCalculatorInput { + async fn read_inner(&mut self, buf: &mut BytesMut) -> io::Result; +} + +pub async fn async_calc(mut input: I, mut selector: S) -> io::Result +where + I: AsyncCalculatorInput, + S: CalculatorSelector, +{ + let mut buf = BytesMut::with_capacity(1024); + loop { + buf.clear(); + let len = input.read_inner(&mut buf).await?; + if len == 0 { + break; + } + selector.update_inner(&buf[0..len]); + } + let hash = selector.finish_inner(); + Ok(hex::encode(hash)) +} + +#[async_trait::async_trait] +impl AsyncCalculatorInput for tokio::io::BufReader +where + R: tokio::io::AsyncRead + Unpin + Send, +{ + async fn read_inner(&mut self, buf: &mut BytesMut) -> io::Result { + use tokio::io::AsyncReadExt; + + self.read_buf(buf).await + } +} diff --git a/src/lib.rs b/src/lib.rs index 94ec155..6e36af4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -50,6 +50,9 @@ use std::io; use std::io::{BufReader, Read}; use std::path::Path; +#[cfg(feature = "async")] +pub mod async_digest; + /// sha256 digest string /// /// # Examples @@ -267,85 +270,6 @@ where Ok(hex::encode(hash)) } -#[cfg(feature = "async")] -pub mod async_digest { - use crate::{CalculatorSelector, TrySha256Digest}; - use bytes::BytesMut; - use std::io; - - /// sha256 digest file - /// - /// # Examples - /// - /// ```rust - /// use sha256::{try_async_digest}; - /// use std::path::Path; - /// let input = Path::new("./foo.file"); - /// tokio_test::block_on(async{ - /// let val = try_async_digest(input).await.unwrap(); - /// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1") - /// }); - /// - /// ``` - pub async fn try_async_digest(input: D) -> Result { - input.async_digest().await - } - - /// sha256 digest file - /// - /// # Examples - /// - /// ```rust - /// use sha256::{try_async_openssl_digest}; - /// use std::path::Path; - /// let input = Path::new("./foo.file"); - /// tokio_test::block_on(async{ - /// let val = try_async_openssl_digest(input).await.unwrap(); - /// assert_eq!(val,"433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1") - /// }); - /// ``` - #[cfg(feature = "native_openssl")] - pub async fn try_async_openssl_digest( - input: D, - ) -> Result { - input.async_openssl_digest().await - } - - #[async_trait::async_trait] - pub trait AsyncCalculatorInput { - async fn read_inner(&mut self, buf: &mut BytesMut) -> io::Result; - } - - pub async fn async_calc(mut input: I, mut selector: S) -> io::Result - where - I: AsyncCalculatorInput, - S: CalculatorSelector, - { - let mut buf = BytesMut::with_capacity(1024); - loop { - buf.clear(); - let len = input.read_inner(&mut buf).await?; - if len == 0 { - break; - } - selector.update_inner(&buf[0..len]); - } - let hash = selector.finish_inner(); - Ok(hex::encode(hash)) - } - - #[async_trait::async_trait] - impl AsyncCalculatorInput for tokio::io::BufReader - where - R: tokio::io::AsyncRead + Unpin + Send, - { - async fn read_inner(&mut self, buf: &mut BytesMut) -> io::Result { - use tokio::io::AsyncReadExt; - - self.read_buf(buf).await - } - } -} #[cfg(feature = "native_openssl")] mod openssl_sha256 { From 90f5cf72aaada7b761098944a3550a6535144652 Mon Sep 17 00:00:00 2001 From: laerling Date: Fri, 5 Apr 2024 10:02:40 +0200 Subject: [PATCH 2/3] Move tests module to separate file --- src/lib.rs | 148 +-------------------------------------------------- src/tests.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 146 deletions(-) create mode 100644 src/tests.rs diff --git a/src/lib.rs b/src/lib.rs index 6e36af4..cf0d485 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,6 +52,8 @@ use std::path::Path; #[cfg(feature = "async")] pub mod async_digest; +#[cfg(test)] +mod tests; /// sha256 digest string /// @@ -289,149 +291,3 @@ mod openssl_sha256 { } } } - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(feature = "native_openssl")] - #[test] - fn test_openssl() { - let input = Path::new("./foo.file"); - let f = fs::File::open(input).unwrap(); - let reader = BufReader::new(f); - let sha = openssl::sha::Sha256::new(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - calc(reader, sha).unwrap() - ); - } - - #[test] - fn test_sha256() { - let input = Path::new("./foo.file"); - let f = fs::File::open(input).unwrap(); - let reader = BufReader::new(f); - let sha = Sha256::new(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - calc(reader, sha).unwrap() - ); - } - - #[cfg(all(feature = "async", feature = "native_openssl"))] - #[tokio::test] - async fn test_async_openssl() { - let input = Path::new("./foo.file"); - let f = tokio::fs::File::open(input).await.unwrap(); - let reader = tokio::io::BufReader::new(f); - let sha = openssl::sha::Sha256::new(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - async_calc(reader, sha).await.unwrap() - ); - } - - #[cfg(feature = "async")] - #[tokio::test] - async fn test_async() { - let input = Path::new("./foo.file"); - let f = tokio::fs::File::open(input).await.unwrap(); - let reader = tokio::io::BufReader::new(f); - let sha = Sha256::new(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - async_calc(reader, sha).await.unwrap() - ); - } - - #[cfg(all(feature = "async", feature = "native_openssl"))] - #[tokio::test] - async fn test_try_async_openssl_digest() { - let hash = try_async_openssl_digest("./foo.file").await.unwrap(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - hash - ); - } - - #[cfg(feature = "async")] - #[tokio::test] - async fn test_try_async_digest() { - let hash = try_async_digest("./foo.file").await.unwrap(); - assert_eq!( - "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", - hash - ); - } - - #[cfg(feature = "async")] - #[tokio::test] - async fn test_async_parity() { - let bytes = (0..0x1000).map(|v| (v % 256) as u8).collect::>(); - let val = digest(&bytes); - - let async_res = { - let bytes = &bytes; - // We want to force Poll::Pending on reads during async_calc, which may break parity - // between sync and async hashing. - let (client, mut server) = tokio::io::duplex(64); - let reader = tokio::io::BufReader::new(client); - let sha = Sha256::new(); - - use tokio::io::AsyncWriteExt; - tokio::join! { - async_calc(reader, sha), - async move { - server.write_all(&bytes[..]).await.unwrap(); - core::mem::drop(server); - } - } - .0 - .unwrap() - }; - - let sync_res = { - let reader = BufReader::new(&*bytes); - let sha = Sha256::new(); - calc(reader, sha).unwrap() - }; - assert_eq!(val, async_res); - assert_eq!(async_res, sync_res); - } - - #[cfg(all(feature = "async", feature = "native_openssl"))] - #[tokio::test] - async fn test_async_parity_openssl() { - let bytes = (0..0x1000).map(|v| (v % 256) as u8).collect::>(); - let val = digest(&bytes); - - let async_res = { - let bytes = &bytes; - // We want to force Poll::Pending on reads during async_calc, which may break parity - // between sync and async hashing. - let (client, mut server) = tokio::io::duplex(64); - let reader = tokio::io::BufReader::new(client); - let sha = OpenSslSha256::new(); - - use tokio::io::AsyncWriteExt; - tokio::join! { - async_calc(reader, sha), - async move { - server.write_all(&bytes[..]).await.unwrap(); - core::mem::drop(server); - } - } - .0 - .unwrap() - }; - - let sync_res = { - let reader = BufReader::new(&*bytes); - let sha = OpenSslSha256::new(); - calc(reader, sha).unwrap() - }; - assert_eq!(val, async_res); - assert_eq!(async_res, sync_res); - } -} diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..43804a9 --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,142 @@ +use super::*; + +#[cfg(feature = "native_openssl")] +#[test] +fn test_openssl() { + let input = Path::new("./foo.file"); + let f = fs::File::open(input).unwrap(); + let reader = BufReader::new(f); + let sha = openssl::sha::Sha256::new(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + calc(reader, sha).unwrap() + ); +} + +#[test] +fn test_sha256() { + let input = Path::new("./foo.file"); + let f = fs::File::open(input).unwrap(); + let reader = BufReader::new(f); + let sha = Sha256::new(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + calc(reader, sha).unwrap() + ); +} + +#[cfg(all(feature = "async", feature = "native_openssl"))] +#[tokio::test] +async fn test_async_openssl() { + let input = Path::new("./foo.file"); + let f = tokio::fs::File::open(input).await.unwrap(); + let reader = tokio::io::BufReader::new(f); + let sha = openssl::sha::Sha256::new(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + async_calc(reader, sha).await.unwrap() + ); +} + +#[cfg(feature = "async")] +#[tokio::test] +async fn test_async() { + let input = Path::new("./foo.file"); + let f = tokio::fs::File::open(input).await.unwrap(); + let reader = tokio::io::BufReader::new(f); + let sha = Sha256::new(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + async_calc(reader, sha).await.unwrap() + ); +} + +#[cfg(all(feature = "async", feature = "native_openssl"))] +#[tokio::test] +async fn test_try_async_openssl_digest() { + let hash = try_async_openssl_digest("./foo.file").await.unwrap(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + hash + ); +} + +#[cfg(feature = "async")] +#[tokio::test] +async fn test_try_async_digest() { + let hash = try_async_digest("./foo.file").await.unwrap(); + assert_eq!( + "433855b7d2b96c23a6f60e70c655eb4305e8806b682a9596a200642f947259b1", + hash + ); +} + +#[cfg(feature = "async")] +#[tokio::test] +async fn test_async_parity() { + let bytes = (0..0x1000).map(|v| (v % 256) as u8).collect::>(); + let val = digest(&bytes); + + let async_res = { + let bytes = &bytes; + // We want to force Poll::Pending on reads during async_calc, which may break parity + // between sync and async hashing. + let (client, mut server) = tokio::io::duplex(64); + let reader = tokio::io::BufReader::new(client); + let sha = Sha256::new(); + + use tokio::io::AsyncWriteExt; + tokio::join! { + async_calc(reader, sha), + async move { + server.write_all(&bytes[..]).await.unwrap(); + core::mem::drop(server); + } + } + .0 + .unwrap() + }; + + let sync_res = { + let reader = BufReader::new(&*bytes); + let sha = Sha256::new(); + calc(reader, sha).unwrap() + }; + assert_eq!(val, async_res); + assert_eq!(async_res, sync_res); +} + +#[cfg(all(feature = "async", feature = "native_openssl"))] +#[tokio::test] +async fn test_async_parity_openssl() { + let bytes = (0..0x1000).map(|v| (v % 256) as u8).collect::>(); + let val = digest(&bytes); + + let async_res = { + let bytes = &bytes; + // We want to force Poll::Pending on reads during async_calc, which may break parity + // between sync and async hashing. + let (client, mut server) = tokio::io::duplex(64); + let reader = tokio::io::BufReader::new(client); + let sha = OpenSslSha256::new(); + + use tokio::io::AsyncWriteExt; + tokio::join! { + async_calc(reader, sha), + async move { + server.write_all(&bytes[..]).await.unwrap(); + core::mem::drop(server); + } + } + .0 + .unwrap() + }; + + let sync_res = { + let reader = BufReader::new(&*bytes); + let sha = OpenSslSha256::new(); + calc(reader, sha).unwrap() + }; + assert_eq!(val, async_res); + assert_eq!(async_res, sync_res); +} From de7b7783aa40898880054ebd62440b43636a778e Mon Sep 17 00:00:00 2001 From: laerling Date: Fri, 5 Apr 2024 10:04:39 +0200 Subject: [PATCH 3/3] Move openssl_sha256 module to separate file --- src/lib.rs | 22 ++-------------------- src/openssl_sha256.rs | 15 +++++++++++++++ 2 files changed, 17 insertions(+), 20 deletions(-) create mode 100644 src/openssl_sha256.rs diff --git a/src/lib.rs b/src/lib.rs index cf0d485..0900e60 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -54,6 +54,8 @@ use std::path::Path; pub mod async_digest; #[cfg(test)] mod tests; +#[cfg(feature = "native_openssl")] +mod openssl_sha256; /// sha256 digest string /// @@ -271,23 +273,3 @@ where let hash = selector.finish_inner(); Ok(hex::encode(hash)) } - - -#[cfg(feature = "native_openssl")] -mod openssl_sha256 { - use crate::CalculatorSelector; - - pub type OpenSslSha256 = openssl::sha::Sha256; - - impl CalculatorSelector for OpenSslSha256 { - type FinishType = [u8; 32]; - - fn update_inner(&mut self, data: &[u8]) { - self.update(data) - } - - fn finish_inner(self) -> Self::FinishType { - self.finish() - } - } -} diff --git a/src/openssl_sha256.rs b/src/openssl_sha256.rs new file mode 100644 index 0000000..739d0ed --- /dev/null +++ b/src/openssl_sha256.rs @@ -0,0 +1,15 @@ +use crate::CalculatorSelector; + +pub type OpenSslSha256 = openssl::sha::Sha256; + +impl CalculatorSelector for OpenSslSha256 { + type FinishType = [u8; 32]; + + fn update_inner(&mut self, data: &[u8]) { + self.update(data) + } + + fn finish_inner(self) -> Self::FinishType { + self.finish() + } +}