11use serde:: { Deserialize , Deserializer , Serialize , Serializer } ;
22use std:: { fmt, ops:: Deref , str:: FromStr } ;
33
4- /// Data that is a cryptographic hash of `BYTES` long.
5- ///
6- /// This is a generic wrapper around a fixed-size byte array that provides:
7- /// - Hexadecimal serialization/deserialization
8- /// - CBOR encoding/decoding via minicbor
9- /// - Type-safe conversions from various byte representations
10- /// - Display and debug formatting
4+ /// data that is a cryptographic [`struct@Hash`] of `BYTES` long.
115///
126/// # Common Hash Sizes in Cardano
137///
148/// - **32 bytes**: Block hashes, transaction hashes
159/// - **28 bytes**: Script hashes, address key hashes
1610///
17- /// # Examples
18- ///
19- /// ```ignore
20- /// use your_crate::Hash;
21- ///
22- /// // Parse from hex string
23- /// let hash: Hash<32> = "0d8d00cdd4657ac84d82f0a56067634a7adfdf43da41cb534bcaa45060973d21"
24- /// .parse()
25- /// .unwrap();
26- ///
27- /// // Create from byte array
28- /// let bytes = [0u8; 28];
29- /// let hash = Hash::new(bytes);
30- ///
31- /// // Convert to hex string
32- /// let hex_string = hash.to_string();
3311/// ```
3412#[ derive( Clone , Copy , PartialEq , Eq , PartialOrd , Ord , Hash ) ]
3513pub struct Hash < const BYTES : usize > ( [ u8 ; BYTES ] ) ;
@@ -61,48 +39,16 @@ impl<'de, const BYTES: usize> Deserialize<'de> for Hash<BYTES> {
6139}
6240
6341impl < const BYTES : usize > Hash < BYTES > {
64- /// Creates a new hash from a byte array.
65- ///
66- /// This is a const function, allowing hashes to be created at compile time.
67- ///
68- /// # Examples
69- ///
70- /// ```ignore
71- /// use your_crate::Hash;
72- ///
73- /// const MY_HASH: Hash<32> = Hash::new([0u8; 32]);
74- /// ```
7542 #[ inline]
7643 pub const fn new ( bytes : [ u8 ; BYTES ] ) -> Self {
7744 Self ( bytes)
7845 }
7946
80- /// Converts the hash to a `Vec<u8>`.
81- ///
82- /// # Examples
83- ///
84- /// ```ignore
85- /// use your_crate::Hash;
86- ///
87- /// let hash = Hash::new([1u8; 28]);
88- /// let vec = hash.to_vec();
89- /// assert_eq!(vec.len(), 28);
90- /// ```
9147 #[ inline]
9248 pub fn to_vec ( & self ) -> Vec < u8 > {
9349 self . 0 . to_vec ( )
9450 }
9551
96- /// Consumes the hash and returns the inner byte array.
97- ///
98- /// # Examples
99- ///
100- /// ```ignore
101- /// use your_crate::Hash;
102- ///
103- /// let hash = Hash::new([1u8; 28]);
104- /// let bytes: [u8; 28] = hash.into_inner();
105- /// ```
10652 #[ inline]
10753 pub fn into_inner ( self ) -> [ u8 ; BYTES ] {
10854 self . 0
@@ -119,11 +65,6 @@ impl<const BYTES: usize> From<[u8; BYTES]> for Hash<BYTES> {
11965impl < const BYTES : usize > TryFrom < & [ u8 ] > for Hash < BYTES > {
12066 type Error = std:: array:: TryFromSliceError ;
12167
122- /// Attempts to create a hash from a byte slice.
123- ///
124- /// # Errors
125- ///
126- /// Returns an error if the slice length does not match `BYTES`.
12768 fn try_from ( value : & [ u8 ] ) -> Result < Self , Self :: Error > {
12869 let hash: [ u8 ; BYTES ] = value. try_into ( ) ?;
12970 Ok ( Self :: new ( hash) )
@@ -133,25 +74,19 @@ impl<const BYTES: usize> TryFrom<&[u8]> for Hash<BYTES> {
13374impl < const BYTES : usize > TryFrom < Vec < u8 > > for Hash < BYTES > {
13475 type Error = Vec < u8 > ;
13576
136- /// Attempts to create a hash from a `Vec<u8>`.
137- ///
138- /// # Errors
139- ///
140- /// Returns the original vector if its length does not match `BYTES`.
14177 fn try_from ( value : Vec < u8 > ) -> Result < Self , Self :: Error > {
142- let hash: [ u8 ; BYTES ] = value. try_into ( ) ?;
143- Ok ( Self :: new ( hash) )
78+ Self :: try_from ( value. as_slice ( ) ) . map_err ( |_| value)
14479 }
14580}
14681
147- impl < const BYTES : usize > From < Hash < BYTES > > for Vec < u8 > {
148- fn from ( hash : Hash < BYTES > ) -> Self {
82+ impl < const BYTES : usize > From < & Hash < BYTES > > for Vec < u8 > {
83+ fn from ( hash : & Hash < BYTES > ) -> Self {
14984 hash. 0 . to_vec ( )
15085 }
15186}
15287
153- impl < const BYTES : usize > From < Hash < BYTES > > for [ u8 ; BYTES ] {
154- fn from ( hash : Hash < BYTES > ) -> Self {
88+ impl < const BYTES : usize > From < & Hash < BYTES > > for [ u8 ; BYTES ] {
89+ fn from ( hash : & Hash < BYTES > ) -> Self {
15590 hash. 0
15691 }
15792}
@@ -185,7 +120,6 @@ impl<const BYTES: usize> fmt::Debug for Hash<BYTES> {
185120}
186121
187122impl < const BYTES : usize > fmt:: Display for Hash < BYTES > {
188- /// Formats the hash as a lowercase hexadecimal string.
189123 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
190124 f. write_str ( & hex:: encode ( self ) )
191125 }
@@ -194,23 +128,6 @@ impl<const BYTES: usize> fmt::Display for Hash<BYTES> {
194128impl < const BYTES : usize > FromStr for Hash < BYTES > {
195129 type Err = hex:: FromHexError ;
196130
197- /// Parses a hash from a hexadecimal string.
198- ///
199- /// # Errors
200- ///
201- /// Returns an error if:
202- /// - The string is not valid hexadecimal
203- /// - The decoded bytes do not match the expected length `BYTES`
204- ///
205- /// # Examples
206- ///
207- /// ```ignore
208- /// use your_crate::Hash;
209- ///
210- /// let hash: Hash<28> = "276fd18711931e2c0e21430192dbeac0e458093cd9d1fcd7210f64b3"
211- /// .parse()
212- /// .unwrap();
213- /// ```
214131 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
215132 let mut bytes = [ 0 ; BYTES ] ;
216133 hex:: decode_to_slice ( s, & mut bytes) ?;
@@ -221,11 +138,6 @@ impl<const BYTES: usize> FromStr for Hash<BYTES> {
221138impl < const BYTES : usize > hex:: FromHex for Hash < BYTES > {
222139 type Error = hex:: FromHexError ;
223140
224- /// Decodes a hash from hexadecimal bytes.
225- ///
226- /// # Errors
227- ///
228- /// Returns an error if the decoded length does not match `BYTES`.
229141 fn from_hex < T : AsRef < [ u8 ] > > ( hex : T ) -> Result < Self , Self :: Error > {
230142 match Self :: try_from ( Vec :: < u8 > :: from_hex ( hex) ?) {
231143 Ok ( h) => Ok ( h) ,
@@ -262,14 +174,6 @@ impl<'a, C, const BYTES: usize> minicbor::Decode<'a, C> for Hash<BYTES> {
262174 }
263175}
264176
265- /// Declares a type alias for a hash with optional documentation.
266- ///
267- /// # Examples
268- ///
269- /// ```ignore
270- /// declare_hash_type!(BlockHash, 32);
271- /// declare_hash_type!(TxHash, 32);
272- /// ```
273177#[ macro_export]
274178macro_rules! declare_hash_type {
275179 ( $name: ident, $size: expr) => {
@@ -341,22 +245,26 @@ macro_rules! declare_hash_type_with_bech32 {
341245 }
342246
343247 impl TryFrom <Vec <u8 >> for $name {
344- type Error = Vec < u8 > ;
248+ type Error = anyhow :: Error ;
345249 fn try_from( vec: Vec <u8 >) -> Result <Self , Self :: Error > {
346- Ok ( Self ( Hash :: try_from( vec) ?) )
250+ Ok ( Self (
251+ Hash :: try_from( vec) . map_err( |e| anyhow:: anyhow!( "{}" , hex:: encode( e) ) ) ?,
252+ ) )
347253 }
348254 }
349255
350256 impl TryFrom <& [ u8 ] > for $name {
351- type Error = std :: array :: TryFromSliceError ;
257+ type Error = anyhow :: Error ;
352258 fn try_from( arr: & [ u8 ] ) -> Result <Self , Self :: Error > {
353- Ok ( Self ( Hash :: try_from( arr) ?) )
259+ Ok ( Self (
260+ Hash :: try_from( arr) . map_err( |e| anyhow:: anyhow!( "{}" , e) ) ?,
261+ ) )
354262 }
355263 }
356264
357265 impl AsRef <[ u8 ] > for $name {
358266 fn as_ref( & self ) -> & [ u8 ] {
359- self . 0 . as_ref( )
267+ & self . 0 . as_ref( )
360268 }
361269 }
362270
@@ -370,7 +278,7 @@ macro_rules! declare_hash_type_with_bech32 {
370278 impl std:: str :: FromStr for $name {
371279 type Err = hex:: FromHexError ;
372280 fn from_str( s: & str ) -> Result <Self , Self :: Err > {
373- Ok ( Self ( s. parse( ) ?) )
281+ Ok ( Self ( s. parse:: < Hash <$size>> ( ) ?) )
374282 }
375283 }
376284
@@ -402,14 +310,30 @@ macro_rules! declare_hash_type_with_bech32 {
402310 impl crate :: serialization:: Bech32Conversion for $name {
403311 fn to_bech32( & self ) -> Result <String , anyhow:: Error > {
404312 use crate :: serialization:: Bech32WithHrp ;
405- self . 0 . to_vec( ) . to_bech32_with_hrp( $hrp)
313+ use anyhow:: Context ;
314+
315+ self . as_ref( ) . to_bech32_with_hrp( $hrp) . with_context( || {
316+ format!(
317+ "Failed to encode {} to bech32 with HRP '{}'" ,
318+ stringify!( $name) ,
319+ $hrp
320+ )
321+ } )
406322 }
407323
408324 fn from_bech32( s: & str ) -> Result <Self , anyhow:: Error > {
409325 use crate :: serialization:: Bech32WithHrp ;
410- let v = Vec :: <u8 >:: from_bech32_with_hrp( s, $hrp) ?;
326+ use anyhow:: Context ;
327+
328+ let v = Vec :: <u8 >:: from_bech32_with_hrp( s, $hrp) . with_context( || {
329+ format!( "Failed to decode {} from bech32" , stringify!( $name) )
330+ } ) ?;
331+
411332 Self :: try_from( v) . map_err( |_| {
412- anyhow:: Error :: msg( format!( "Bad vector input to {}" , stringify!( $name) ) )
333+ anyhow:: anyhow!(
334+ "Failed to create {} from decoded bech32 data" ,
335+ stringify!( $name)
336+ )
413337 } )
414338 }
415339 }
@@ -459,7 +383,7 @@ mod tests {
459383 fn into_vec ( ) {
460384 let bytes = [ 0u8 ; 28 ] ;
461385 let hash = Hash :: new ( bytes) ;
462- let vec: Vec < u8 > = hash. into ( ) ;
386+ let vec: Vec < u8 > = hash. as_ref ( ) . into ( ) ;
463387 assert_eq ! ( vec, bytes. to_vec( ) ) ;
464388 }
465389
0 commit comments