reifydb_core/key/
dictionary.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use super::{EncodableKey, EncodableKeyRange, KeyKind};
5use crate::{
6	EncodedKey, EncodedKeyRange,
7	interface::DictionaryId,
8	util::encoding::keycode::{KeyDeserializer, KeySerializer},
9};
10
11const VERSION: u8 = 1;
12
13/// Key for storing dictionary metadata
14#[derive(Debug, Clone, PartialEq)]
15pub struct DictionaryKey {
16	pub dictionary: DictionaryId,
17}
18
19impl DictionaryKey {
20	pub fn new(dictionary: DictionaryId) -> Self {
21		Self {
22			dictionary,
23		}
24	}
25
26	pub fn encoded(dictionary: impl Into<DictionaryId>) -> EncodedKey {
27		Self::new(dictionary.into()).encode()
28	}
29
30	pub fn full_scan() -> EncodedKeyRange {
31		EncodedKeyRange::start_end(Some(Self::dictionary_start()), Some(Self::dictionary_end()))
32	}
33
34	fn dictionary_start() -> EncodedKey {
35		let mut serializer = KeySerializer::with_capacity(2);
36		serializer.extend_u8(VERSION);
37		serializer.extend_u8(Self::KIND as u8);
38		serializer.to_encoded_key()
39	}
40
41	fn dictionary_end() -> EncodedKey {
42		let mut serializer = KeySerializer::with_capacity(2);
43		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8 - 1);
44		serializer.to_encoded_key()
45	}
46}
47
48impl EncodableKey for DictionaryKey {
49	const KIND: KeyKind = KeyKind::Dictionary;
50
51	fn encode(&self) -> EncodedKey {
52		let mut serializer = KeySerializer::with_capacity(10);
53		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
54		serializer.to_encoded_key()
55	}
56
57	fn decode(key: &EncodedKey) -> Option<Self> {
58		let mut de = KeyDeserializer::from_bytes(key.as_slice());
59
60		let version = de.read_u8().ok()?;
61		if version != VERSION {
62			return None;
63		}
64
65		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
66		if kind != Self::KIND {
67			return None;
68		}
69
70		let dictionary = de.read_u64().ok()?;
71
72		Some(Self {
73			dictionary: DictionaryId(dictionary),
74		})
75	}
76}
77
78/// Key for dictionary entries: hash(value) -> (id, value)
79/// Uses xxh3_128 hash of the value for fixed-size keys
80#[derive(Debug, Clone, PartialEq)]
81pub struct DictionaryEntryKey {
82	pub dictionary: DictionaryId,
83	pub hash: [u8; 16], // xxh3_128 hash of the value
84}
85
86impl DictionaryEntryKey {
87	pub fn new(dictionary: DictionaryId, hash: [u8; 16]) -> Self {
88		Self {
89			dictionary,
90			hash,
91		}
92	}
93
94	pub fn encoded(dictionary: impl Into<DictionaryId>, hash: [u8; 16]) -> EncodedKey {
95		Self::new(dictionary.into(), hash).encode()
96	}
97
98	pub fn full_scan(dictionary: DictionaryId) -> EncodedKeyRange {
99		EncodedKeyRange::start_end(Some(Self::entry_start(dictionary)), Some(Self::entry_end(dictionary)))
100	}
101
102	fn entry_start(dictionary: DictionaryId) -> EncodedKey {
103		let mut serializer = KeySerializer::with_capacity(10);
104		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(dictionary);
105		serializer.to_encoded_key()
106	}
107
108	fn entry_end(dictionary: DictionaryId) -> EncodedKey {
109		let mut serializer = KeySerializer::with_capacity(10);
110		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(*dictionary - 1);
111		serializer.to_encoded_key()
112	}
113}
114
115impl EncodableKey for DictionaryEntryKey {
116	const KIND: KeyKind = KeyKind::DictionaryEntry;
117
118	fn encode(&self) -> EncodedKey {
119		let mut serializer = KeySerializer::with_capacity(26);
120		serializer
121			.extend_u8(VERSION)
122			.extend_u8(Self::KIND as u8)
123			.extend_u64(self.dictionary)
124			.extend_bytes(&self.hash);
125		serializer.to_encoded_key()
126	}
127
128	fn decode(key: &EncodedKey) -> Option<Self> {
129		let mut de = KeyDeserializer::from_bytes(key.as_slice());
130
131		let version = de.read_u8().ok()?;
132		if version != VERSION {
133			return None;
134		}
135
136		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
137		if kind != Self::KIND {
138			return None;
139		}
140
141		let dictionary = de.read_u64().ok()?;
142		let hash_bytes = de.read_raw(16).ok()?;
143		let mut hash = [0u8; 16];
144		hash.copy_from_slice(hash_bytes);
145
146		Some(Self {
147			dictionary: DictionaryId(dictionary),
148			hash,
149		})
150	}
151}
152
153/// Key for reverse lookup: id -> row_number (for decoding)
154#[derive(Debug, Clone, PartialEq)]
155pub struct DictionaryEntryIndexKey {
156	pub dictionary: DictionaryId,
157	pub id: u64,
158}
159
160impl DictionaryEntryIndexKey {
161	pub fn new(dictionary: DictionaryId, id: u64) -> Self {
162		Self {
163			dictionary,
164			id,
165		}
166	}
167
168	pub fn encoded(dictionary: impl Into<DictionaryId>, id: u64) -> EncodedKey {
169		Self::new(dictionary.into(), id).encode()
170	}
171
172	pub fn full_scan(dictionary: DictionaryId) -> EncodedKeyRange {
173		EncodedKeyRange::start_end(Some(Self::index_start(dictionary)), Some(Self::index_end(dictionary)))
174	}
175
176	fn index_start(dictionary: DictionaryId) -> EncodedKey {
177		let mut serializer = KeySerializer::with_capacity(10);
178		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(dictionary);
179		serializer.to_encoded_key()
180	}
181
182	fn index_end(dictionary: DictionaryId) -> EncodedKey {
183		let mut serializer = KeySerializer::with_capacity(10);
184		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(*dictionary - 1);
185		serializer.to_encoded_key()
186	}
187}
188
189impl EncodableKey for DictionaryEntryIndexKey {
190	const KIND: KeyKind = KeyKind::DictionaryEntryIndex;
191
192	fn encode(&self) -> EncodedKey {
193		let mut serializer = KeySerializer::with_capacity(18);
194		serializer
195			.extend_u8(VERSION)
196			.extend_u8(Self::KIND as u8)
197			.extend_u64(self.dictionary)
198			.extend_u64(self.id);
199		serializer.to_encoded_key()
200	}
201
202	fn decode(key: &EncodedKey) -> Option<Self> {
203		let mut de = KeyDeserializer::from_bytes(key.as_slice());
204
205		let version = de.read_u8().ok()?;
206		if version != VERSION {
207			return None;
208		}
209
210		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
211		if kind != Self::KIND {
212			return None;
213		}
214
215		let dictionary = de.read_u64().ok()?;
216		let id = de.read_u64().ok()?;
217
218		Some(Self {
219			dictionary: DictionaryId(dictionary),
220			id,
221		})
222	}
223}
224
225/// Key for dictionary entry ID sequence
226#[derive(Debug, Clone, PartialEq)]
227pub struct DictionarySequenceKey {
228	pub dictionary: DictionaryId,
229}
230
231impl DictionarySequenceKey {
232	pub fn new(dictionary: DictionaryId) -> Self {
233		Self {
234			dictionary,
235		}
236	}
237
238	pub fn encoded(dictionary: impl Into<DictionaryId>) -> EncodedKey {
239		Self::new(dictionary.into()).encode()
240	}
241}
242
243impl EncodableKey for DictionarySequenceKey {
244	const KIND: KeyKind = KeyKind::DictionarySequence;
245
246	fn encode(&self) -> EncodedKey {
247		let mut serializer = KeySerializer::with_capacity(10);
248		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
249		serializer.to_encoded_key()
250	}
251
252	fn decode(key: &EncodedKey) -> Option<Self> {
253		let mut de = KeyDeserializer::from_bytes(key.as_slice());
254
255		let version = de.read_u8().ok()?;
256		if version != VERSION {
257			return None;
258		}
259
260		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
261		if kind != Self::KIND {
262			return None;
263		}
264
265		let dictionary = de.read_u64().ok()?;
266
267		Some(Self {
268			dictionary: DictionaryId(dictionary),
269		})
270	}
271}
272
273/// Key range for dictionary entry index scans
274#[derive(Debug, Clone, PartialEq)]
275pub struct DictionaryEntryIndexKeyRange {
276	pub dictionary: DictionaryId,
277	pub start_id: Option<u64>,
278	pub end_id: Option<u64>,
279}
280
281impl DictionaryEntryIndexKeyRange {
282	pub fn new(dictionary: DictionaryId, start_id: Option<u64>, end_id: Option<u64>) -> Self {
283		Self {
284			dictionary,
285			start_id,
286			end_id,
287		}
288	}
289
290	pub fn full(dictionary: DictionaryId) -> Self {
291		Self {
292			dictionary,
293			start_id: None,
294			end_id: None,
295		}
296	}
297}
298
299impl EncodableKeyRange for DictionaryEntryIndexKeyRange {
300	const KIND: KeyKind = KeyKind::DictionaryEntryIndex;
301
302	fn start(&self) -> Option<EncodedKey> {
303		let mut serializer = KeySerializer::with_capacity(18);
304		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(self.dictionary);
305		if let Some(id) = self.start_id {
306			serializer.extend_u64(id);
307		}
308		Some(serializer.to_encoded_key())
309	}
310
311	fn end(&self) -> Option<EncodedKey> {
312		if let Some(id) = self.end_id {
313			let mut serializer = KeySerializer::with_capacity(18);
314			serializer
315				.extend_u8(VERSION)
316				.extend_u8(Self::KIND as u8)
317				.extend_u64(self.dictionary)
318				.extend_u64(id - 1);
319			Some(serializer.to_encoded_key())
320		} else {
321			let mut serializer = KeySerializer::with_capacity(10);
322			serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(*self.dictionary - 1);
323			Some(serializer.to_encoded_key())
324		}
325	}
326
327	fn decode(_range: &EncodedKeyRange) -> (Option<Self>, Option<Self>) {
328		// Range decoding not typically needed
329		(None, None)
330	}
331}
332
333#[cfg(test)]
334mod tests {
335	use super::*;
336
337	#[test]
338	fn test_dictionary_key_encode_decode() {
339		let key = DictionaryKey {
340			dictionary: DictionaryId(0x1234),
341		};
342		let encoded = key.encode();
343		let decoded = DictionaryKey::decode(&encoded).unwrap();
344		assert_eq!(decoded.dictionary, key.dictionary);
345	}
346
347	#[test]
348	fn test_dictionary_entry_key_encode_decode() {
349		let key = DictionaryEntryKey {
350			dictionary: DictionaryId(42),
351			hash: [
352				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
353				0x0f, 0x10,
354			],
355		};
356		let encoded = key.encode();
357		let decoded = DictionaryEntryKey::decode(&encoded).unwrap();
358		assert_eq!(decoded.dictionary, key.dictionary);
359		assert_eq!(decoded.hash, key.hash);
360	}
361
362	#[test]
363	fn test_dictionary_entry_index_key_encode_decode() {
364		let key = DictionaryEntryIndexKey {
365			dictionary: DictionaryId(99),
366			id: 12345,
367		};
368		let encoded = key.encode();
369		let decoded = DictionaryEntryIndexKey::decode(&encoded).unwrap();
370		assert_eq!(decoded.dictionary, key.dictionary);
371		assert_eq!(decoded.id, key.id);
372	}
373
374	#[test]
375	fn test_dictionary_sequence_key_encode_decode() {
376		let key = DictionarySequenceKey {
377			dictionary: DictionaryId(7),
378		};
379		let encoded = key.encode();
380		let decoded = DictionarySequenceKey::decode(&encoded).unwrap();
381		assert_eq!(decoded.dictionary, key.dictionary);
382	}
383
384	#[test]
385	fn test_dictionary_key_full_scan() {
386		use std::ops::Bound;
387		let range = DictionaryKey::full_scan();
388		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
389		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
390	}
391
392	#[test]
393	fn test_dictionary_entry_key_full_scan() {
394		use std::ops::Bound;
395		let range = DictionaryEntryKey::full_scan(DictionaryId(42));
396		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
397		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
398	}
399
400	#[test]
401	fn test_dictionary_entry_index_key_full_scan() {
402		use std::ops::Bound;
403		let range = DictionaryEntryIndexKey::full_scan(DictionaryId(42));
404		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
405		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
406	}
407
408	#[test]
409	fn test_dictionary_entry_index_key_range() {
410		let range = DictionaryEntryIndexKeyRange::full(DictionaryId(42));
411		let start = range.start();
412		let end = range.end();
413		assert!(start.is_some());
414		assert!(end.is_some());
415	}
416}