1use std::io;
2
3use lexe_byte_array::ByteArray;
4use ref_cast::RefCast;
5
6pub const HASH_LEN: usize = 32;
7
8#[derive(Copy, Clone, Default, Eq, Hash, PartialEq, RefCast)]
10#[repr(transparent)]
11pub struct Hash([u8; 32]);
12
13#[derive(Clone)]
15pub struct Context(ring::digest::Context);
16
17pub fn digest(input: &[u8]) -> Hash {
19 digest_many(&[input])
20}
21
22pub fn digest_many(inputs: &[&[u8]]) -> Hash {
25 let mut ctx = Context::new();
26 for input in inputs {
27 ctx.update(input);
28 }
29 ctx.finish()
30}
31
32impl Hash {
35 pub const fn new(value: [u8; 32]) -> Self {
36 Self(value)
37 }
38
39 fn from_ring(output: ring::digest::Digest) -> Self {
42 Self::new(<[u8; 32]>::try_from(output.as_ref()).unwrap())
43 }
44}
45
46lexe_byte_array::impl_byte_array!(Hash, 32);
47lexe_byte_array::impl_fromstr_fromhex!(Hash, 32);
48lexe_byte_array::impl_debug_display_as_hex!(Hash);
49
50impl Context {
53 pub fn new() -> Self {
54 Self(ring::digest::Context::new(&ring::digest::SHA256))
55 }
56
57 pub fn update(&mut self, input: &[u8]) {
58 self.0.update(input);
59 }
60
61 pub fn finish(self) -> Hash {
62 Hash::from_ring(self.0.finish())
63 }
64}
65
66impl Default for Context {
67 fn default() -> Self {
68 Self::new()
69 }
70}
71
72impl io::Write for Context {
73 fn write(&mut self, input: &[u8]) -> io::Result<usize> {
74 self.update(input);
75 Ok(input.len())
76 }
77
78 fn flush(&mut self) -> io::Result<()> {
79 Ok(())
80 }
81}
82
83#[cfg(test)]
84mod test {
85 use lexe_hex::hex;
86
87 use crate::sha256;
88
89 #[test]
91 fn test_sha256() {
92 let actual = hex::encode(sha256::digest(b"").as_ref());
93 let expected =
94 "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
95 assert_eq!(&actual, expected);
96 }
97}