Skip to main content

ephemeris_release/
digest.rs

1//! Digests of release files.
2
3use facet::Facet;
4use sha2::{Digest as _, Sha256, Sha512};
5
6/// The hash algorithm of a digest.
7#[derive(Clone, Copy, Debug, Eq, Facet, PartialEq)]
8#[repr(u8)]
9pub(crate) enum DigestAlgorithm {
10    /// SHA-256, 64 hex characters.
11    #[facet(rename = "sha256")]
12    Sha256,
13    /// SHA-512, 128 hex characters.
14    #[facet(rename = "sha512")]
15    Sha512,
16}
17
18impl DigestAlgorithm {
19    /// The lowercase hex digest of `bytes`.
20    pub(crate) fn hex(self, bytes: &[u8]) -> String {
21        match self {
22            Self::Sha256 => Self::encode(&Sha256::digest(bytes)),
23            Self::Sha512 => Self::encode(&Sha512::digest(bytes)),
24        }
25    }
26
27    fn encode(digest: &[u8]) -> String {
28        let hex: Vec<String> = digest.iter().map(|byte| format!("{byte:02x}")).collect();
29        hex.concat()
30    }
31}
32
33#[cfg(test)]
34mod tests {
35    use super::DigestAlgorithm;
36
37    #[test]
38    fn digests_are_lowercase_hex() {
39        assert_eq!(
40            DigestAlgorithm::Sha256.hex(b"abc"),
41            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
42        );
43        assert_eq!(
44            DigestAlgorithm::Sha256.hex(b""),
45            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
46        );
47        assert!(
48            DigestAlgorithm::Sha512
49                .hex(b"abc")
50                .starts_with("ddaf35a193617aba")
51        );
52    }
53}