1use std::num::{NonZeroU8, NonZeroU16, NonZeroU32};
15
16pub trait SymbolPrimitive: TryFrom<NonZeroU32> + Into<NonZeroU32> + Copy {
18 type BasePrimitive: From<Self> + TryInto<Self> + From<u8>;
20
21 const MAX: u32;
25}
26
27impl SymbolPrimitive for NonZeroU8 {
28 type BasePrimitive = u8;
29 const MAX: u32 = u8::MAX as u32;
30}
31
32impl SymbolPrimitive for NonZeroU16 {
33 type BasePrimitive = u16;
34 const MAX: u32 = u16::MAX as u32;
35}
36
37impl SymbolPrimitive for NonZeroU32 {
38 type BasePrimitive = u32;
39 const MAX: u32 = u32::MAX;
40}
41
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
46pub struct Symbol<T: SymbolPrimitive = NonZeroU32> {
47 pub(crate) n: T,
48}
49
50impl<T: SymbolPrimitive> Default for Symbol<T> {
51 fn default() -> Self {
52 Self::first()
53 }
54}
55
56impl<T: SymbolPrimitive> Symbol<T> {
57 pub fn first() -> Self {
59 let one: T::BasePrimitive = 1u8.into();
60 Symbol {
61 n: one
62 .try_into()
63 .ok()
64 .expect("unreachable: could not convert 1u8"),
65 }
66 }
67
68 pub fn usize(&self) -> usize {
74 let val = self.n.into().get();
75 #[cfg(target_pointer_width = "16")]
76 assert!(val <= 0xFFFF);
77 val as usize - 1
78 }
79}
80
81impl<T: SymbolPrimitive> Into<u32> for Symbol<T> {
82 fn into(self) -> u32 {
83 let nzu32: NonZeroU32 = self.n.into();
84 nzu32.get() - 1
85 }
86}
87
88mod miniserde_impls {
89 use super::{Symbol, SymbolPrimitive};
90 use miniserde::de::{Deserialize, Visitor};
91 use miniserde::{Error, Result, make_place};
92 use miniserde::{Serialize, de, ser};
93 use std::num::NonZeroU32;
94
95 make_place!(Place);
96
97 impl<T: SymbolPrimitive> Visitor for Place<Symbol<T>> {
98 fn nonnegative(&mut self, n: u64) -> Result<()> {
99 if n < T::MAX as u64 {
100 if let Some(Ok(nonzero_num)) =
101 NonZeroU32::new((n + 1) as u32).map(|n| TryInto::<T>::try_into(n))
102 {
103 self.out = Some(Symbol { n: nonzero_num });
104 Ok(())
105 } else {
106 Err(Error)
107 }
108 } else {
109 Err(Error)
110 }
111 }
112 }
113
114 impl<T: SymbolPrimitive> Deserialize for Symbol<T> {
115 fn begin(out: &mut Option<Self>) -> &mut dyn de::Visitor {
116 Place::new(out)
117 }
118 }
119
120 impl<T: SymbolPrimitive> Serialize for Symbol<T> {
121 fn begin(&self) -> ser::Fragment<'_> {
122 let n: u32 = (*self).into();
127 ser::Fragment::U64(n as u64)
128 }
129 }
130}
131
132#[cfg(feature = "nanoserde")]
133impl nanoserde::DeBin for Symbol<NonZeroU32> {
134 fn de_bin(offset: &mut usize, bytes: &[u8]) -> Result<Self, nanoserde::DeBinErr> {
135 Ok(Symbol {
136 n: u32::de_bin(offset, bytes)?.try_into().unwrap(),
137 })
138 }
139}
140
141#[cfg(feature = "nanoserde")]
142impl nanoserde::SerBin for Symbol<NonZeroU32> {
143 fn ser_bin(&self, output: &mut Vec<u8>) {
144 u32::ser_bin(&self.n.get(), output);
145 }
146}