From 688c8625f2dbd0d538371ebe16b82091c0d51908 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 9 Aug 2022 10:44:46 +1000 Subject: [PATCH 1/4] Remove implementation of Deref According to the Rust docs [0] on the `Deref` trait, it should only be implemented for smart pointers. Remove the implementation of `Deref`. [0] https://doc.rust-lang.org/std/ops/trait.Deref.html --- src/util.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/util.rs b/src/util.rs index 77f4ce2..85a6615 100644 --- a/src/util.rs +++ b/src/util.rs @@ -28,9 +28,9 @@ macro_rules! hex_fmt_impl( write!(f, "0x")?; } if $ty::<$($gen),*>::DISPLAY_BACKWARD { - hex::format_hex_reverse(&self.0, f) + hex::format_hex_reverse(self.as_ref(), f) } else { - hex::format_hex(&self.0, f) + hex::format_hex(self.as_ref(), f) } } } @@ -67,14 +67,6 @@ macro_rules! borrow_slice_impl( &self[..] } } - - impl<$($gen: $gent),*> $crate::_export::_core::ops::Deref for $ty<$($gen),*> { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.0 - } - } ) ); @@ -243,7 +235,7 @@ mod test { fn borrow_slice_impl_to_vec() { // Test that the borrow_slice_impl macro gives to_vec. let hash = sha256::Hash::hash(&[3, 50]); - assert_eq!(hash.to_vec().len(), sha256::Hash::LEN); + assert_eq!(hash.as_ref().len(), sha256::Hash::LEN); } hash_newtype!(TestHash, crate::sha256d::Hash, 32, doc="Test hash."); From b13b06a8ca59a378d36e199dd48ff98f12964057 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 9 Aug 2022 11:08:31 +1000 Subject: [PATCH 2/4] Remove Index implementations The `Index` trait is not required if we provide the `AsRef` trait. Users can just call `as_ref()[0]` to get access to the 0th element of a `Hash`. For times when we take a reference to the whole slice `[..]` using `as_ref()` is capable and arguably more ergonomic. From the `Hash` trait remove the trait bound on `Index` and its associated traits, instead use the trait bound `AsRef` (we already have a trait bound of `Borrow`). Fix all uses of `foo[..]` -> `foo.as_ref()`. --- fuzz/fuzz_targets/ripemd160.rs | 2 +- fuzz/fuzz_targets/sha1.rs | 2 +- fuzz/fuzz_targets/sha256.rs | 2 +- fuzz/fuzz_targets/sha512.rs | 2 +- src/cmp.rs | 16 +++++------ src/hash160.rs | 21 ++++---------- src/hmac.rs | 51 ++++++++-------------------------- src/lib.rs | 15 ++++------ src/ripemd160.rs | 13 +-------- src/serde_macros.rs | 7 ++--- src/sha1.rs | 13 +-------- src/sha256.rs | 24 ++-------------- src/sha256d.rs | 17 ++---------- src/sha256t.rs | 13 +-------- src/sha512.rs | 13 +-------- src/siphash24.rs | 11 -------- src/util.rs | 13 ++------- 17 files changed, 47 insertions(+), 188 deletions(-) diff --git a/fuzz/fuzz_targets/ripemd160.rs b/fuzz/fuzz_targets/ripemd160.rs index ed7ba86..a95d7c4 100644 --- a/fuzz/fuzz_targets/ripemd160.rs +++ b/fuzz/fuzz_targets/ripemd160.rs @@ -15,7 +15,7 @@ fn do_test(data: &[u8]) { rc_engine.input(data); rc_engine.result(&mut rc_hash); - assert_eq!(&our_hash[..], &rc_hash[..]); + assert_eq!(our_hash.as_ref(), rc_hash.as_ref()); } #[cfg(feature = "honggfuzz")] diff --git a/fuzz/fuzz_targets/sha1.rs b/fuzz/fuzz_targets/sha1.rs index f2648db..68f75ea 100644 --- a/fuzz/fuzz_targets/sha1.rs +++ b/fuzz/fuzz_targets/sha1.rs @@ -15,7 +15,7 @@ fn do_test(data: &[u8]) { rc_sha1.input(data); rc_sha1.result(&mut rc_hash); - assert_eq!(&our_hash[..], &rc_hash[..]); + assert_eq!(our_hash.as_ref(), rc_hash.as_ref()); } #[cfg(feature = "honggfuzz")] diff --git a/fuzz/fuzz_targets/sha256.rs b/fuzz/fuzz_targets/sha256.rs index 898002b..485af58 100644 --- a/fuzz/fuzz_targets/sha256.rs +++ b/fuzz/fuzz_targets/sha256.rs @@ -15,7 +15,7 @@ fn do_test(data: &[u8]) { rc_engine.input(data); rc_engine.result(&mut rc_hash); - assert_eq!(&our_hash[..], &rc_hash[..]); + assert_eq!(our_hash.as_ref(), rc_hash.as_ref()); } #[cfg(feature = "honggfuzz")] diff --git a/fuzz/fuzz_targets/sha512.rs b/fuzz/fuzz_targets/sha512.rs index 88a0b29..d388120 100644 --- a/fuzz/fuzz_targets/sha512.rs +++ b/fuzz/fuzz_targets/sha512.rs @@ -15,7 +15,7 @@ fn do_test(data: &[u8]) { rc_engine.input(data); rc_engine.result(&mut rc_hash); - assert_eq!(&our_hash[..], &rc_hash[..]); + assert_eq!(our_hash.as_ref(), rc_hash.as_ref()); } #[cfg(feature = "honggfuzz")] diff --git a/src/cmp.rs b/src/cmp.rs index 3fe1df7..9ddbdee 100644 --- a/src/cmp.rs +++ b/src/cmp.rs @@ -91,7 +91,7 @@ mod benches { let hash_a = sha256::Hash::hash(&[0; 1]); let hash_b = sha256::Hash::hash(&[1; 1]); bh.iter(|| { - fixed_time_eq(&hash_a[..], &hash_b[..]) + fixed_time_eq(hash_a.as_ref(), hash_b.as_ref()) }) } @@ -100,7 +100,7 @@ mod benches { let hash_a = sha256::Hash::hash(&[0; 1]); let hash_b = sha256::Hash::hash(&[1; 1]); bh.iter(|| { - &hash_a[..] == &hash_b[..] + hash_a.as_ref() == hash_b.as_ref() }) } @@ -109,7 +109,7 @@ mod benches { let hash_a = sha256::Hash::hash(&[0; 1]); let hash_b = sha256::Hash::hash(&[0; 1]); bh.iter(|| { - fixed_time_eq(&hash_a[..], &hash_b[..]) + fixed_time_eq(hash_a.as_ref(), hash_b.as_ref()) }) } @@ -118,7 +118,7 @@ mod benches { let hash_a = sha256::Hash::hash(&[0; 1]); let hash_b = sha256::Hash::hash(&[0; 1]); bh.iter(|| { - &hash_a[..] == &hash_b[..] + hash_a.as_ref() == hash_b.as_ref() }) } @@ -127,7 +127,7 @@ mod benches { let hash_a = sha512::Hash::hash(&[0; 1]); let hash_b = sha512::Hash::hash(&[1; 1]); bh.iter(|| { - fixed_time_eq(&hash_a[..], &hash_b[..]) + fixed_time_eq(hash_a.as_ref(), hash_b.as_ref()) }) } @@ -136,7 +136,7 @@ mod benches { let hash_a = sha512::Hash::hash(&[0; 1]); let hash_b = sha512::Hash::hash(&[1; 1]); bh.iter(|| { - &hash_a[..] == &hash_b[..] + hash_a.as_ref() == hash_b.as_ref() }) } @@ -145,7 +145,7 @@ mod benches { let hash_a = sha512::Hash::hash(&[0; 1]); let hash_b = sha512::Hash::hash(&[0; 1]); bh.iter(|| { - fixed_time_eq(&hash_a[..], &hash_b[..]) + fixed_time_eq(hash_a.as_ref(), hash_b.as_ref()) }) } @@ -154,7 +154,7 @@ mod benches { let hash_a = sha512::Hash::hash(&[0; 1]); let hash_b = sha512::Hash::hash(&[0; 1]); bh.iter(|| { - &hash_a[..] == &hash_b[..] + hash_a.as_ref() == hash_b.as_ref() }) } } diff --git a/src/hash160.rs b/src/hash160.rs index 0e15f03..acac9cb 100644 --- a/src/hash160.rs +++ b/src/hash160.rs @@ -21,8 +21,6 @@ //! use core::str; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, hex, ripemd160, sha256}; @@ -39,15 +37,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Hash { type Err = hex::Error; fn from_str(s: &str) -> Result { @@ -65,10 +54,10 @@ impl crate::Hash for Hash { fn from_engine(e: sha256::HashEngine) -> Hash { let sha2 = sha256::Hash::from_engine(e); - let rmd = ripemd160::Hash::hash(&sha2[..]); + let rmd = ripemd160::Hash::hash(sha2.as_ref()); let mut ret = [0; 20]; - ret.copy_from_slice(&rmd[..]); + ret.copy_from_slice(rmd.as_ref()); Hash(ret) } @@ -141,9 +130,9 @@ mod tests { for test in tests { // Hash through high-level API, check hex encoding/decoding - let hash = hash160::Hash::hash(&test.input[..]); + let hash = hash160::Hash::hash(test.input.as_ref()); assert_eq!(hash, hash160::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte @@ -153,7 +142,7 @@ mod tests { } let manual_hash = Hash::from_engine(engine); assert_eq!(hash, manual_hash); - assert_eq!(hash.into_inner()[..].as_ref(), test.output.as_slice()); + assert_eq!(hash.into_inner().as_ref(), test.output.as_slice()); } } diff --git a/src/hmac.rs b/src/hmac.rs index 01bdc78..cbc5be6 100644 --- a/src/hmac.rs +++ b/src/hmac.rs @@ -20,7 +20,7 @@ //! Hash-based Message Authentication Code (HMAC). //! -use core::{borrow, fmt, ops, str}; +use core::{borrow, convert, fmt, str}; #[cfg(feature = "serde")] use serde::{Serialize, Serializer, Deserialize, Deserializer}; @@ -81,10 +81,10 @@ impl HmacEngine { if key.len() > T::Engine::BLOCK_SIZE { let hash = ::hash(key); - for (b_i, b_h) in ipad.iter_mut().zip(&hash[..]) { + for (b_i, b_h) in ipad.iter_mut().zip(hash.as_ref()) { *b_i ^= *b_h; } - for (b_o, b_h) in opad.iter_mut().zip(&hash[..]) { + for (b_o, b_h) in opad.iter_mut().zip(hash.as_ref()) { *b_o ^= *b_h; } } else { @@ -149,44 +149,15 @@ impl fmt::LowerHex for Hmac { } } -impl ops::Index for Hmac { - type Output = u8; - fn index(&self, index: usize) -> &u8 { - &self.0[index] - } -} - -impl ops::Index> for Hmac { - type Output = [u8]; - fn index(&self, index: ops::Range) -> &[u8] { - &self.0[index] - } -} - -impl ops::Index> for Hmac { - type Output = [u8]; - fn index(&self, index: ops::RangeFrom) -> &[u8] { - &self.0[index] - } -} - -impl ops::Index> for Hmac { - type Output = [u8]; - fn index(&self, index: ops::RangeTo) -> &[u8] { - &self.0[index] - } -} - -impl ops::Index for Hmac { - type Output = [u8]; - fn index(&self, index: ops::RangeFull) -> &[u8] { - &self.0[index] +impl borrow::Borrow<[u8]> for Hmac { + fn borrow(&self) -> &[u8] { + self.0.borrow() } } -impl borrow::Borrow<[u8]> for Hmac { - fn borrow(&self) -> &[u8] { - &self[..] +impl convert::AsRef<[u8]> for Hmac { + fn as_ref(&self) -> &[u8] { + self.0.as_ref() } } @@ -196,7 +167,7 @@ impl Hash for Hmac { fn from_engine(mut e: HmacEngine) -> Hmac { let ihash = T::from_engine(e.iengine); - e.oengine.input(&ihash[..]); + e.oengine.input(ihash.as_ref()); let ohash = T::from_engine(e.oengine); Hmac(ohash) } @@ -364,7 +335,7 @@ mod tests { let mut engine = HmacEngine::::new(&test.key); engine.input(&test.input); let hash = Hmac::::from_engine(engine); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(hash.into_inner()[..].as_ref(), test.output.as_slice()); } } diff --git a/src/lib.rs b/src/lib.rs index c2e0ec3..9e6d03f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -131,7 +131,7 @@ pub mod siphash24; pub mod sha512; pub mod cmp; -use core::{borrow, fmt, hash, ops}; +use core::{borrow, convert, fmt, hash}; pub use hmac::{Hmac, HmacEngine}; pub use error::Error; @@ -156,14 +156,9 @@ pub trait HashEngine: Clone + Default { } /// Trait which applies to hashes of all types. -pub trait Hash: Copy + Clone + PartialEq + Eq + PartialOrd + Ord + - hash::Hash + fmt::Debug + fmt::Display + fmt::LowerHex + - ops::Index + - ops::Index, Output = [u8]> + - ops::Index, Output = [u8]> + - ops::Index, Output = [u8]> + - ops::Index + - borrow::Borrow<[u8]> +pub trait Hash: Copy + Clone + PartialEq + Eq + PartialOrd + Ord + + hash::Hash + fmt::Debug + fmt::Display + fmt::LowerHex + + borrow::Borrow<[u8]> + convert::AsRef<[u8]> { /// A hashing engine which bytes can be serialized into. It is expected /// to implement the `io::Write` trait, and to never return errors under @@ -227,7 +222,7 @@ mod tests { fn convert_newtypes() { let h1 = TestNewtype::hash(&[]); let h2: TestNewtype2 = h1.as_hash().into(); - assert_eq!(&h1[..], &h2[..]); + assert_eq!(h1.as_ref(), h2.as_ref()); let h = sha256d::Hash::hash(&[]); let h2: TestNewtype = h.to_string().parse().unwrap(); diff --git a/src/ripemd160.rs b/src/ripemd160.rs index 2cf88cc..a381828 100644 --- a/src/ripemd160.rs +++ b/src/ripemd160.rs @@ -22,8 +22,6 @@ use core::{cmp, str}; use core::convert::TryInto; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, HashEngine as _, hex}; @@ -88,15 +86,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Hash { type Err = hex::Error; fn from_str(s: &str) -> Result { @@ -526,7 +515,7 @@ mod tests { // Hash through high-level API, check hex encoding/decoding let hash = ripemd160::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, ripemd160::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/serde_macros.rs b/src/serde_macros.rs index 16a316a..d74afda 100644 --- a/src/serde_macros.rs +++ b/src/serde_macros.rs @@ -22,7 +22,7 @@ pub mod serde_details { use crate::Error; use core::marker::PhantomData; - use core::{fmt, ops, str}; + use core::{convert, fmt, str}; use core::str::FromStr; struct HexVisitor(PhantomData); use serde::{de, Serializer, Deserializer}; @@ -90,8 +90,7 @@ pub mod serde_details { Self: Sized + FromStr + fmt::Display - + ops::Index - + ops::Index, + + convert::AsRef<[u8]>, ::Err: fmt::Display, { /// Size, in bits, of the hash. @@ -105,7 +104,7 @@ pub mod serde_details { if s.is_human_readable() { s.collect_str(self) } else { - s.serialize_bytes(&self[..]) + s.serialize_bytes(self.as_ref()) } } diff --git a/src/sha1.rs b/src/sha1.rs index c9bc6f4..7a49a24 100644 --- a/src/sha1.rs +++ b/src/sha1.rs @@ -17,8 +17,6 @@ use core::{cmp, str}; use core::convert::TryInto; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, HashEngine as _, hex}; @@ -83,15 +81,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Hash { type Err = hex::Error; fn from_str(s: &str) -> Result { @@ -252,7 +241,7 @@ mod tests { // Hash through high-level API, check hex encoding/decoding let hash = sha1::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, sha1::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/sha256.rs b/src/sha256.rs index dd7a324..191c032 100644 --- a/src/sha256.rs +++ b/src/sha256.rs @@ -17,8 +17,6 @@ use core::{cmp, str}; use core::convert::TryInto; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, HashEngine as _, hex}; @@ -90,15 +88,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 32); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl crate::Hash for Hash { type Engine = HashEngine; type Inner = [u8; 32]; @@ -171,15 +160,6 @@ hex_fmt_impl!(Midstate); serde_impl!(Midstate, 32); borrow_slice_impl!(Midstate); -impl> Index for Midstate { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Midstate { type Err = hex::Error; fn from_str(s: &str) -> Result { @@ -259,7 +239,7 @@ impl HashEngine { assert!(length % BLOCK_SIZE == 0, "length is no multiple of the block size"); let mut ret = [0; 8]; - for (ret_val, midstate_bytes) in ret.iter_mut().zip(midstate[..].chunks_exact(4)) { + for (ret_val, midstate_bytes) in ret.iter_mut().zip(midstate.as_ref().chunks_exact(4)) { *ret_val = u32::from_be_bytes(midstate_bytes.try_into().expect("4 byte slice")); } @@ -421,7 +401,7 @@ mod tests { // Hash through high-level API, check hex encoding/decoding let hash = sha256::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, sha256::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/sha256d.rs b/src/sha256d.rs index 2e7909d..3073395 100644 --- a/src/sha256d.rs +++ b/src/sha256d.rs @@ -16,8 +16,6 @@ //! use core::str; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, hex, sha256}; @@ -34,15 +32,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 32); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Hash { type Err = hex::Error; fn from_str(s: &str) -> Result { @@ -60,10 +49,10 @@ impl crate::Hash for Hash { fn from_engine(e: sha256::HashEngine) -> Hash { let sha2 = sha256::Hash::from_engine(e); - let sha2d = sha256::Hash::hash(&sha2[..]); + let sha2d = sha256::Hash::hash(sha2.as_ref()); let mut ret = [0; 32]; - ret.copy_from_slice(&sha2d[..]); + ret.copy_from_slice(sha2d.as_ref()); Hash(ret) } @@ -131,7 +120,7 @@ mod tests { // Hash through high-level API, check hex encoding/decoding let hash = sha256d::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, sha256d::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/sha256t.rs b/src/sha256t.rs index cfac310..37c782a 100644 --- a/src/sha256t.rs +++ b/src/sha256t.rs @@ -18,8 +18,6 @@ use core::{cmp, str}; #[cfg(feature = "serde")] use core::fmt; use core::marker::PhantomData; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, hex, sha256}; #[cfg(feature="serde")] use crate::Hash as _; @@ -83,15 +81,6 @@ impl str::FromStr for Hash { hex_fmt_impl!(Hash, T:Tag); borrow_slice_impl!(Hash, T:Tag); -impl, T: Tag> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl crate::Hash for Hash { type Engine = sha256::HashEngine; type Inner = [u8; 32]; @@ -170,7 +159,7 @@ impl serde::Serialize for Hash { if s.is_human_readable() { s.collect_str(self) } else { - s.serialize_bytes(&self[..]) + s.serialize_bytes(self.as_ref()) } } } diff --git a/src/sha512.rs b/src/sha512.rs index aad0ca9..476f290 100644 --- a/src/sha512.rs +++ b/src/sha512.rs @@ -22,8 +22,6 @@ use core::{cmp, hash, str}; use core::convert::TryInto; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, HashEngine as _, hex}; @@ -139,15 +137,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 64); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl crate::Hash for Hash { type Engine = HashEngine; type Inner = [u8; 64]; @@ -411,7 +400,7 @@ mod tests { // Hash through high-level API, check hex encoding/decoding let hash = sha512::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, sha512::Hash::from_hex(test.output_str).expect("parse hex")); - assert_eq!(&hash[..], &test.output[..]); + assert_eq!(hash.as_ref(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/siphash24.rs b/src/siphash24.rs index eaa8c68..5a0c4bb 100644 --- a/src/siphash24.rs +++ b/src/siphash24.rs @@ -21,8 +21,6 @@ //! use core::{cmp, mem, ptr, str}; -use core::ops::Index; -use core::slice::SliceIndex; use crate::{Error, Hash as _, HashEngine as _, hex}; @@ -207,15 +205,6 @@ hex_fmt_impl!(Hash); serde_impl!(Hash, 8); borrow_slice_impl!(Hash); -impl> Index for Hash { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } -} - impl str::FromStr for Hash { type Err = hex::Error; fn from_str(s: &str) -> Result { diff --git a/src/util.rs b/src/util.rs index 85a6615..75a5157 100644 --- a/src/util.rs +++ b/src/util.rs @@ -58,13 +58,13 @@ macro_rules! borrow_slice_impl( ($ty:ident, $($gen:ident: $gent:ident),*) => ( impl<$($gen: $gent),*> $crate::_export::_core::borrow::Borrow<[u8]> for $ty<$($gen),*> { fn borrow(&self) -> &[u8] { - &self[..] + self.0.borrow() } } impl<$($gen: $gent),*> $crate::_export::_core::convert::AsRef<[u8]> for $ty<$($gen),*> { fn as_ref(&self) -> &[u8] { - &self[..] + self.0.as_ref() } } ) @@ -191,15 +191,6 @@ macro_rules! hash_newtype { $crate::hex::FromHex::from_hex(s) } } - - impl> $crate::_export::_core::ops::Index for $newtype { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - &self.0[index] - } - } }; } From 07fac40fc733b2fb324d4e7344cca6d2596c1710 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 8 Sep 2022 10:36:05 +1000 Subject: [PATCH 3/4] Add an `as_bytes` method to hash types We now implement `AsRef` for hash types, sometimes usage of `as_ref` may required type annotations. For such cases we can provide an alternate way to get the underlying bytes to make the API more ergonomic. Add a method `as_bytes` for getting a reference to the inner byte array. Add for new types created by `hash_newtype` also. --- src/hash160.rs | 1 + src/ripemd160.rs | 2 ++ src/sha1.rs | 1 + src/sha256.rs | 2 ++ src/sha256d.rs | 1 + src/sha256t.rs | 1 + src/sha512.rs | 1 + src/siphash24.rs | 1 + src/util.rs | 21 +++++++++++++++++++++ 9 files changed, 31 insertions(+) diff --git a/src/hash160.rs b/src/hash160.rs index acac9cb..d932435 100644 --- a/src/hash160.rs +++ b/src/hash160.rs @@ -36,6 +36,7 @@ pub struct Hash( hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 20); impl str::FromStr for Hash { type Err = hex::Error; diff --git a/src/ripemd160.rs b/src/ripemd160.rs index a381828..4df4cc3 100644 --- a/src/ripemd160.rs +++ b/src/ripemd160.rs @@ -85,6 +85,7 @@ pub struct Hash( hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 20); impl str::FromStr for Hash { type Err = hex::Error; @@ -516,6 +517,7 @@ mod tests { let hash = ripemd160::Hash::hash(&test.input.as_bytes()); assert_eq!(hash, ripemd160::Hash::from_hex(test.output_str).expect("parse hex")); assert_eq!(hash.as_ref(), &test.output[..]); + assert_eq!(hash.as_bytes(), &test.output[..]); assert_eq!(&hash.to_hex(), &test.output_str); // Hash through engine, checking that we can input byte by byte diff --git a/src/sha1.rs b/src/sha1.rs index 7a49a24..b6ddc5e 100644 --- a/src/sha1.rs +++ b/src/sha1.rs @@ -80,6 +80,7 @@ pub struct Hash( hex_fmt_impl!(Hash); serde_impl!(Hash, 20); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 20); impl str::FromStr for Hash { type Err = hex::Error; diff --git a/src/sha256.rs b/src/sha256.rs index 191c032..2d5bbc1 100644 --- a/src/sha256.rs +++ b/src/sha256.rs @@ -87,6 +87,7 @@ impl str::FromStr for Hash { hex_fmt_impl!(Hash); serde_impl!(Hash, 32); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 32); impl crate::Hash for Hash { type Engine = HashEngine; @@ -159,6 +160,7 @@ pub struct Midstate(pub [u8; 32]); hex_fmt_impl!(Midstate); serde_impl!(Midstate, 32); borrow_slice_impl!(Midstate); +as_bytes_impl!(Midstate, 32); impl str::FromStr for Midstate { type Err = hex::Error; diff --git a/src/sha256d.rs b/src/sha256d.rs index 3073395..02d4395 100644 --- a/src/sha256d.rs +++ b/src/sha256d.rs @@ -31,6 +31,7 @@ pub struct Hash( hex_fmt_impl!(Hash); serde_impl!(Hash, 32); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 32); impl str::FromStr for Hash { type Err = hex::Error; diff --git a/src/sha256t.rs b/src/sha256t.rs index 37c782a..fc37c93 100644 --- a/src/sha256t.rs +++ b/src/sha256t.rs @@ -80,6 +80,7 @@ impl str::FromStr for Hash { hex_fmt_impl!(Hash, T:Tag); borrow_slice_impl!(Hash, T:Tag); +as_bytes_impl!(Hash, 32, T:Tag); impl crate::Hash for Hash { type Engine = sha256::HashEngine; diff --git a/src/sha512.rs b/src/sha512.rs index 476f290..7e7a429 100644 --- a/src/sha512.rs +++ b/src/sha512.rs @@ -136,6 +136,7 @@ impl str::FromStr for Hash { hex_fmt_impl!(Hash); serde_impl!(Hash, 64); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 64); impl crate::Hash for Hash { type Engine = HashEngine; diff --git a/src/siphash24.rs b/src/siphash24.rs index 5a0c4bb..aabde6e 100644 --- a/src/siphash24.rs +++ b/src/siphash24.rs @@ -204,6 +204,7 @@ pub struct Hash( hex_fmt_impl!(Hash); serde_impl!(Hash, 8); borrow_slice_impl!(Hash); +as_bytes_impl!(Hash, 8); impl str::FromStr for Hash { type Err = hex::Error; diff --git a/src/util.rs b/src/util.rs index 75a5157..b8725a2 100644 --- a/src/util.rs +++ b/src/util.rs @@ -70,6 +70,22 @@ macro_rules! borrow_slice_impl( ) ); +/// Adds a method `as_bytes` to a given type `$ty`. +#[macro_export] +macro_rules! as_bytes_impl( + ($ty:ident, $len:expr) => ( + $crate::as_bytes_impl!($ty, $len, ); + ); + ($ty:ident, $len:expr, $($gen:ident: $gent:ident),*) => ( + impl<$($gen: $gent),*> $ty<$($gen),*> { + /// Returns `self` as a byte array reference. + pub fn as_bytes(&self) -> &[u8; $len] { + &self.0 + } + } + ); +); + macro_rules! engine_input_impl( () => ( #[cfg(not(fuzzing))] @@ -128,6 +144,11 @@ macro_rules! hash_newtype { // Hashes implement Copy so don't need into_hash. self.0 } + + /// Returns `self` as a byte array reference. + pub fn as_bytes(&self) -> &[u8; $len] { + &self.0.as_bytes() + } } impl $crate::_export::_core::convert::From<$hash> for $newtype { From be8b9f1cf496beccbf493ec0ee756f535653c9bc Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Thu, 8 Sep 2022 10:45:54 +1000 Subject: [PATCH 4/4] Add method as_mut_bytes We implement `as_bytes` on hash types; in order to be able to modify a hash it would be useful to iterate the inner byte array mutable. Add a `as_mut_bytes` method to all hash types and also to any hash created with `hash_newtype`. --- src/util.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/util.rs b/src/util.rs index b8725a2..7857009 100644 --- a/src/util.rs +++ b/src/util.rs @@ -70,7 +70,7 @@ macro_rules! borrow_slice_impl( ) ); -/// Adds a method `as_bytes` to a given type `$ty`. +/// Adds methods `as_bytes` and `as_mut_bytes` to a given type `$ty`. #[macro_export] macro_rules! as_bytes_impl( ($ty:ident, $len:expr) => ( @@ -82,6 +82,11 @@ macro_rules! as_bytes_impl( pub fn as_bytes(&self) -> &[u8; $len] { &self.0 } + + /// Returns `self` as a mutable byte array reference. + pub fn as_mut_bytes(&mut self) -> &mut [u8; $len] { + &mut self.0 + } } ); ); @@ -149,6 +154,11 @@ macro_rules! hash_newtype { pub fn as_bytes(&self) -> &[u8; $len] { &self.0.as_bytes() } + + /// Returns `self` as a mutable byte array reference. + pub fn as_mut_bytes(&mut self) -> &mut [u8; $len] { + self.0.as_mut_bytes() + } } impl $crate::_export::_core::convert::From<$hash> for $newtype { @@ -279,4 +289,16 @@ mod test { let got = format!("{:#x}", TestHash::all_zeros()); assert_eq!(got, want) } + + #[test] + fn as_mut_bytes() { + let mut hash = TestHash::all_zeros(); + for b in hash.as_mut_bytes().iter_mut() { + *b = 0xff; + } + + let got = format!("{:#x}", hash); + let want = "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; + assert_eq!(got, want) + } }