1use sha2::Sha256;
33use sha2::Digest;
34use byteorder::{LittleEndian, WriteBytesExt};
35use paste::paste;
36
37pub use simple_hash_macro::Hashable;
38
39pub trait Hasher {
40 type Output;
41 fn update<D: AsRef<[u8]>>(&mut self, data: D);
42 fn finish(self) -> Self::Output;
43 fn digest<H: Hashable>(data: &H) -> Self::Output;
44}
45
46pub trait Hashable {
47 fn update<H: Hasher>(&self, h: &mut H);
48 fn digest<H: Hasher>(&self) -> <H as Hasher>::Output where Self: Sized {
49 H::digest(self)
50 }
51}
52
53impl Hasher for Sha256 {
54 type Output = [u8; 32];
55
56 fn update<D: AsRef<[u8]>>(&mut self, data: D) {
57 Digest::update(self, data);
58 }
59 fn finish(self) -> Self::Output {
60 let res = self.finalize();
61 let mut out = [0; 32];
62 for i in 0..res.len() {
63 out[i] = res[i];
64 }
65 out
66 }
67 fn digest<H: Hashable>(data: &H) -> Self::Output {
68 let mut sha = Sha256::new();
69 data.update(&mut sha);
70 sha.finish()
71 }
72}
73
74impl Hashable for u8 {
75 fn update<H: Hasher>(&self, h: &mut H) {
76 let mut buf = [0u8; std::mem::size_of::<u8>()];
77 let mut b = &mut buf[..];
78 b.write_u8(*self).unwrap();
79 h.update(buf.as_slice());
80 }
81}
82impl Hashable for bool {
83 fn update<H: Hasher>(&self, h: &mut H) {
84 let mut buf = [0u8; std::mem::size_of::<u8>()];
85 let mut b = &mut buf[..];
86 b.write_u8(*self as u8).unwrap();
87 h.update(buf.as_slice());
88 }
89}
90impl Hashable for i8 {
91 fn update<H: Hasher>(&self, h: &mut H) {
92 let mut buf = [0u8; std::mem::size_of::<u8>()];
93 let mut b = &mut buf[..];
94 b.write_i8(*self).unwrap();
95 h.update(buf.as_slice());
96 }
97}
98
99macro_rules! impl_hashable_for {
100 ($t:ty) => {
101 impl crate::Hashable for $t {
102 fn update<H: Hasher>(&self, h: &mut H) {
103 let mut buf = [0u8; std::mem::size_of::<$t>()];
104 let mut b = &mut buf[..];
105 paste! {
106 b.[<write_ $t>]::<LittleEndian>(*self).unwrap();
107 }
108 h.update(buf.as_slice());
109 }
110 }
111 };
112}
113
114impl_hashable_for!(i16);
115impl_hashable_for!(u16);
116impl_hashable_for!(i32);
117impl_hashable_for!(u32);
118impl_hashable_for!(i64);
119impl_hashable_for!(u64);
120
121
122impl<T: Hashable> Hashable for Vec<T> {
123 fn update<H: Hasher>(&self, h: &mut H) {
124 for t in self {
125 t.update(h);
126 }
127 }
128}
129impl Hashable for String {
130 fn update<H: Hasher>(&self, h: &mut H) {
131 for t in self.as_bytes() {
132 t.update(h);
133 }
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140 use crate as simple_hash;
141
142 #[derive(Hashable)]
143 struct Foo {
144 a: u8,
145 b: u16,
146 c: Vec<u32>,
147 }
148 #[test]
149 fn test_u8() {
150 let res = (9u8).digest::<sha2::Sha256>();
151 assert_eq!(res, hex_literal::hex!("2b4c342f5433ebe591a1da77e013d1b72475562d48578dca8b84bac6651c3cb9"));
152 }
153 #[test]
154 fn test_derive() {
155 let foo = Foo {
156 a: 8,
157 b: 99,
158 c: vec![0,1,2,3],
159 };
160 let res = foo.digest::<sha2::Sha256>();
161 assert_eq!(res, hex_literal::hex!("929863ce588951eae0cc88755216f96951d431e7d15adbb836d8f1960bb65a9d"));
162 }
163}