1+ //! # Hash Module
2+ //! This module provides a struct meant for containing Hashes (Kecack256 or Sha256).
3+
4+ use core:: ops:: { Deref , DerefMut } ;
5+ use rustc_hex:: { FromHex , FromHexError } ;
6+ use arrayvec:: ArrayVec ;
7+ use crate :: serde:: { Serialize , Deserialize } ;
8+
9+ /// This struct is basically a wrapper over `[u8; 32]`, and is meant to be returned from whatever hashing functions we use.
10+ /// `#[repr(C)]` is a Rust feature which makes the struct be aligned just like C structs.
11+ /// See [`Repr(C)`][https://doc.rust-lang.org/nomicon/other-reprs.html]
12+ #[ derive( Serialize , Deserialize , Clone , Copy , Debug , PartialEq , PartialOrd , Eq , Ord , Hash , Default ) ]
13+ #[ serde( crate = "crate::serde" ) ]
14+ #[ repr( C ) ]
15+ pub struct Hash256 ( [ u8 ; 32 ] ) ;
16+
17+
18+ impl Hash256 {
19+ /// This method exposes rust's built in [`copy_from_slice`][https://doc.rust-lang.org/std/primitive.slice.html#method.copy_from_slice]
20+ /// Copies the elements from `src` into `self`.
21+ ///
22+ /// The length of `src` must be the same as `self`.
23+ ///
24+ /// # Panics
25+ ///
26+ /// This function will panic if the two slices have different lengths.
27+ ///
28+ /// This might not be needed since we implement `Deref` and `DerefMut` for the inner array.
29+ pub fn copy_from_slice ( & mut self , src : & [ u8 ] ) {
30+ self . 0 . copy_from_slice ( src)
31+ }
32+
33+ /// This function converts a hex string into `Hash256` type.
34+ /// the hex must not contain `0x` (as is usually the case in hexs in rust)
35+ /// if the hex length isn't 64 (which will be converted into the 32 bytes) it will return an error.
36+ pub fn from_hex ( hex : & str ) -> Result < Self , FromHexError > {
37+ if hex. len ( ) != 64 {
38+ return Err ( FromHexError :: InvalidHexLength ) ;
39+ }
40+ let hex_vec: ArrayVec < [ u8 ; 32 ] > = hex. from_hex ( ) ?;
41+ let mut result = Self :: default ( ) ;
42+ result. copy_from_slice ( & hex_vec) ;
43+ Ok ( result)
44+ }
45+
46+ /// Checks if the struct contains only zeroes or not.
47+ pub fn is_zero ( & self ) -> bool {
48+ self . 0 == [ 0u8 ; 32 ]
49+ }
50+ }
51+
52+
53+ impl From < [ u8 ; 32 ] > for Hash256 {
54+ fn from ( arr : [ u8 ; 32 ] ) -> Self {
55+ Hash256 ( arr)
56+ }
57+ }
58+
59+ impl Into < [ u8 ; 32 ] > for Hash256 {
60+ fn into ( self ) -> [ u8 ; 32 ] {
61+ self . 0
62+ }
63+ }
64+
65+ impl Deref for Hash256 {
66+ type Target = [ u8 ; 32 ] ;
67+
68+ fn deref ( & self ) -> & [ u8 ; 32 ] {
69+ & self . 0
70+ }
71+ }
72+
73+ impl DerefMut for Hash256 {
74+ fn deref_mut ( & mut self ) -> & mut [ u8 ; 32 ] {
75+ & mut self . 0
76+ }
77+ }
78+
79+ impl AsRef < [ u8 ] > for Hash256 {
80+ fn as_ref ( & self ) -> & [ u8 ] {
81+ & self . 0
82+ }
83+ }
84+
85+ impl AsMut < [ u8 ] > for Hash256 {
86+ fn as_mut ( & mut self ) -> & mut [ u8 ] {
87+ & mut self . 0
88+ }
89+ }
90+
91+ #[ cfg( test) ]
92+ mod test {
93+ use super :: Hash256 ;
94+ #[ test]
95+ fn test_hex_succeed ( ) {
96+ let a = "0101010101010101010101010101010101010101010101010101010101010101" ;
97+ Hash256 :: from_hex ( & a) . unwrap ( ) ;
98+ }
99+
100+ #[ should_panic]
101+ #[ test]
102+ fn test_hex_long ( ) {
103+ let a = "02020202020202020202020202020202020202020202020202020202020202020202024444020202020202" ;
104+ Hash256 :: from_hex ( & a) . unwrap ( ) ;
105+ }
106+ }
0 commit comments