aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEduardo Leegwater Simões <[email protected]>2023-04-12 11:26:53 +0200
committerJack O'Connor <[email protected]>2023-05-01 03:23:16 -0500
commit8176a2202dfd3556949cbdab2b669a011231c63b (patch)
treeb4010c6addc81a361e505c2078b145885775e096 /src
parentce48d79f38a8862b749ec6cc12ba5d1da69ab131 (diff)
add `from_bytes` for conversions from `[u8; 32]`
The function is `const`, so it is fundamentally different from the `From` trait implementation by allowing compile-time instantiation of a `Hash`.
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs22
-rw-r--r--src/test.rs25
2 files changed, 39 insertions, 8 deletions
diff --git a/src/lib.rs b/src/lib.rs
index aa61672..f1775b9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -176,13 +176,13 @@ fn counter_high(counter: u64) -> u32 {
/// An output of the default size, 32 bytes, which provides constant-time
/// equality checking.
///
-/// `Hash` implements [`From`] and [`Into`] for `[u8; 32]`, and it provides an
-/// explicit [`as_bytes`] method returning `&[u8; 32]`. However, byte arrays
-/// and slices don't provide constant-time equality checking, which is often a
-/// security requirement in software that handles private data. `Hash` doesn't
-/// implement [`Deref`] or [`AsRef`], to avoid situations where a type
-/// conversion happens implicitly and the constant-time property is
-/// accidentally lost.
+/// `Hash` implements [`From`] and [`Into`] for `[u8; 32]`, and it provides
+/// explicit [`from_bytes`], and [`as_bytes`] for conversions between itself
+/// and `[u8; 32]`. However, byte arrays and slices don't provide constant-time
+/// equality checking, which is often a security requirement in software that
+/// handles private data. `Hash` doesn't implement [`Deref`] or [`AsRef`], to
+/// avoid situations where a type conversion happens implicitly and the
+/// constant-time property is accidentally lost.
///
/// `Hash` provides the [`to_hex`] and [`from_hex`] methods for converting to
/// and from hexadecimal. It also implements [`Display`] and [`FromStr`].
@@ -190,6 +190,7 @@ fn counter_high(counter: u64) -> u32 {
/// [`From`]: https://doc.rust-lang.org/std/convert/trait.From.html
/// [`Into`]: https://doc.rust-lang.org/std/convert/trait.Into.html
/// [`as_bytes`]: #method.as_bytes
+/// [`from_bytes`]: #method.from_bytes
/// [`Deref`]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html
/// [`AsRef`]: https://doc.rust-lang.org/std/convert/trait.AsRef.html
/// [`to_hex`]: #method.to_hex
@@ -208,6 +209,11 @@ impl Hash {
&self.0
}
+ /// Create a `Hash` from its raw bytes representation.
+ pub const fn from_bytes(bytes: [u8; OUT_LEN]) -> Self {
+ Self(bytes)
+ }
+
/// Encode a `Hash` in lowercase hexadecimal.
///
/// The returned [`ArrayString`] is a fixed size and doesn't allocate memory
@@ -259,7 +265,7 @@ impl Hash {
impl From<[u8; OUT_LEN]> for Hash {
#[inline]
fn from(bytes: [u8; OUT_LEN]) -> Self {
- Self(bytes)
+ Self::from_bytes(bytes)
}
}
diff --git a/src/test.rs b/src/test.rs
index 4b6272c..f5b3462 100644
--- a/src/test.rs
+++ b/src/test.rs
@@ -603,3 +603,28 @@ fn test_issue_206_windows_sse2() {
assert_eq!(crate::Hasher::new().update(input).finalize(), expected_hash);
}
}
+
+#[test]
+fn test_hash_conversions() {
+ let bytes1 = [42; 32];
+ let hash1: crate::Hash = bytes1.into();
+ let bytes2: [u8; 32] = hash1.into();
+ assert_eq!(bytes1, bytes2);
+
+ let bytes3 = *hash1.as_bytes();
+ assert_eq!(bytes1, bytes3);
+
+ let hash2 = crate::Hash::from_bytes(bytes1);
+ assert_eq!(hash1, hash2);
+
+ let hex = hash1.to_hex();
+ let hash3 = crate::Hash::from_hex(hex.as_bytes()).unwrap();
+ assert_eq!(hash1, hash3);
+}
+
+#[test]
+const fn test_hash_const_conversions() {
+ let bytes = [42; 32];
+ let hash = crate::Hash::from_bytes(bytes);
+ _ = hash.as_bytes();
+}