Skip to main content

cesr/core/matter/code/
labeler.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 auto-sized tags and labels used as field names.
13#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
14#[allow(
15    non_camel_case_types,
16    reason = "variable-size code names use underscores by convention"
17)]
18pub enum LabelerCode {
19    /// Empty value.
20    Empty,
21    /// 1-char tag.
22    Tag1,
23    /// 2-char tag.
24    Tag2,
25    /// 3-char tag.
26    Tag3,
27    /// 4-char tag.
28    Tag4,
29    /// 5-char tag.
30    Tag5,
31    /// 6-char tag.
32    Tag6,
33    /// 7-char tag.
34    Tag7,
35    /// 8-char tag.
36    Tag8,
37    /// 9-char tag.
38    Tag9,
39    /// 10-char tag.
40    Tag10,
41    /// 11-char tag.
42    Tag11,
43    /// 1-byte label.
44    Label1,
45    /// 2-byte label.
46    Label2,
47    /// Variable-length Base64 string (lead 0).
48    StrB64_L0,
49    /// Variable-length Base64 string (lead 1).
50    StrB64_L1,
51    /// Variable-length Base64 string (lead 2).
52    StrB64_L2,
53    /// Variable-length big Base64 string (lead 0).
54    StrB64Big_L0,
55    /// Variable-length big Base64 string (lead 1).
56    StrB64Big_L1,
57    /// Variable-length big Base64 string (lead 2).
58    StrB64Big_L2,
59    /// Variable-length byte string (lead 0).
60    Bytes_L0,
61    /// Variable-length byte string (lead 1).
62    Bytes_L1,
63    /// Variable-length byte string (lead 2).
64    Bytes_L2,
65    /// Variable-length big byte string (lead 0).
66    BytesBig_L0,
67    /// Variable-length big byte string (lead 1).
68    BytesBig_L1,
69    /// Variable-length big byte string (lead 2).
70    BytesBig_L2,
71}
72
73impl Sealed for LabelerCode {}
74
75impl CesrCode for LabelerCode {
76    fn to_matter_code(&self) -> MatterCode {
77        match self {
78            Self::Empty => MatterCode::Empty,
79            Self::Tag1 => MatterCode::Tag1,
80            Self::Tag2 => MatterCode::Tag2,
81            Self::Tag3 => MatterCode::Tag3,
82            Self::Tag4 => MatterCode::Tag4,
83            Self::Tag5 => MatterCode::Tag5,
84            Self::Tag6 => MatterCode::Tag6,
85            Self::Tag7 => MatterCode::Tag7,
86            Self::Tag8 => MatterCode::Tag8,
87            Self::Tag9 => MatterCode::Tag9,
88            Self::Tag10 => MatterCode::Tag10,
89            Self::Tag11 => MatterCode::Tag11,
90            Self::Label1 => MatterCode::Label1,
91            Self::Label2 => MatterCode::Label2,
92            Self::StrB64_L0 => MatterCode::StrB64_L0,
93            Self::StrB64_L1 => MatterCode::StrB64_L1,
94            Self::StrB64_L2 => MatterCode::StrB64_L2,
95            Self::StrB64Big_L0 => MatterCode::StrB64Big_L0,
96            Self::StrB64Big_L1 => MatterCode::StrB64Big_L1,
97            Self::StrB64Big_L2 => MatterCode::StrB64Big_L2,
98            Self::Bytes_L0 => MatterCode::Bytes_L0,
99            Self::Bytes_L1 => MatterCode::Bytes_L1,
100            Self::Bytes_L2 => MatterCode::Bytes_L2,
101            Self::BytesBig_L0 => MatterCode::BytesBig_L0,
102            Self::BytesBig_L1 => MatterCode::BytesBig_L1,
103            Self::BytesBig_L2 => MatterCode::BytesBig_L2,
104        }
105    }
106
107    fn as_str(&self) -> &'static str {
108        match self {
109            Self::Empty => "1AAP",
110            Self::Tag1 => "0J",
111            Self::Tag2 => "0K",
112            Self::Tag3 => "X",
113            Self::Tag4 => "1AAF",
114            Self::Tag5 => "0L",
115            Self::Tag6 => "0M",
116            Self::Tag7 => "Y",
117            Self::Tag8 => "1AAN",
118            Self::Tag9 => "0N",
119            Self::Tag10 => "0O",
120            Self::Tag11 => "Z",
121            Self::Label1 => "V",
122            Self::Label2 => "W",
123            Self::StrB64_L0 => "4A",
124            Self::StrB64_L1 => "5A",
125            Self::StrB64_L2 => "6A",
126            Self::StrB64Big_L0 => "7AAA",
127            Self::StrB64Big_L1 => "8AAA",
128            Self::StrB64Big_L2 => "9AAA",
129            Self::Bytes_L0 => "4B",
130            Self::Bytes_L1 => "5B",
131            Self::Bytes_L2 => "6B",
132            Self::BytesBig_L0 => "7AAB",
133            Self::BytesBig_L1 => "8AAB",
134            Self::BytesBig_L2 => "9AAB",
135        }
136    }
137}
138
139impl TryFrom<MatterCode> for LabelerCode {
140    type Error = ValidationError;
141
142    fn try_from(code: MatterCode) -> Result<Self, Self::Error> {
143        match code {
144            MatterCode::Empty => Ok(Self::Empty),
145            MatterCode::Tag1 => Ok(Self::Tag1),
146            MatterCode::Tag2 => Ok(Self::Tag2),
147            MatterCode::Tag3 => Ok(Self::Tag3),
148            MatterCode::Tag4 => Ok(Self::Tag4),
149            MatterCode::Tag5 => Ok(Self::Tag5),
150            MatterCode::Tag6 => Ok(Self::Tag6),
151            MatterCode::Tag7 => Ok(Self::Tag7),
152            MatterCode::Tag8 => Ok(Self::Tag8),
153            MatterCode::Tag9 => Ok(Self::Tag9),
154            MatterCode::Tag10 => Ok(Self::Tag10),
155            MatterCode::Tag11 => Ok(Self::Tag11),
156            MatterCode::Label1 => Ok(Self::Label1),
157            MatterCode::Label2 => Ok(Self::Label2),
158            MatterCode::StrB64_L0 => Ok(Self::StrB64_L0),
159            MatterCode::StrB64_L1 => Ok(Self::StrB64_L1),
160            MatterCode::StrB64_L2 => Ok(Self::StrB64_L2),
161            MatterCode::StrB64Big_L0 => Ok(Self::StrB64Big_L0),
162            MatterCode::StrB64Big_L1 => Ok(Self::StrB64Big_L1),
163            MatterCode::StrB64Big_L2 => Ok(Self::StrB64Big_L2),
164            MatterCode::Bytes_L0 => Ok(Self::Bytes_L0),
165            MatterCode::Bytes_L1 => Ok(Self::Bytes_L1),
166            MatterCode::Bytes_L2 => Ok(Self::Bytes_L2),
167            MatterCode::BytesBig_L0 => Ok(Self::BytesBig_L0),
168            MatterCode::BytesBig_L1 => Ok(Self::BytesBig_L1),
169            MatterCode::BytesBig_L2 => Ok(Self::BytesBig_L2),
170            _ => Err(ValidationError::UnknownMatterCode(code.to_string())),
171        }
172    }
173}
174
175impl From<LabelerCode> for MatterCode {
176    fn from(code: LabelerCode) -> Self {
177        code.to_matter_code()
178    }
179}
180
181#[cfg(test)]
182mod tests {
183    use super::*;
184    use crate::core::matter::code::MatterCode;
185
186    #[test]
187    fn labeler_code_to_matter_code_roundtrip() {
188        let codes = [
189            (LabelerCode::Empty, MatterCode::Empty),
190            (LabelerCode::Tag1, MatterCode::Tag1),
191            (LabelerCode::Tag2, MatterCode::Tag2),
192            (LabelerCode::Tag3, MatterCode::Tag3),
193            (LabelerCode::Tag4, MatterCode::Tag4),
194            (LabelerCode::Tag5, MatterCode::Tag5),
195            (LabelerCode::Tag6, MatterCode::Tag6),
196            (LabelerCode::Tag7, MatterCode::Tag7),
197            (LabelerCode::Tag8, MatterCode::Tag8),
198            (LabelerCode::Tag9, MatterCode::Tag9),
199            (LabelerCode::Tag10, MatterCode::Tag10),
200            (LabelerCode::Tag11, MatterCode::Tag11),
201            (LabelerCode::Label1, MatterCode::Label1),
202            (LabelerCode::Label2, MatterCode::Label2),
203            (LabelerCode::StrB64_L0, MatterCode::StrB64_L0),
204            (LabelerCode::StrB64_L1, MatterCode::StrB64_L1),
205            (LabelerCode::StrB64_L2, MatterCode::StrB64_L2),
206            (LabelerCode::StrB64Big_L0, MatterCode::StrB64Big_L0),
207            (LabelerCode::StrB64Big_L1, MatterCode::StrB64Big_L1),
208            (LabelerCode::StrB64Big_L2, MatterCode::StrB64Big_L2),
209            (LabelerCode::Bytes_L0, MatterCode::Bytes_L0),
210            (LabelerCode::Bytes_L1, MatterCode::Bytes_L1),
211            (LabelerCode::Bytes_L2, MatterCode::Bytes_L2),
212            (LabelerCode::BytesBig_L0, MatterCode::BytesBig_L0),
213            (LabelerCode::BytesBig_L1, MatterCode::BytesBig_L1),
214            (LabelerCode::BytesBig_L2, MatterCode::BytesBig_L2),
215        ];
216        for (lc, mc) in codes {
217            assert_eq!(lc.to_matter_code(), mc);
218            assert_eq!(LabelerCode::try_from(mc).unwrap(), lc);
219            assert_eq!(MatterCode::from(lc), mc);
220        }
221    }
222
223    #[test]
224    fn labeler_code_rejects_non_labeler() {
225        assert!(LabelerCode::try_from(MatterCode::Ed25519).is_err());
226        assert!(LabelerCode::try_from(MatterCode::Ed25519Seed).is_err());
227        assert!(LabelerCode::try_from(MatterCode::Short).is_err());
228    }
229
230    #[test]
231    fn labeler_code_as_str() {
232        assert_eq!(LabelerCode::Empty.as_str(), "1AAP");
233        assert_eq!(LabelerCode::Tag3.as_str(), "X");
234        assert_eq!(LabelerCode::Tag7.as_str(), "Y");
235        assert_eq!(LabelerCode::Label1.as_str(), "V");
236        assert_eq!(LabelerCode::StrB64_L0.as_str(), "4A");
237        assert_eq!(LabelerCode::Bytes_L0.as_str(), "4B");
238        assert_eq!(LabelerCode::BytesBig_L2.as_str(), "9AAB");
239    }
240}