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
use std::ops::{Deref, DerefMut};
use crate::*;

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

        pub struct $sid(lib_sha3::$sid);
        impl Deref for $sid {
            type Target = lib_sha3::$sid;
            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_sha3::Digest::new())
            }

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

            fn result(self) -> Box<Self::HasherOutput> {
                let hash = lib_sha3::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();

            let htype = $tname;
            let newhash = htype.new_with_content(hash.as_slice()).unwrap();

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

new_sha3!(
    Sha3_224,
    test_sha3_224,
    Hash_Sha3_224,
    HashType_Sha3_224,
    28,
    "sha3_224",
    "8e800079a0b311788bf29353f400eff969b650a3597c91efd9aa5b38"
);
new_sha3!(
    Sha3_256,
    test_sha3_256,
    Hash_Sha3_256,
    HashType_Sha3_256,
    32,
    "sha3_256",
    "e167f68d6563d75bb25f3aa49c29ef612d41352dc00606de7cbd630bb2665f51"
);
new_sha3!(
    Sha3_384,
    test_sha3_384,
    Hash_Sha3_384,
    HashType_Sha3_384,
    48,
    "sha3_384",
    "a78ec2851e991638ce505d4a44efa606dd4056d3ab274ec6fdbac00cde16478263ef7213bad5a7db7044f58d637afdeb"
);
new_sha3!(
    Sha3_512,
    test_sha3_512,
    Hash_Sha3_512,
    HashType_Sha3_512,
    64,
    "sha3_512",
    "3d58a719c6866b0214f96b0a67b37e51a91e233ce0be126a08f35fdf4c043c6126f40139bfbc338d44eb2a03de9f7bb8eff0ac260b3629811e389a5fbee8a894"
);