cesr/core/matter/code/
number.rs1use 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#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
14pub enum NumberCode {
15 Short,
17 Long,
19 Tall,
21 Big,
23 Large,
25 Great,
27 Vast,
29}
30
31impl NumberCode {
32 pub fn max_value(&self) -> Result<u128, ValidationError> {
39 let raw_size = self.to_matter_code().raw_size()?;
40 if raw_size >= 16 {
41 Ok(u128::MAX)
42 } else {
43 Ok((1u128 << (raw_size * 8)) - 1)
44 }
45 }
46
47 #[must_use]
49 pub const fn for_value(value: u128) -> Self {
50 match value {
51 0..=0xFFFF => Self::Short,
52 0x1_0000..=0xFFFF_FFFF => Self::Long,
53 0x1_0000_0000..=0xFF_FFFF_FFFF => Self::Tall,
54 0x100_0000_0000..=0xFFFF_FFFF_FFFF_FFFF => Self::Big,
55 _ => Self::Vast,
56 }
57 }
58}
59
60impl Sealed for NumberCode {}
61
62impl CesrCode for NumberCode {
63 fn to_matter_code(&self) -> MatterCode {
64 match self {
65 Self::Short => MatterCode::Short,
66 Self::Long => MatterCode::Long,
67 Self::Tall => MatterCode::Tall,
68 Self::Big => MatterCode::Big,
69 Self::Large => MatterCode::Large,
70 Self::Great => MatterCode::Great,
71 Self::Vast => MatterCode::Vast,
72 }
73 }
74
75 fn as_str(&self) -> &'static str {
76 match self {
77 Self::Short => "M",
78 Self::Long => "0H",
79 Self::Tall => "R",
80 Self::Big => "N",
81 Self::Large => "S",
82 Self::Great => "T",
83 Self::Vast => "U",
84 }
85 }
86}
87
88impl TryFrom<MatterCode> for NumberCode {
89 type Error = ValidationError;
90
91 fn try_from(code: MatterCode) -> Result<Self, Self::Error> {
92 match code {
93 MatterCode::Short => Ok(Self::Short),
94 MatterCode::Long => Ok(Self::Long),
95 MatterCode::Tall => Ok(Self::Tall),
96 MatterCode::Big => Ok(Self::Big),
97 MatterCode::Large => Ok(Self::Large),
98 MatterCode::Great => Ok(Self::Great),
99 MatterCode::Vast => Ok(Self::Vast),
100 _ => Err(ValidationError::UnknownMatterCode(code.to_string())),
101 }
102 }
103}
104
105impl From<NumberCode> for MatterCode {
106 fn from(code: NumberCode) -> Self {
107 code.to_matter_code()
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::*;
114 use crate::core::matter::code::MatterCode;
115
116 #[test]
117 fn number_code_to_matter_code_roundtrip() {
118 let codes = [
119 (NumberCode::Short, MatterCode::Short),
120 (NumberCode::Long, MatterCode::Long),
121 (NumberCode::Tall, MatterCode::Tall),
122 (NumberCode::Big, MatterCode::Big),
123 (NumberCode::Large, MatterCode::Large),
124 (NumberCode::Great, MatterCode::Great),
125 (NumberCode::Vast, MatterCode::Vast),
126 ];
127 for (nc, mc) in codes {
128 assert_eq!(nc.to_matter_code(), mc);
129 assert_eq!(NumberCode::try_from(mc).unwrap(), nc);
130 assert_eq!(MatterCode::from(nc), mc);
131 }
132 }
133
134 #[test]
135 fn number_code_rejects_non_number() {
136 assert!(NumberCode::try_from(MatterCode::Ed25519).is_err());
137 assert!(NumberCode::try_from(MatterCode::Blake3_256).is_err());
138 assert!(NumberCode::try_from(MatterCode::Ed25519Seed).is_err());
139 }
140
141 #[test]
142 fn number_code_as_str() {
143 assert_eq!(NumberCode::Short.as_str(), "M");
144 assert_eq!(NumberCode::Long.as_str(), "0H");
145 assert_eq!(NumberCode::Big.as_str(), "N");
146 assert_eq!(NumberCode::Vast.as_str(), "U");
147 }
148
149 #[test]
150 fn number_code_max_value() {
151 assert_eq!(NumberCode::Short.max_value().unwrap(), 0xFFFF);
152 assert_eq!(NumberCode::Long.max_value().unwrap(), 0xFFFF_FFFF);
153 assert_eq!(NumberCode::Big.max_value().unwrap(), 0xFFFF_FFFF_FFFF_FFFF);
154 }
155
156 #[test]
157 fn number_code_for_value() {
158 assert_eq!(NumberCode::for_value(0), NumberCode::Short);
159 assert_eq!(NumberCode::for_value(255), NumberCode::Short);
160 assert_eq!(NumberCode::for_value(0xFFFF), NumberCode::Short);
161 assert_eq!(NumberCode::for_value(0x1_0000), NumberCode::Long);
162 assert_eq!(NumberCode::for_value(0xFFFF_FFFF), NumberCode::Long);
163 assert_eq!(NumberCode::for_value(0x1_0000_0000), NumberCode::Tall);
164 assert_eq!(NumberCode::for_value(0x1_0000_0000_0000), NumberCode::Big);
165 assert_eq!(NumberCode::for_value(u128::from(u64::MAX)), NumberCode::Big);
166 assert_eq!(NumberCode::for_value(u128::MAX), NumberCode::Vast);
167 }
168}