1use sha2::{Digest, Sha256, Sha384, Sha512, digest::typenum::Unsigned};
2
3use crate::{DeterministicHash, DeterministicHasher};
4
5pub struct ShaHasher<D: Digest>(D);
6
7impl<D: Digest> ShaHasher<D>
8where
9 sha2::digest::Output<D>: core::fmt::LowerHex,
10{
11 pub fn write_value<T: DeterministicHash>(&mut self, input: T) {
14 input.deterministic_hash(self);
15 }
16
17 pub fn write_ref<T: DeterministicHash>(&mut self, input: &T) {
20 input.deterministic_hash(self);
21 }
22
23 pub fn finish(self) -> String {
25 let result = self.0.finalize();
26 format!("{:01$x}", result, D::OutputSize::to_usize() * 2)
27 }
28
29 pub fn finish_base64(self) -> String {
31 let result = self.0.finalize();
32 data_encoding::BASE64.encode(result.as_slice())
33 }
34}
35
36impl<D: Digest> DeterministicHasher for ShaHasher<D> {
37 fn finish(&self) -> u64 {
38 panic!("use the ShaHasher non-trait function instead");
39 }
40
41 fn write_bytes(&mut self, bytes: &[u8]) {
42 self.0.update(bytes);
43 }
44}
45
46impl ShaHasher<Sha256> {
47 pub fn new_sha256() -> Self {
48 ShaHasher(Sha256::new())
49 }
50}
51impl ShaHasher<Sha384> {
52 pub fn new_sha384() -> Self {
53 ShaHasher(Sha384::new())
54 }
55}
56impl ShaHasher<Sha512> {
57 pub fn new_sha512() -> Self {
58 ShaHasher(Sha512::new())
59 }
60}