Skip to main content

reifydb_type/value/
dictionary.rs

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