1use std::{
5 fmt,
6 fmt::{Display, Formatter},
7 ops::Deref,
8};
9
10use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Visitor};
11
12use super::r#type::Type;
13use crate::{error, error::diagnostic::dictionary::dictionary_entry_id_capacity_exceeded};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
18pub enum DictionaryEntryId {
19 U1(u8),
20 U2(u16),
21 U4(u32),
22 U8(u64),
23 U16(u128),
24}
25
26impl DictionaryEntryId {
27 pub fn from_u128(value: u128, id_type: Type) -> crate::Result<Self> {
30 match id_type {
31 Type::Uint1 => {
32 if value > u8::MAX as u128 {
33 return Err(error!(dictionary_entry_id_capacity_exceeded(
34 Type::Uint1,
35 value,
36 u8::MAX as u128
37 )));
38 }
39 Ok(Self::U1(value as u8))
40 }
41 Type::Uint2 => {
42 if value > u16::MAX as u128 {
43 return Err(error!(dictionary_entry_id_capacity_exceeded(
44 Type::Uint2,
45 value,
46 u16::MAX as u128
47 )));
48 }
49 Ok(Self::U2(value as u16))
50 }
51 Type::Uint4 => {
52 if value > u32::MAX as u128 {
53 return Err(error!(dictionary_entry_id_capacity_exceeded(
54 Type::Uint4,
55 value,
56 u32::MAX as u128
57 )));
58 }
59 Ok(Self::U4(value as u32))
60 }
61 Type::Uint8 => {
62 if value > u64::MAX as u128 {
63 return Err(error!(dictionary_entry_id_capacity_exceeded(
64 Type::Uint8,
65 value,
66 u64::MAX as u128
67 )));
68 }
69 Ok(Self::U8(value as u64))
70 }
71 Type::Uint16 => Ok(Self::U16(value)),
72 _ => unimplemented!(
74 "Invalid dictionary id_type: {:?}. Must be Uint1, Uint2, Uint4, Uint8, or Uint16",
75 id_type
76 ),
77 }
78 }
79
80 pub fn to_u128(&self) -> u128 {
82 match self {
83 Self::U1(v) => *v as u128,
84 Self::U2(v) => *v as u128,
85 Self::U4(v) => *v as u128,
86 Self::U8(v) => *v as u128,
87 Self::U16(v) => *v,
88 }
89 }
90
91 pub fn id_type(&self) -> Type {
93 match self {
94 Self::U1(_) => Type::Uint1,
95 Self::U2(_) => Type::Uint2,
96 Self::U4(_) => Type::Uint4,
97 Self::U8(_) => Type::Uint8,
98 Self::U16(_) => Type::Uint16,
99 }
100 }
101
102 pub fn to_value(self) -> super::Value {
104 super::Value::DictionaryId(self)
105 }
106
107 pub fn from_value(value: &super::Value) -> Option<Self> {
110 match value {
111 super::Value::DictionaryId(id) => Some(*id),
112 super::Value::Uint1(v) => Some(Self::U1(*v)),
113 super::Value::Uint2(v) => Some(Self::U2(*v)),
114 super::Value::Uint4(v) => Some(Self::U4(*v)),
115 super::Value::Uint8(v) => Some(Self::U8(*v)),
116 super::Value::Uint16(v) => Some(Self::U16(*v)),
117 _ => None,
118 }
119 }
120}
121
122impl PartialOrd for DictionaryEntryId {
123 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
124 Some(self.cmp(other))
125 }
126}
127
128impl Ord for DictionaryEntryId {
129 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
130 self.to_u128().cmp(&other.to_u128())
131 }
132}
133
134impl Default for DictionaryEntryId {
135 fn default() -> Self {
136 Self::U1(0)
137 }
138}
139
140impl std::fmt::Display for DictionaryEntryId {
141 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
142 match self {
143 Self::U1(v) => write!(f, "{}", v),
144 Self::U2(v) => write!(f, "{}", v),
145 Self::U4(v) => write!(f, "{}", v),
146 Self::U8(v) => write!(f, "{}", v),
147 Self::U16(v) => write!(f, "{}", v),
148 }
149 }
150}
151
152#[repr(transparent)]
153#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash)]
154pub struct DictionaryId(pub u64);
155
156impl Display for DictionaryId {
157 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
158 Display::fmt(&self.0, f)
159 }
160}
161
162impl Deref for DictionaryId {
163 type Target = u64;
164
165 fn deref(&self) -> &Self::Target {
166 &self.0
167 }
168}
169
170impl PartialEq<u64> for DictionaryId {
171 fn eq(&self, other: &u64) -> bool {
172 self.0.eq(other)
173 }
174}
175
176impl From<DictionaryId> for u64 {
177 fn from(value: DictionaryId) -> Self {
178 value.0
179 }
180}
181
182impl DictionaryId {
183 #[inline]
185 pub fn to_u64(self) -> u64 {
186 self.0
187 }
188}
189
190impl From<i32> for DictionaryId {
191 fn from(value: i32) -> Self {
192 Self(value as u64)
193 }
194}
195
196impl From<u64> for DictionaryId {
197 fn from(value: u64) -> Self {
198 Self(value)
199 }
200}
201
202impl Serialize for DictionaryId {
203 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
204 where
205 S: Serializer,
206 {
207 serializer.serialize_u64(self.0)
208 }
209}
210
211impl<'de> Deserialize<'de> for DictionaryId {
212 fn deserialize<D>(deserializer: D) -> Result<DictionaryId, D::Error>
213 where
214 D: Deserializer<'de>,
215 {
216 struct U64Visitor;
217
218 impl Visitor<'_> for U64Visitor {
219 type Value = DictionaryId;
220
221 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
222 formatter.write_str("an unsigned 64-bit number")
223 }
224
225 fn visit_u64<E>(self, value: u64) -> Result<Self::Value, E> {
226 Ok(DictionaryId(value))
227 }
228 }
229
230 deserializer.deserialize_u64(U64Visitor)
231 }
232}
233
234#[cfg(test)]
235pub mod tests {
236 use super::*;
237
238 #[test]
239 fn test_from_u128_u1() {
240 let id = DictionaryEntryId::from_u128(42, Type::Uint1).unwrap();
241 assert_eq!(id, DictionaryEntryId::U1(42));
242 assert_eq!(id.to_u128(), 42);
243 assert_eq!(id.id_type(), Type::Uint1);
244 }
245
246 #[test]
247 fn test_from_u128_u1_overflow() {
248 let err = DictionaryEntryId::from_u128(256, Type::Uint1).unwrap_err();
249 assert!(err.to_string().contains("DICT_001"));
250 }
251
252 #[test]
253 fn test_from_u128_u2() {
254 let id = DictionaryEntryId::from_u128(1000, Type::Uint2).unwrap();
255 assert_eq!(id, DictionaryEntryId::U2(1000));
256 assert_eq!(id.to_u128(), 1000);
257 }
258
259 #[test]
260 fn test_from_u128_u4() {
261 let id = DictionaryEntryId::from_u128(100_000, Type::Uint4).unwrap();
262 assert_eq!(id, DictionaryEntryId::U4(100_000));
263 assert_eq!(id.to_u128(), 100_000);
264 }
265
266 #[test]
267 fn test_from_u128_u8() {
268 let id = DictionaryEntryId::from_u128(10_000_000_000, Type::Uint8).unwrap();
269 assert_eq!(id, DictionaryEntryId::U8(10_000_000_000));
270 assert_eq!(id.to_u128(), 10_000_000_000);
271 }
272
273 #[test]
274 fn test_from_u128_u16() {
275 let large_value: u128 = u64::MAX as u128 + 1;
276 let id = DictionaryEntryId::from_u128(large_value, Type::Uint16).unwrap();
277 assert_eq!(id, DictionaryEntryId::U16(large_value));
278 assert_eq!(id.to_u128(), large_value);
279 }
280
281 #[test]
282 fn test_display() {
283 assert_eq!(format!("{}", DictionaryEntryId::U1(42)), "42");
284 assert_eq!(format!("{}", DictionaryEntryId::U8(12345)), "12345");
285 }
286}