1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use std::ops::{Deref, DerefMut};
use crate::*;

macro_rules! new_sha2 {
    ( $sid:ident, $tid:ident, $hname:ident, $tname:ident, $lid:ident, $len:expr, $str:expr, $hwhash:expr) => {
        new_hash!($hname, $tname, $len, $str);

        pub struct $sid(lib_sha2::$lid);
        impl Deref for $sid {
            type Target = lib_sha2::$lid;
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }
        impl DerefMut for $sid {
            fn deref_mut(&mut self) -> &mut Self::Target {
                &mut self.0
            }
        }

        impl Hasher for $sid {
            type HasherOutput = $hname;

            fn output_type() -> &'static HashType {
                &$tname as &HashType
            }

            fn new() -> Self {
                $sid(lib_sha2::Digest::new())
            }

            fn input(&mut self, buf: &[u8]) -> Result<(), std::io::Error> {
                Ok(lib_sha2::digest::Input::input(&mut self.0, buf))
            }

            fn result(self) -> Box<Self::HasherOutput> {
                let hash = lib_sha2::digest::FixedOutput::fixed_result(self.0);
                let mut array: [u8; $len] = [0; $len]; // This should have a default implementation
                assert!(hash.as_slice().len() == array.len());

                array.copy_from_slice(&hash);
                Box::new($hname(array))
            }
        }

        #[test]
        fn $tid() {
            let mut hasher: $sid = $sid::new();
            hasher.input(b"Hello World").unwrap();
            let hash: Box<$hname> = hasher.result();

            assert!(format!("{:?}", hash) == format!("Hash<{}, {}>", $str, $hwhash));
        }
    };
}

new_sha2!(
    Sha2_224,
    test_sha2_224,
    Hash_Sha2_224,
    HashType_Sha2_224,
    Sha224,
    28,
    "sha224",
    "c4890faffdb0105d991a461e668e276685401b02eab1ef4372795047"
);

new_sha2!(
    Sha2_256,
    test_sha2_256,
    Hash_Sha2_256,
    HashType_Sha2_256,
    Sha256,
    32,
    "sha256",
    "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e"
);
new_sha2!(
    Sha2_384,
    test_sha2_384,
    Hash_Sha2_384,
    HashType_Sha2_384,
    Sha384,
    48,
    "sha384",
    "99514329186b2f6ae4a1329e7ee6c610a729636335174ac6b740f9028396fcc803d0e93863a7c3d90f86beee782f4f3f"
);
new_sha2!(
    Sha2_512,
    test_sha2_512,
    Hash_Sha2_512,
    HashType_Sha2_512,
    Sha512,
    64,
    "sha512",
    "2c74fd17edafd80e8447b0d46741ee243b7eb74dd2149a0ab1b9246fb30382f27e853d8585719e0e67cbda0daa8f51671064615d645ae27acb15bfb1447f459b"
);