1pub mod arrayref;
4pub mod owned;
5pub mod slice;
6
7#[cfg(feature = "generic-tests")]
8pub mod tests;
9
10#[derive(Debug, PartialEq)]
12pub enum UpdateError {
13 InvalidPayloadLength,
15 MaximumLengthExceeded,
17 Unknown,
19}
20
21impl core::fmt::Display for UpdateError {
22 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
23 let text = match self {
24 UpdateError::InvalidPayloadLength => "the length of the provided payload is invalid",
25 UpdateError::MaximumLengthExceeded => "the maximum input length is exceeded",
26 UpdateError::Unknown => "indicates an unknown error",
27 };
28
29 f.write_str(text)
30 }
31}
32
33#[cfg(feature = "error-in-core")]
34mod error_in_core {
35
36 impl core::error::Error for super::UpdateError {}
37}
38
39pub trait DigestIncrementalBase {
46 type IncrementalState: InitializeDigestState;
48 fn reset(state: &mut Self::IncrementalState);
50 fn update(state: &mut Self::IncrementalState, payload: &[u8]) -> Result<(), UpdateError>;
52}
53
54pub trait InitializeDigestState {
56 fn new() -> Self;
58}
59
60#[derive(Clone)]
61pub struct Hasher<const N: usize, D: DigestIncrementalBase> {
63 pub state: D::IncrementalState,
65}
66
67impl<const N: usize, D: arrayref::DigestIncremental<N>> Default for Hasher<N, D>
68where
69 D::IncrementalState: Default,
70{
71 fn default() -> Self {
72 Self {
73 state: Default::default(),
74 }
75 }
76}
77
78impl<const N: usize, D: DigestIncrementalBase + slice::Hash> Hasher<N, D> {
79 pub fn hash_slice(digest: &mut [u8], payload: &[u8]) -> Result<usize, slice::HashError> {
81 D::hash(digest, payload)
82 }
83}
84
85impl<const N: usize, D: slice::DigestIncremental> Hasher<N, D> {
86 pub fn finish_slice(&mut self, digest: &mut [u8]) -> Result<usize, slice::FinishError> {
88 D::finish(&mut self.state, digest)
89 }
90}
91
92impl<const N: usize, D: DigestIncrementalBase> Hasher<N, D> {
93 pub fn update(&mut self, payload: &[u8]) -> Result<(), UpdateError> {
95 D::update(&mut self.state, payload)
96 }
97 pub fn reset(&mut self) {
99 D::reset(&mut self.state)
100 }
101
102 pub fn new() -> Self {
104 Self {
105 state: D::IncrementalState::new(),
106 }
107 }
108}
109
110impl<const N: usize, D: arrayref::DigestIncremental<N>> Hasher<N, D> {
111 pub fn finish(&mut self, digest: &mut [u8; N]) {
113 D::finish(&mut self.state, digest)
114 }
115 pub fn finish_to_owned(&mut self) -> [u8; N] {
117 <D as owned::DigestIncremental<N>>::finish(&mut self.state)
118 }
119}
120
121impl<const N: usize, D: DigestIncrementalBase + arrayref::Hash<N>> Hasher<N, D> {
122 pub fn hash(digest: &mut [u8; N], payload: &[u8]) -> Result<(), arrayref::HashError> {
124 D::hash(digest, payload)
125 }
126 pub fn hash_to_owned(payload: &[u8]) -> Result<[u8; N], arrayref::HashError> {
128 <D as owned::Hash<N>>::hash(payload)
129 }
130}