1extern crate alloc;
6use alloc::boxed::Box;
7use alloc::string::{String, ToString};
8use core::char::ParseCharError;
9use core::cmp::Ordering;
10use core::fmt::{Display, Formatter};
11use core::hash::{Hash, Hasher};
12use core::num::{ParseFloatError, ParseIntError};
13use core::str::{FromStr, ParseBoolError};
14use irox_enums::{EnumIterItem, EnumName, EnumTryFromStr};
15
16#[allow(non_camel_case_types)]
19#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, EnumName, EnumIterItem, EnumTryFromStr)]
20#[non_exhaustive]
21#[repr(u8)]
22pub enum Primitives {
23 u8,
24 i8,
25 u16,
26 i16,
27 u32,
28 i32,
29 f32,
30 u64,
31 i64,
32 f64,
33 u128,
34 i128,
35
36 bool,
37 char,
38
39 null,
40}
41
42impl TryFrom<u8> for Primitives {
43 type Error = ();
44
45 fn try_from(value: u8) -> Result<Self, Self::Error> {
46 for v in Primitives::iter_items() {
47 if value == v as u8 {
48 return Ok(v);
49 }
50 }
51 Err(())
52 }
53}
54
55pub enum PrimitiveParseError {
56 IntError(ParseIntError),
57 FloatError(ParseFloatError),
58 BoolError(ParseBoolError),
59 CharError(ParseCharError),
60 StringWasNotNullError,
61}
62
63impl From<ParseIntError> for PrimitiveParseError {
64 fn from(value: ParseIntError) -> Self {
65 PrimitiveParseError::IntError(value)
66 }
67}
68
69impl From<ParseFloatError> for PrimitiveParseError {
70 fn from(value: ParseFloatError) -> Self {
71 PrimitiveParseError::FloatError(value)
72 }
73}
74
75impl From<ParseBoolError> for PrimitiveParseError {
76 fn from(value: ParseBoolError) -> Self {
77 PrimitiveParseError::BoolError(value)
78 }
79}
80
81impl From<ParseCharError> for PrimitiveParseError {
82 fn from(value: ParseCharError) -> Self {
83 PrimitiveParseError::CharError(value)
84 }
85}
86
87impl Primitives {
88 #[must_use]
90 #[allow(clippy::match_same_arms)]
91 pub fn bytes_length(&self) -> usize {
92 match self {
93 Primitives::u8 => 1,
94 Primitives::i8 => 1,
95 Primitives::u16 => 2,
96 Primitives::i16 => 2,
97 Primitives::u32 => 4,
98 Primitives::i32 => 4,
99 Primitives::f32 => 4,
100 Primitives::u64 => 8,
101 Primitives::i64 => 8,
102 Primitives::f64 => 8,
103 Primitives::u128 => 16,
104 Primitives::i128 => 16,
105 Primitives::bool => 1,
106 Primitives::char => 4,
107 Primitives::null => 0,
108 }
109 }
110
111 pub fn try_value_from_str(&self, val: &str) -> Result<PrimitiveValue, PrimitiveParseError> {
112 match self {
113 Primitives::u8 => Ok(PrimitiveValue::u8(u8::from_str(val)?)),
114 Primitives::i8 => Ok(PrimitiveValue::i8(i8::from_str(val)?)),
115 Primitives::u16 => Ok(PrimitiveValue::u16(u16::from_str(val)?)),
116 Primitives::i16 => Ok(PrimitiveValue::i16(i16::from_str(val)?)),
117 Primitives::u32 => Ok(PrimitiveValue::u32(u32::from_str(val)?)),
118 Primitives::i32 => Ok(PrimitiveValue::i32(i32::from_str(val)?)),
119 Primitives::f32 => Ok(PrimitiveValue::f32(f32::from_str(val)?)),
120 Primitives::u64 => Ok(PrimitiveValue::u64(u64::from_str(val)?)),
121 Primitives::i64 => Ok(PrimitiveValue::i64(i64::from_str(val)?)),
122 Primitives::f64 => Ok(PrimitiveValue::f64(f64::from_str(val)?)),
123 Primitives::u128 => Ok(PrimitiveValue::u128(u128::from_str(val)?)),
124 Primitives::i128 => Ok(PrimitiveValue::i128(i128::from_str(val)?)),
125 Primitives::bool => Ok(PrimitiveValue::bool(bool::from_str(val)?)),
126 Primitives::char => Ok(PrimitiveValue::char(char::from_str(val)?)),
127 Primitives::null => {
128 if "null".eq_ignore_ascii_case(val) {
129 Ok(PrimitiveValue::null)
130 } else {
131 Err(PrimitiveParseError::StringWasNotNullError)
132 }
133 }
134 }
135 }
136
137 #[cfg(feature = "bits")]
138 pub fn read_be_from<T: irox_bits::Bits>(
139 &self,
140 src: &mut T,
141 ) -> Result<PrimitiveValue, irox_bits::BitsError> {
142 match self {
143 Primitives::u8 => Ok(PrimitiveValue::u8(src.read_u8()?)),
144 Primitives::i8 => Ok(PrimitiveValue::i8(src.read_i8()?)),
145 Primitives::u16 => Ok(PrimitiveValue::u16(src.read_be_u16()?)),
146 Primitives::i16 => Ok(PrimitiveValue::i16(src.read_be_i16()?)),
147 Primitives::u32 => Ok(PrimitiveValue::u32(src.read_be_u32()?)),
148 Primitives::i32 => Ok(PrimitiveValue::i32(src.read_be_i32()?)),
149 Primitives::f32 => Ok(PrimitiveValue::f32(src.read_be_f32()?)),
150 Primitives::u64 => Ok(PrimitiveValue::u64(src.read_be_u64()?)),
151 Primitives::i64 => Ok(PrimitiveValue::i64(src.read_be_i64()?)),
152 Primitives::f64 => Ok(PrimitiveValue::f64(src.read_be_f64()?)),
153 Primitives::u128 => Ok(PrimitiveValue::u128(src.read_be_u128()?)),
154 Primitives::i128 => Ok(PrimitiveValue::i128(src.read_be_i128()?)),
155 Primitives::bool => Ok(PrimitiveValue::bool(src.read_bool()?)),
156 Primitives::char => Ok(PrimitiveValue::char(src.read_be_utf8_char()?)),
157 Primitives::null => Ok(PrimitiveValue::null),
158 }
159 }
160}
161
162#[allow(non_camel_case_types)]
166#[derive(Debug, Copy, Clone, PartialEq, EnumName)]
167#[non_exhaustive]
168pub enum PrimitiveValue {
169 u8(u8),
170 i8(i8),
171 u16(u16),
172 i16(i16),
173 u32(u32),
174 i32(i32),
175 f32(f32),
176 u64(u64),
177 i64(i64),
178 f64(f64),
179 u128(u128),
180 i128(i128),
181 bool(bool),
182 char(char),
183
184 null,
185}
186impl Hash for PrimitiveValue {
187 fn hash<H: Hasher>(&self, state: &mut H) {
188 self.primitive().hash(state);
189 match self {
190 PrimitiveValue::u8(v) => v.hash(state),
191 PrimitiveValue::i8(v) => v.hash(state),
192 PrimitiveValue::u16(v) => v.hash(state),
193 PrimitiveValue::i16(v) => v.hash(state),
194 PrimitiveValue::u32(v) => v.hash(state),
195 PrimitiveValue::i32(v) => v.hash(state),
196 PrimitiveValue::f32(v) => v.to_bits().hash(state),
197 PrimitiveValue::u64(v) => v.hash(state),
198 PrimitiveValue::i64(v) => v.hash(state),
199 PrimitiveValue::f64(v) => v.to_bits().hash(state),
200 PrimitiveValue::u128(v) => v.hash(state),
201 PrimitiveValue::i128(v) => v.hash(state),
202 PrimitiveValue::bool(v) => v.hash(state),
203 PrimitiveValue::char(v) => v.hash(state),
204 PrimitiveValue::null => {}
205 }
206 }
207}
208
209impl PrimitiveValue {
210 #[must_use]
212 pub const fn primitive(&self) -> Primitives {
213 match self {
214 PrimitiveValue::u8(_) => Primitives::u8,
215 PrimitiveValue::i8(_) => Primitives::i8,
216 PrimitiveValue::u16(_) => Primitives::u16,
217 PrimitiveValue::i16(_) => Primitives::i16,
218 PrimitiveValue::u32(_) => Primitives::u32,
219 PrimitiveValue::i32(_) => Primitives::i32,
220 PrimitiveValue::f32(_) => Primitives::f32,
221 PrimitiveValue::u64(_) => Primitives::u64,
222 PrimitiveValue::i64(_) => Primitives::i64,
223 PrimitiveValue::f64(_) => Primitives::f64,
224 PrimitiveValue::u128(_) => Primitives::u128,
225 PrimitiveValue::i128(_) => Primitives::i128,
226 PrimitiveValue::bool(_) => Primitives::bool,
227 PrimitiveValue::char(_) => Primitives::char,
228 PrimitiveValue::null => Primitives::null,
229 }
230 }
231
232 pub fn as_be_bytes(&self) -> Box<[u8]> {
233 match self {
234 PrimitiveValue::u8(v) => Box::new([*v]),
235 PrimitiveValue::i8(v) => Box::new(v.to_be_bytes()),
236 PrimitiveValue::u16(v) => Box::new(v.to_be_bytes()),
237 PrimitiveValue::i16(v) => Box::new(v.to_be_bytes()),
238 PrimitiveValue::u32(v) => Box::new(v.to_be_bytes()),
239 PrimitiveValue::i32(v) => Box::new(v.to_be_bytes()),
240 PrimitiveValue::f32(v) => Box::new(v.to_be_bytes()),
241 PrimitiveValue::u64(v) => Box::new(v.to_be_bytes()),
242 PrimitiveValue::i64(v) => Box::new(v.to_be_bytes()),
243 PrimitiveValue::f64(v) => Box::new(v.to_be_bytes()),
244 PrimitiveValue::u128(v) => Box::new(v.to_be_bytes()),
245 PrimitiveValue::i128(v) => Box::new(v.to_be_bytes()),
246 PrimitiveValue::bool(v) => {
247 if *v {
248 Box::new([1])
249 } else {
250 Box::new([0])
251 }
252 }
253 PrimitiveValue::char(v) => {
254 let mut buf = [0u8; 4];
255 v.encode_utf8(&mut buf);
256 Box::new(buf)
257 }
258 PrimitiveValue::null => Box::new([]),
259 }
260 }
261
262 #[cfg(feature = "bits")]
263 pub fn write_be_to<T: irox_bits::MutBits>(
264 &self,
265 out: &mut T,
266 ) -> Result<(), irox_bits::BitsError> {
267 match self {
268 PrimitiveValue::u8(v) => out.write_u8(*v),
269 PrimitiveValue::i8(v) => out.write_i8(*v),
270 PrimitiveValue::u16(v) => out.write_be_u16(*v),
271 PrimitiveValue::i16(v) => out.write_be_i16(*v),
272 PrimitiveValue::u32(v) => out.write_be_u32(*v),
273 PrimitiveValue::i32(v) => out.write_be_i32(*v),
274 PrimitiveValue::f32(v) => out.write_be_f32(*v),
275 PrimitiveValue::u64(v) => out.write_be_u64(*v),
276 PrimitiveValue::i64(v) => out.write_be_i64(*v),
277 PrimitiveValue::f64(v) => out.write_be_f64(*v),
278 PrimitiveValue::u128(v) => out.write_be_u128(*v),
279 PrimitiveValue::i128(v) => out.write_be_i128(*v),
280 PrimitiveValue::bool(v) => out.write_bool(*v),
281 PrimitiveValue::char(v) => {
282 out.write_be_utf8_char(*v)?;
283 Ok(())
284 }
285 PrimitiveValue::null => Ok(()),
286 }
287 }
288}
289impl Display for PrimitiveValue {
290 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
291 match self {
292 PrimitiveValue::u8(v) => write!(f, "{v}"),
293 PrimitiveValue::i8(v) => write!(f, "{v}"),
294 PrimitiveValue::u16(v) => write!(f, "{v}"),
295 PrimitiveValue::i16(v) => write!(f, "{v}"),
296 PrimitiveValue::u32(v) => write!(f, "{v}"),
297 PrimitiveValue::i32(v) => write!(f, "{v}"),
298 PrimitiveValue::f32(v) => write!(f, "{v}"),
299 PrimitiveValue::u64(v) => write!(f, "{v}"),
300 PrimitiveValue::i64(v) => write!(f, "{v}"),
301 PrimitiveValue::f64(v) => write!(f, "{v}"),
302 PrimitiveValue::u128(v) => write!(f, "{v}"),
303 PrimitiveValue::i128(v) => write!(f, "{v}"),
304 PrimitiveValue::bool(v) => write!(f, "{v}"),
305 PrimitiveValue::char(v) => write!(f, "{v}"),
306
307 PrimitiveValue::null => write!(f, "null"),
308 }
309 }
310}
311macro_rules! impl_into_primivevalue {
312 ($ty:ty, $pv:tt) => {
313 impl From<$ty> for PrimitiveValue {
314 fn from(value: $ty) -> Self {
315 PrimitiveValue::$pv(value)
316 }
317 }
318 };
319}
320impl_into_primivevalue!(u8, u8);
321impl_into_primivevalue!(i8, i8);
322impl_into_primivevalue!(u16, u16);
323impl_into_primivevalue!(i16, i16);
324impl_into_primivevalue!(u32, u32);
325impl_into_primivevalue!(i32, i32);
326impl_into_primivevalue!(f32, f32);
327impl_into_primivevalue!(u64, u64);
328impl_into_primivevalue!(i64, i64);
329impl_into_primivevalue!(f64, f64);
330impl_into_primivevalue!(u128, u128);
331impl_into_primivevalue!(i128, i128);
332impl_into_primivevalue!(bool, bool);
333impl_into_primivevalue!(char, char);
334impl From<()> for PrimitiveValue {
335 fn from((): ()) -> Self {
336 PrimitiveValue::null
337 }
338}
339
340#[derive(Debug, Clone, Eq, PartialEq, Hash)]
344pub struct NamedPrimitive {
345 name: String,
346 primitive: Primitives,
347}
348impl Ord for NamedPrimitive {
349 fn cmp(&self, other: &Self) -> Ordering {
350 self.name.cmp(&other.name)
351 }
352}
353impl PartialOrd for NamedPrimitive {
354 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
355 Some(self.cmp(other))
356 }
357}
358
359impl NamedPrimitive {
360 #[must_use]
361 pub fn new(name: String, primitive: Primitives) -> NamedPrimitive {
362 NamedPrimitive { name, primitive }
363 }
364
365 #[must_use]
367 pub fn name(&self) -> &String {
368 &self.name
369 }
370
371 #[must_use]
373 pub fn primitive(&self) -> Primitives {
374 self.primitive
375 }
376}
377
378#[derive(Debug, Clone, PartialEq)]
382pub struct NamedPrimitiveValue {
383 pub(crate) name: String,
384 pub(crate) value: PrimitiveValue,
385}
386
387impl NamedPrimitiveValue {
388 #[must_use]
389 pub fn new(name: String, value: PrimitiveValue) -> NamedPrimitiveValue {
390 NamedPrimitiveValue { name, value }
391 }
392
393 #[must_use]
395 pub fn name(&self) -> &String {
396 &self.name
397 }
398
399 #[must_use]
401 pub fn value(&self) -> &PrimitiveValue {
402 &self.value
403 }
404}
405
406#[derive(Debug, Clone, PartialEq)]
407pub struct PrimitiveField {
408 pub name: String,
409 pub inner: PrimitiveFieldInner,
410}
411impl PrimitiveField {
412 pub fn new_unset(name: &str, primitive: Primitives) -> Self {
413 Self {
414 name: name.to_string(),
415 inner: PrimitiveFieldInner::Unset(primitive),
416 }
417 }
418}
419#[derive(Debug, Clone, PartialEq)]
420pub enum PrimitiveFieldInner {
421 Unset(Primitives),
422 Set(PrimitiveValue),
423}
424impl PrimitiveFieldInner {
425 pub fn primitive(&self) -> Primitives {
426 match self {
427 PrimitiveFieldInner::Unset(v) => *v,
428 PrimitiveFieldInner::Set(v) => v.primitive(),
429 }
430 }
431 pub fn value(&self) -> Option<&PrimitiveValue> {
432 if let PrimitiveFieldInner::Set(v) = self {
433 Some(v)
434 } else {
435 None
436 }
437 }
438}