hashes 0.1.9

Rust implementation of cryptographic hash function algorithms
Documentation
#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub struct Digest<const N_BYTES: usize>([u8; N_BYTES]);

impl<const N_BYTES: usize> Digest<N_BYTES> {
    pub fn from_bytes(bytes: [u8; N_BYTES]) -> Self {
        Self(bytes)
    }

    pub fn into_bytes(self) -> [u8; N_BYTES] {
        self.0
    }
}

#[cfg(any(feature = "std", doctest))]
mod with_std {
    use super::Digest;

    impl<const N_BYTES: usize> std::fmt::Display for Digest<N_BYTES> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            for b in self.0 {
                write!(f, "{:02x}", b)?
            }
            Ok(())
        }
    }

    impl<const N_BYTES: usize> std::fmt::Debug for Digest<N_BYTES> {
        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
            write!(f, "\"{}\"", self)
        }
    }

    impl<const N_BYTES: usize> std::str::FromStr for Digest<N_BYTES> {
        type Err = String;

        fn from_str(s: &str) -> Result<Self, Self::Err> {
            let mut bytes = [0; N_BYTES];

            if s.len() != 2 * N_BYTES {
                return Err("Invalid digest string length".into());
            }

            bytes
                .iter_mut()
                .zip(s.as_bytes().chunks(2).map(std::str::from_utf8))
                .try_for_each(|(byte, chunk)| {
                    chunk
                        .map_err(|_| "Invalid utf8 character in digest string".to_string())
                        .and_then(|chunk| {
                            u8::from_str_radix(chunk, 16)
                                .map_err(|_| "Invalid hex character in digest string".into())
                                .map(|value| {
                                    *byte = value;
                                })
                        })
                })?;

            Ok(Self(bytes))
        }
    }
}