Skip to main content

cesr/core/matter/code/
noncer.rs

1use super::cesr_code::CesrCode;
2use super::matter_code::MatterCode;
3use super::sealed::Sealed;
4use crate::core::matter::error::ValidationError;
5#[cfg(feature = "alloc")]
6#[allow(
7    unused_imports,
8    reason = "alloc prelude items; subset used per cfg/feature combination"
9)]
10use alloc::string::ToString;
11
12/// CESR codes for nonce/randomness primitives.
13///
14/// Combines digest codes, salt codes, and an empty-value code
15/// for representing absent nonces.
16#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
17#[allow(
18    non_camel_case_types,
19    reason = "digest algorithm names use underscores by convention"
20)]
21pub enum NoncerCode {
22    /// Empty value for absent nonces.
23    Empty,
24    /// Salt/nonce, 128 bits.
25    Salt128,
26    /// Salt/nonce, 256 bits.
27    Salt256,
28    /// BLAKE3, 256-bit.
29    Blake3_256,
30    /// `BLAKE2b`, 256-bit.
31    Blake2b_256,
32    /// BLAKE2s, 256-bit.
33    Blake2s_256,
34    /// SHA-3, 256-bit.
35    SHA3_256,
36    /// SHA-2, 256-bit.
37    SHA2_256,
38    /// BLAKE3, 512-bit.
39    Blake3_512,
40    /// `BLAKE2b`, 512-bit.
41    Blake2b_512,
42    /// SHA-3, 512-bit.
43    SHA3_512,
44    /// SHA-2, 512-bit.
45    SHA2_512,
46}
47
48impl Sealed for NoncerCode {}
49
50impl CesrCode for NoncerCode {
51    fn to_matter_code(&self) -> MatterCode {
52        match self {
53            Self::Empty => MatterCode::Empty,
54            Self::Salt128 => MatterCode::Salt128,
55            Self::Salt256 => MatterCode::Salt256,
56            Self::Blake3_256 => MatterCode::Blake3_256,
57            Self::Blake2b_256 => MatterCode::Blake2b_256,
58            Self::Blake2s_256 => MatterCode::Blake2s_256,
59            Self::SHA3_256 => MatterCode::SHA3_256,
60            Self::SHA2_256 => MatterCode::SHA2_256,
61            Self::Blake3_512 => MatterCode::Blake3_512,
62            Self::Blake2b_512 => MatterCode::Blake2b_512,
63            Self::SHA3_512 => MatterCode::SHA3_512,
64            Self::SHA2_512 => MatterCode::SHA2_512,
65        }
66    }
67
68    fn as_str(&self) -> &'static str {
69        match self {
70            Self::Empty => "1AAP",
71            Self::Salt128 => "0A",
72            Self::Salt256 => "a",
73            Self::Blake3_256 => "E",
74            Self::Blake2b_256 => "F",
75            Self::Blake2s_256 => "G",
76            Self::SHA3_256 => "H",
77            Self::SHA2_256 => "I",
78            Self::Blake3_512 => "0D",
79            Self::Blake2b_512 => "0E",
80            Self::SHA3_512 => "0F",
81            Self::SHA2_512 => "0G",
82        }
83    }
84}
85
86impl TryFrom<MatterCode> for NoncerCode {
87    type Error = ValidationError;
88
89    fn try_from(code: MatterCode) -> Result<Self, Self::Error> {
90        match code {
91            MatterCode::Empty => Ok(Self::Empty),
92            MatterCode::Salt128 => Ok(Self::Salt128),
93            MatterCode::Salt256 => Ok(Self::Salt256),
94            MatterCode::Blake3_256 => Ok(Self::Blake3_256),
95            MatterCode::Blake2b_256 => Ok(Self::Blake2b_256),
96            MatterCode::Blake2s_256 => Ok(Self::Blake2s_256),
97            MatterCode::SHA3_256 => Ok(Self::SHA3_256),
98            MatterCode::SHA2_256 => Ok(Self::SHA2_256),
99            MatterCode::Blake3_512 => Ok(Self::Blake3_512),
100            MatterCode::Blake2b_512 => Ok(Self::Blake2b_512),
101            MatterCode::SHA3_512 => Ok(Self::SHA3_512),
102            MatterCode::SHA2_512 => Ok(Self::SHA2_512),
103            _ => Err(ValidationError::UnknownMatterCode(code.to_string())),
104        }
105    }
106}
107
108impl From<NoncerCode> for MatterCode {
109    fn from(code: NoncerCode) -> Self {
110        code.to_matter_code()
111    }
112}
113
114#[cfg(test)]
115mod tests {
116    use super::*;
117    use crate::core::matter::code::MatterCode;
118
119    #[test]
120    fn noncer_code_to_matter_code_roundtrip() {
121        let codes = [
122            (NoncerCode::Empty, MatterCode::Empty),
123            (NoncerCode::Salt128, MatterCode::Salt128),
124            (NoncerCode::Salt256, MatterCode::Salt256),
125            (NoncerCode::Blake3_256, MatterCode::Blake3_256),
126            (NoncerCode::Blake2b_256, MatterCode::Blake2b_256),
127            (NoncerCode::Blake2s_256, MatterCode::Blake2s_256),
128            (NoncerCode::SHA3_256, MatterCode::SHA3_256),
129            (NoncerCode::SHA2_256, MatterCode::SHA2_256),
130            (NoncerCode::Blake3_512, MatterCode::Blake3_512),
131            (NoncerCode::Blake2b_512, MatterCode::Blake2b_512),
132            (NoncerCode::SHA3_512, MatterCode::SHA3_512),
133            (NoncerCode::SHA2_512, MatterCode::SHA2_512),
134        ];
135        for (nc, mc) in codes {
136            assert_eq!(nc.to_matter_code(), mc);
137            assert_eq!(NoncerCode::try_from(mc).unwrap(), nc);
138            assert_eq!(MatterCode::from(nc), mc);
139        }
140    }
141
142    #[test]
143    fn noncer_code_rejects_non_noncer() {
144        assert!(NoncerCode::try_from(MatterCode::Ed25519).is_err());
145        assert!(NoncerCode::try_from(MatterCode::Ed25519Seed).is_err());
146        assert!(NoncerCode::try_from(MatterCode::Short).is_err());
147    }
148
149    #[test]
150    fn noncer_code_as_str() {
151        assert_eq!(NoncerCode::Empty.as_str(), "1AAP");
152        assert_eq!(NoncerCode::Salt128.as_str(), "0A");
153        assert_eq!(NoncerCode::Salt256.as_str(), "a");
154        assert_eq!(NoncerCode::Blake3_256.as_str(), "E");
155        assert_eq!(NoncerCode::SHA2_512.as_str(), "0G");
156    }
157}