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