Skip to main content

reifydb_type/value/
dictionary.rs

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