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