Skip to main content

cesr/core/matter/code/
texter.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 variable-length byte string primitives.
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 TexterCode {
19    /// Variable-length byte string (lead 0).
20    Bytes_L0,
21    /// Variable-length byte string (lead 1).
22    Bytes_L1,
23    /// Variable-length byte string (lead 2).
24    Bytes_L2,
25    /// Variable-length big byte string (lead 0).
26    BytesBig_L0,
27    /// Variable-length big byte string (lead 1).
28    BytesBig_L1,
29    /// Variable-length big byte string (lead 2).
30    BytesBig_L2,
31}
32
33impl Sealed for TexterCode {}
34
35impl CesrCode for TexterCode {
36    fn to_matter_code(&self) -> MatterCode {
37        match self {
38            Self::Bytes_L0 => MatterCode::Bytes_L0,
39            Self::Bytes_L1 => MatterCode::Bytes_L1,
40            Self::Bytes_L2 => MatterCode::Bytes_L2,
41            Self::BytesBig_L0 => MatterCode::BytesBig_L0,
42            Self::BytesBig_L1 => MatterCode::BytesBig_L1,
43            Self::BytesBig_L2 => MatterCode::BytesBig_L2,
44        }
45    }
46
47    fn as_str(&self) -> &'static str {
48        match self {
49            Self::Bytes_L0 => "4B",
50            Self::Bytes_L1 => "5B",
51            Self::Bytes_L2 => "6B",
52            Self::BytesBig_L0 => "7AAB",
53            Self::BytesBig_L1 => "8AAB",
54            Self::BytesBig_L2 => "9AAB",
55        }
56    }
57}
58
59impl TryFrom<MatterCode> for TexterCode {
60    type Error = ValidationError;
61
62    fn try_from(code: MatterCode) -> Result<Self, Self::Error> {
63        match code {
64            MatterCode::Bytes_L0 => Ok(Self::Bytes_L0),
65            MatterCode::Bytes_L1 => Ok(Self::Bytes_L1),
66            MatterCode::Bytes_L2 => Ok(Self::Bytes_L2),
67            MatterCode::BytesBig_L0 => Ok(Self::BytesBig_L0),
68            MatterCode::BytesBig_L1 => Ok(Self::BytesBig_L1),
69            MatterCode::BytesBig_L2 => Ok(Self::BytesBig_L2),
70            _ => Err(ValidationError::UnknownMatterCode(code.to_string())),
71        }
72    }
73}
74
75impl From<TexterCode> for MatterCode {
76    fn from(code: TexterCode) -> Self {
77        code.to_matter_code()
78    }
79}
80
81#[cfg(test)]
82mod tests {
83    use super::*;
84    use crate::core::matter::code::MatterCode;
85
86    #[test]
87    fn texter_code_to_matter_code_roundtrip() {
88        let codes = [
89            (TexterCode::Bytes_L0, MatterCode::Bytes_L0),
90            (TexterCode::Bytes_L1, MatterCode::Bytes_L1),
91            (TexterCode::Bytes_L2, MatterCode::Bytes_L2),
92            (TexterCode::BytesBig_L0, MatterCode::BytesBig_L0),
93            (TexterCode::BytesBig_L1, MatterCode::BytesBig_L1),
94            (TexterCode::BytesBig_L2, MatterCode::BytesBig_L2),
95        ];
96        for (tc, mc) in codes {
97            assert_eq!(tc.to_matter_code(), mc);
98            assert_eq!(TexterCode::try_from(mc).unwrap(), tc);
99            assert_eq!(MatterCode::from(tc), mc);
100        }
101    }
102
103    #[test]
104    fn texter_code_rejects_non_texter() {
105        assert!(TexterCode::try_from(MatterCode::Ed25519).is_err());
106        assert!(TexterCode::try_from(MatterCode::Ed25519Seed).is_err());
107        assert!(TexterCode::try_from(MatterCode::Short).is_err());
108    }
109
110    #[test]
111    fn texter_code_as_str() {
112        assert_eq!(TexterCode::Bytes_L0.as_str(), "4B");
113        assert_eq!(TexterCode::Bytes_L2.as_str(), "6B");
114        assert_eq!(TexterCode::BytesBig_L0.as_str(), "7AAB");
115        assert_eq!(TexterCode::BytesBig_L2.as_str(), "9AAB");
116    }
117}