Skip to main content

reifydb_core/key/
dictionary.rs

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