Skip to main content

reifydb_core/key/
catalog.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::{borrow::Cow, collections::Bound};
5
6use reifydb_codec::key::{
7	ByteSink, decode_u64_from,
8	deserializer::KeyDeserializer,
9	encode_u64,
10	encoded::{EncodedKey, EncodedKeyBuilder, EncodedKeyRange},
11	serializer::KeySerializer,
12};
13use reifydb_macro::KeyCodec;
14use reifydb_value::{
15	Result,
16	value::{dictionary::DictionaryId, sumtype::SumTypeId},
17};
18use smallvec::{SmallVec, smallvec};
19
20use super::{KeyRangeCodec, KeyTag};
21use crate::{
22	interface::catalog::{
23		id::{
24			BindingId, ColumnId, ColumnPropertyId, HandlerId, IndexId, NamespaceId, PrimaryKeyId,
25			RelationshipId, SinkId, SourceId, TableId, ViewId,
26		},
27		object::ObjectId,
28	},
29	key::{
30		any::{Field, KeyFields, RawEncoding, Width, index_tag},
31		bound::{TaggedKeyBound, TaggedKeyBoundRange, object_fields},
32	},
33	return_internal_error,
34	value::index::{encoded::EncodedIndexKey, range::EncodedIndexKeyRange},
35};
36
37pub fn serialize_object_id<B: ByteSink>(object: &ObjectId, out: &mut B) {
38	out.push(object.type_tag());
39	out.extend_from_slice(&encode_u64(object.as_u64()));
40}
41
42pub fn deserialize_object_id(input: &mut &[u8]) -> Result<ObjectId> {
43	if input.is_empty() {
44		return_internal_error!("Invalid ObjectId encoding: empty input");
45	}
46
47	let type_byte = input[0];
48	*input = &input[1..];
49	let id = decode_u64_from(input)?;
50
51	match ObjectId::from_type_tag(type_byte, id) {
52		Some(object) => Ok(object),
53		None => return_internal_error!("Invalid ObjectId type byte: 0x{:02x}.", type_byte),
54	}
55}
56
57pub fn serialize_index_id<B: ByteSink>(index: &IndexId, out: &mut B) {
58	match index {
59		IndexId::Primary(PrimaryKeyId(id)) => {
60			out.push(0x01);
61			out.extend_from_slice(&encode_u64(*id));
62		}
63	}
64}
65
66pub fn deserialize_index_id(input: &mut &[u8]) -> Result<IndexId> {
67	if input.is_empty() {
68		return_internal_error!("Invalid IndexId encoding: empty input");
69	}
70
71	let type_byte = input[0];
72	*input = &input[1..];
73	let id = decode_u64_from(input)?;
74
75	match type_byte {
76		0x01 => Ok(IndexId::Primary(PrimaryKeyId(id))),
77
78		_ => return_internal_error!("Invalid IndexId type byte: 0x{:02x}.", type_byte),
79	}
80}
81
82pub trait KeySerializerCatalogExt {
83	fn extend_object_id(&mut self, object: impl Into<ObjectId>) -> &mut Self;
84	fn extend_index_id(&mut self, index: impl Into<IndexId>) -> &mut Self;
85}
86
87impl KeySerializerCatalogExt for KeySerializer {
88	fn extend_object_id(&mut self, object: impl Into<ObjectId>) -> &mut Self {
89		let mut buf = Vec::new();
90		serialize_object_id(&object.into(), &mut buf);
91		self.extend_raw(&buf);
92		self
93	}
94
95	fn extend_index_id(&mut self, index: impl Into<IndexId>) -> &mut Self {
96		let mut buf = Vec::new();
97		serialize_index_id(&index.into(), &mut buf);
98		self.extend_raw(&buf);
99		self
100	}
101}
102
103pub trait KeyDeserializerCatalogExt {
104	fn read_object_id(&mut self) -> Result<ObjectId>;
105	fn read_index_id(&mut self) -> Result<IndexId>;
106}
107
108impl KeyDeserializerCatalogExt for KeyDeserializer<'_> {
109	fn read_object_id(&mut self) -> Result<ObjectId> {
110		let mut slice = self.remaining_bytes();
111		let before = slice.len();
112		let object_id = deserialize_object_id(&mut slice)?;
113		self.read_raw(before - slice.len())?;
114		Ok(object_id)
115	}
116
117	fn read_index_id(&mut self) -> Result<IndexId> {
118		let mut slice = self.remaining_bytes();
119		let before = slice.len();
120		let index_id = deserialize_index_id(&mut slice)?;
121		self.read_raw(before - slice.len())?;
122		Ok(index_id)
123	}
124}
125
126pub trait EncodedKeyBuilderCatalogExt {
127	fn object_id(self, object: impl Into<ObjectId>) -> Self;
128	fn index_id(self, index: impl Into<IndexId>) -> Self;
129}
130
131impl EncodedKeyBuilderCatalogExt for EncodedKeyBuilder {
132	fn object_id(self, object: impl Into<ObjectId>) -> Self {
133		let mut buf = Vec::new();
134		serialize_object_id(&object.into(), &mut buf);
135		self.raw(&buf)
136	}
137
138	fn index_id(self, index: impl Into<IndexId>) -> Self {
139		let mut buf = Vec::new();
140		serialize_index_id(&index.into(), &mut buf);
141		self.raw(&buf)
142	}
143}
144
145#[cfg(test)]
146pub mod index_entry_key_tests {
147	use reifydb_codec::key::encode_u64;
148
149	use super::{
150		serialize_index_id as serialize_index_id_inner, serialize_object_id as serialize_object_id_inner, *,
151	};
152	use crate::interface::catalog::vtable::VTableId;
153
154	fn serialize_object_id(object: &ObjectId) -> Vec<u8> {
155		let mut out = Vec::new();
156		serialize_object_id_inner(object, &mut out);
157		out
158	}
159
160	fn serialize_index_id(index: &IndexId) -> Vec<u8> {
161		let mut out = Vec::new();
162		serialize_index_id_inner(index, &mut out);
163		out
164	}
165
166	#[test]
167	fn test_object_id_ordering() {
168		let object1 = ObjectId::table(1);
169		let object2 = ObjectId::table(2);
170		let object100 = ObjectId::table(100);
171		let object200 = ObjectId::table(200);
172
173		let bytes1 = serialize_object_id(&object1);
174		let bytes2 = serialize_object_id(&object2);
175		let bytes100 = serialize_object_id(&object100);
176		let bytes200 = serialize_object_id(&object200);
177
178		assert!(bytes2 < bytes1, "object(2) should be < object(1) in bytes");
179		assert!(bytes200 < bytes100, "object(200) should be < object(100) in bytes");
180		assert!(bytes100 < bytes2, "object(100) should be < object(2) in bytes");
181	}
182
183	#[test]
184	fn test_range_boundaries() {
185		let object10 = ObjectId::table(10);
186		let object9 = object10.prev();
187
188		let bytes10 = serialize_object_id(&object10);
189		let bytes9 = serialize_object_id(&object9);
190
191		assert!(bytes9 > bytes10, "object(9) should be > object(10) in bytes");
192
193		let view10 = ObjectId::view(10);
194		let view9 = view10.prev();
195
196		let vbytes10 = serialize_object_id(&view10);
197		let vbytes9 = serialize_object_id(&view9);
198
199		assert!(vbytes9 > vbytes10, "view(9) should be > view(10) in bytes");
200
201		let virtual10 = ObjectId::vtable(10);
202		let virtual9 = virtual10.prev();
203
204		let tvbytes10 = serialize_object_id(&virtual10);
205		let tvbytes9 = serialize_object_id(&virtual9);
206
207		assert!(tvbytes9 > tvbytes10, "vtable(9) should be > vtable(10) in bytes");
208
209		assert_ne!(bytes10, vbytes10, "table(10) should != view(10)");
210		assert_ne!(bytes10, tvbytes10, "table(10) should != vtable(10)");
211		assert_ne!(vbytes10, tvbytes10, "view(10) should != vtable(10)");
212		assert_eq!(bytes10[0], 0x01, "table type byte should be 0x01");
213		assert_eq!(vbytes10[0], 0x02, "view type byte should be 0x02");
214		assert_eq!(tvbytes10[0], 0x03, "vtable type byte should be 0x03");
215
216		let row_key_10_100 = vec![0xFC];
217		let mut key1 = row_key_10_100.clone();
218		key1.extend(&bytes10);
219		key1.extend(&encode_u64(100u64));
220
221		let mut key2 = row_key_10_100.clone();
222		key2.extend(&bytes10);
223		key2.extend(&encode_u64(200u64));
224
225		let mut end_key = vec![0xFC];
226		end_key.extend(&bytes9);
227
228		assert!(key1 >= bytes10, "key1 should be >= start(object10)");
229		assert!(key1 < end_key, "key1 should be < end(object9)");
230		assert!(key2 >= bytes10, "key2 should be >= start(object10)");
231		assert!(key2 < end_key, "key2 should be < end(object9)");
232	}
233
234	#[test]
235	fn test_vtable_serialization() {
236		let virtual_object = ObjectId::vtable(42);
237		let bytes = serialize_object_id(&virtual_object);
238		let mut slice = &bytes[..];
239		let deserialized = deserialize_object_id(&mut slice).unwrap();
240		assert_eq!(virtual_object, deserialized);
241		assert!(slice.is_empty());
242
243		assert_eq!(bytes[0], 0x03);
244
245		let virtual_id = VTableId(123);
246		let object_from_id = ObjectId::from(virtual_id);
247		let bytes_from_id = serialize_object_id(&object_from_id);
248		let mut slice = &bytes_from_id[..];
249		let deserialized_id = deserialize_object_id(&mut slice).unwrap();
250		assert_eq!(object_from_id, deserialized_id);
251		assert!(slice.is_empty());
252
253		let virtual1 = ObjectId::vtable(1);
254		let virtual2 = ObjectId::vtable(2);
255		let bytes1 = serialize_object_id(&virtual1);
256		let bytes2 = serialize_object_id(&virtual2);
257
258		assert!(bytes2 < bytes1, "vtable(2) should be < vtable(1) in bytes");
259	}
260
261	#[test]
262	fn test_index_id_serialization() {
263		let index = IndexId::primary(42);
264		let bytes = serialize_index_id(&index);
265		let mut slice = &bytes[..];
266		let deserialized = deserialize_index_id(&mut slice).unwrap();
267		assert_eq!(index.as_u64(), deserialized.as_u64());
268		assert!(slice.is_empty());
269
270		assert_eq!(bytes[0], 0x01);
271
272		let primary_id = PrimaryKeyId(123);
273		let index_from_id = IndexId::Primary(primary_id);
274		let bytes_from_id = serialize_index_id(&index_from_id);
275		let mut slice = &bytes_from_id[..];
276		let deserialized_id = deserialize_index_id(&mut slice).unwrap();
277		assert_eq!(index_from_id.as_u64(), deserialized_id.as_u64());
278		assert!(slice.is_empty());
279	}
280
281	#[test]
282	fn test_index_id_ordering() {
283		let index1 = IndexId::primary(1);
284		let index2 = IndexId::primary(2);
285		let index100 = IndexId::primary(100);
286		let index200 = IndexId::primary(200);
287
288		let bytes1 = serialize_index_id(&index1);
289		let bytes2 = serialize_index_id(&index2);
290		let bytes100 = serialize_index_id(&index100);
291		let bytes200 = serialize_index_id(&index200);
292
293		assert!(bytes2 < bytes1, "index(2) should be < index(1) in bytes");
294		assert!(bytes200 < bytes100, "index(200) should be < index(100) in bytes");
295		assert!(bytes100 < bytes2, "index(100) should be < index(2) in bytes");
296	}
297
298	#[test]
299	fn test_index_id_range_boundaries() {
300		let index10 = IndexId::primary(10);
301		let index11 = IndexId::primary(11);
302
303		let bytes10 = serialize_index_id(&index10);
304		let bytes11 = serialize_index_id(&index11);
305
306		assert!(bytes11 < bytes10, "index(11) should be < index(10) in bytes");
307
308		assert_eq!(bytes10.len(), 9, "IndexId(10) should be 9 bytes");
309		assert_eq!(bytes10[0], 0x01, "Primary variant should have type byte 0x01");
310
311		let next_index = IndexId::primary(11);
312		let next_bytes = serialize_index_id(&next_index);
313
314		assert!(next_bytes < bytes10, "index(11) should be < index(10) for proper range boundaries");
315	}
316
317	#[test]
318	fn test_index_entry_key_encoding_with_discriminator() {
319		let object = ObjectId::table(42);
320		let index = IndexId::primary(7);
321
322		let object_bytes = serialize_object_id(&object);
323		let index_bytes = serialize_index_id(&index);
324
325		assert_eq!(object_bytes.len(), 9, "ObjectId(42) should be 9 bytes");
326		assert_eq!(index_bytes.len(), 9, "IndexId(7) should be 9 bytes");
327
328		assert_eq!(object_bytes[0], 0x01, "Table object should have type byte 0x01");
329		assert_eq!(index_bytes[0], 0x01, "Primary index should have type byte 0x01");
330
331		let total_prefix_size = 1 + 1 + object_bytes.len() + index_bytes.len();
332		assert_eq!(total_prefix_size, 20, "Total IndexEntryKey prefix should be 20 bytes");
333	}
334}
335
336#[cfg(test)]
337mod moved_catalog_key_tests {
338	use reifydb_codec::key::{deserializer::KeyDeserializer, serializer::KeySerializer};
339
340	use super::{KeyDeserializerCatalogExt, KeySerializerCatalogExt};
341	use crate::interface::catalog::{
342		id::{IndexId, PrimaryKeyId, TableId},
343		object::ObjectId,
344	};
345
346	#[test]
347	fn test_index_id() {
348		let mut serializer = KeySerializer::new();
349		serializer.extend_index_id(IndexId::Primary(PrimaryKeyId(123456789)));
350		let result = serializer.finish();
351
352		// A fixed-width id keeps every IndexId the same length, so a constant prefix scan stays exact.
353		assert_eq!(result.len(), 9);
354		assert_eq!(result[0], 0x01); // Primary variant prefix
355
356		// Ids are stored bitwise-inverted, so the smaller id encodes to the larger bytes; the
357		// comparison skips byte 0 because that is the variant prefix.
358		let mut serializer2 = KeySerializer::new();
359		serializer2.extend_index_id(IndexId::Primary(PrimaryKeyId(1)));
360		let result2 = serializer2.finish();
361
362		assert!(result2[1..] > result[1..]);
363	}
364
365	#[test]
366	fn test_object_id() {
367		let mut serializer = KeySerializer::new();
368		serializer.extend_object_id(ObjectId::Table(TableId(987654321)));
369		let result = serializer.finish();
370
371		// A fixed-width id keeps every ObjectId the same length, so a constant prefix scan stays exact.
372		assert_eq!(result.len(), 9);
373		assert_eq!(result[0], 0x01); // Table variant prefix
374
375		// Inverted encoding: the larger id sorts below the smaller one; byte 0 is the variant prefix.
376		let mut serializer2 = KeySerializer::new();
377		serializer2.extend_object_id(ObjectId::Table(TableId(987654322)));
378		let result2 = serializer2.finish();
379
380		assert!(result2[1..] < result[1..]);
381	}
382
383	#[test]
384	fn test_read_object_id() {
385		let mut ser = KeySerializer::new();
386		let object = ObjectId::table(42);
387		ser.extend_object_id(object);
388		let bytes = ser.finish();
389
390		let mut de = KeyDeserializer::from_bytes(&bytes);
391		assert_eq!(de.read_object_id().unwrap(), object);
392		assert!(de.is_empty());
393	}
394
395	#[test]
396	fn test_read_index_id() {
397		let mut ser = KeySerializer::new();
398		let index = IndexId::primary(999);
399		ser.extend_index_id(index);
400		let bytes = ser.finish();
401
402		let mut de = KeyDeserializer::from_bytes(&bytes);
403		assert_eq!(de.read_index_id().unwrap(), index);
404		assert!(de.is_empty());
405	}
406}
407
408#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
409#[key(tag = Dictionary)]
410pub struct DictionaryKey {
411	pub dictionary: DictionaryId,
412}
413
414impl DictionaryKey {
415	pub fn new(dictionary: DictionaryId) -> Self {
416		Self {
417			dictionary,
418		}
419	}
420
421	pub fn encoded(dictionary: impl Into<DictionaryId>) -> EncodedKey {
422		Self::new(dictionary.into()).encode()
423	}
424
425	pub fn full_scan() -> TaggedKeyBoundRange {
426		TaggedKeyBoundRange::kind(Self::TAG)
427	}
428}
429
430#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
431#[key(tag = DictionaryEntry)]
432pub struct DictionaryEntryKey {
433	pub dictionary: DictionaryId,
434	pub hash: [u8; 16],
435}
436
437impl DictionaryEntryKey {
438	pub fn new(dictionary: DictionaryId, hash: [u8; 16]) -> Self {
439		Self {
440			dictionary,
441			hash,
442		}
443	}
444
445	pub fn encoded(dictionary: impl Into<DictionaryId>, hash: [u8; 16]) -> EncodedKey {
446		Self::new(dictionary.into(), hash).encode()
447	}
448
449	pub fn full_scan(dictionary: DictionaryId) -> TaggedKeyBoundRange {
450		TaggedKeyBoundRange::prefix(Self::TAG, [Field::UDesc(Width::U64, dictionary.0 as u128)])
451	}
452}
453
454#[derive(Debug, Clone, PartialEq, Hash)]
455pub struct DictionaryEntryIndexKey {
456	pub dictionary: DictionaryId,
457	pub id: u128,
458}
459
460impl DictionaryEntryIndexKey {
461	pub fn new(dictionary: DictionaryId, id: u128) -> Self {
462		Self {
463			dictionary,
464			id,
465		}
466	}
467
468	pub fn encoded(dictionary: impl Into<DictionaryId>, id: u128) -> EncodedKey {
469		Self::new(dictionary.into(), id).encode()
470	}
471
472	pub fn full_scan(dictionary: DictionaryId) -> TaggedKeyBoundRange {
473		TaggedKeyBoundRange::prefix(Self::TAG, [Field::UDesc(Width::U64, dictionary.0 as u128)])
474	}
475}
476
477impl DictionaryEntryIndexKey {
478	pub const TAG: KeyTag = KeyTag::DictionaryEntryIndex;
479
480	pub fn encode(&self) -> EncodedKey {
481		let mut serializer = KeySerializer::with_capacity(25);
482		serializer.extend_u8(Self::TAG as u8).extend_u64(self.dictionary).extend_u128_varint(self.id);
483		serializer.to_encoded_key()
484	}
485
486	pub fn decode(key: &EncodedKey) -> Option<Self> {
487		let mut de = KeyDeserializer::from_bytes(key.as_slice());
488
489		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
490		if kind != Self::TAG {
491			return None;
492		}
493
494		let dictionary = de.read_u64().ok()?;
495		let id = de.read_u128_varint().ok()?;
496
497		Some(Self {
498			dictionary: DictionaryId(dictionary),
499			id,
500		})
501	}
502}
503
504#[derive(Debug, Clone, PartialEq)]
505pub struct DictionaryEntryIndexKeyRange {
506	pub dictionary: DictionaryId,
507	pub start_id: Option<u128>,
508	pub end_id: Option<u128>,
509}
510
511impl DictionaryEntryIndexKeyRange {
512	pub fn new(dictionary: DictionaryId, start_id: Option<u128>, end_id: Option<u128>) -> Self {
513		Self {
514			dictionary,
515			start_id,
516			end_id,
517		}
518	}
519
520	pub fn full(dictionary: DictionaryId) -> Self {
521		Self {
522			dictionary,
523			start_id: None,
524			end_id: None,
525		}
526	}
527}
528
529impl KeyRangeCodec for DictionaryEntryIndexKeyRange {
530	const TAG: KeyTag = KeyTag::DictionaryEntryIndex;
531
532	fn start(&self) -> Option<EncodedKey> {
533		let mut serializer = KeySerializer::with_capacity(25);
534		serializer.extend_u8(Self::TAG as u8).extend_u64(self.dictionary);
535		if let Some(id) = self.start_id {
536			serializer.extend_u128_varint(id);
537		}
538		Some(serializer.to_encoded_key())
539	}
540
541	fn end(&self) -> Option<EncodedKey> {
542		if let Some(id) = self.end_id {
543			let mut serializer = KeySerializer::with_capacity(25);
544			serializer.extend_u8(Self::TAG as u8).extend_u64(self.dictionary).extend_u128_varint(id - 1);
545			Some(serializer.to_encoded_key())
546		} else {
547			let mut serializer = KeySerializer::with_capacity(9);
548			serializer.extend_u8(Self::TAG as u8).extend_u64(*self.dictionary - 1);
549			Some(serializer.to_encoded_key())
550		}
551	}
552
553	fn decode(_range: &EncodedKeyRange) -> (Option<Self>, Option<Self>) {
554		(None, None)
555	}
556}
557
558#[cfg(test)]
559pub mod dictionary_key_tests {
560	use std::ops::Bound;
561
562	use super::*;
563
564	#[test]
565	fn test_dictionary_key_encode_decode() {
566		let key = DictionaryKey {
567			dictionary: DictionaryId(0x1234),
568		};
569		let encoded = key.encode();
570		let decoded = DictionaryKey::decode(&encoded).unwrap();
571		assert_eq!(decoded.dictionary, key.dictionary);
572	}
573
574	#[test]
575	fn test_dictionary_entry_key_encode_decode() {
576		let key = DictionaryEntryKey {
577			dictionary: DictionaryId(42),
578			hash: [
579				0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
580				0x0f, 0x10,
581			],
582		};
583		let encoded = key.encode();
584		let decoded = DictionaryEntryKey::decode(&encoded).unwrap();
585		assert_eq!(decoded.dictionary, key.dictionary);
586		assert_eq!(decoded.hash, key.hash);
587	}
588
589	#[test]
590	fn a_dictionary_entry_hash_made_of_0xff_bytes_still_round_trips() {
591		// the hand-rolled encoder escaped 0xff and appended a terminator while decode read 16 raw
592		// bytes, so any hash carrying an 0xff came back shifted and the key ran two bytes long
593		let key = DictionaryEntryKey {
594			dictionary: DictionaryId(42),
595			hash: [0xff; 16],
596		};
597		let encoded = key.encode();
598		assert_eq!(encoded.len(), 1 + 8 + 16);
599		assert_eq!(DictionaryEntryKey::decode(&encoded).unwrap(), key);
600	}
601
602	#[test]
603	fn test_dictionary_entry_index_key_encode_decode() {
604		let key = DictionaryEntryIndexKey {
605			dictionary: DictionaryId(99),
606			id: 12345,
607		};
608		let encoded = key.encode();
609		let decoded = DictionaryEntryIndexKey::decode(&encoded).unwrap();
610		assert_eq!(decoded.dictionary, key.dictionary);
611		assert_eq!(decoded.id, key.id);
612	}
613
614	#[test]
615	fn test_dictionary_key_full_scan() {
616		let range = DictionaryKey::full_scan();
617		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
618		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
619	}
620
621	#[test]
622	fn test_dictionary_entry_key_full_scan() {
623		let range = DictionaryEntryKey::full_scan(DictionaryId(42)).encode();
624		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
625		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
626	}
627
628	#[test]
629	fn test_dictionary_entry_index_key_full_scan() {
630		let range = DictionaryEntryIndexKey::full_scan(DictionaryId(42)).encode();
631		assert!(matches!(range.start, Bound::Included(_) | Bound::Excluded(_)));
632		assert!(matches!(range.end, Bound::Included(_) | Bound::Excluded(_)));
633	}
634
635	#[test]
636	fn test_dictionary_entry_index_key_range() {
637		let range = DictionaryEntryIndexKeyRange::full(DictionaryId(42));
638		let start = range.start();
639		let end = range.end();
640		assert!(start.is_some());
641		assert!(end.is_some());
642	}
643}
644
645#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
646#[key(tag = Index)]
647pub struct IndexKey {
648	pub object: ObjectId,
649	pub index: IndexId,
650}
651
652#[derive(Debug, Clone, PartialEq)]
653pub struct ObjectIndexKeyRange {
654	pub object: ObjectId,
655}
656
657impl ObjectIndexKeyRange {
658	fn decode_key(key: &EncodedKey) -> Option<Self> {
659		let mut de = KeyDeserializer::from_bytes(key.as_slice());
660
661		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
662		if kind != Self::TAG {
663			return None;
664		}
665
666		let object = de.read_object_id().ok()?;
667
668		Some(ObjectIndexKeyRange {
669			object,
670		})
671	}
672}
673
674impl KeyRangeCodec for ObjectIndexKeyRange {
675	const TAG: KeyTag = KeyTag::Index;
676
677	fn start(&self) -> Option<EncodedKey> {
678		let mut serializer = KeySerializer::with_capacity(10);
679		serializer.extend_u8(Self::TAG as u8).extend_object_id(self.object);
680		Some(serializer.to_encoded_key())
681	}
682
683	fn end(&self) -> Option<EncodedKey> {
684		let mut serializer = KeySerializer::with_capacity(10);
685		serializer.extend_u8(Self::TAG as u8).extend_object_id(self.object.prev());
686		Some(serializer.to_encoded_key())
687	}
688
689	fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
690	where
691		Self: Sized,
692	{
693		let start_key = match &range.start {
694			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
695			Bound::Unbounded => None,
696		};
697
698		let end_key = match &range.end {
699			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
700			Bound::Unbounded => None,
701		};
702
703		(start_key, end_key)
704	}
705}
706
707impl IndexKey {
708	pub fn new(object: impl Into<ObjectId>, index: impl Into<IndexId>) -> Self {
709		Self {
710			object: object.into(),
711			index: index.into(),
712		}
713	}
714
715	pub fn encoded(object: impl Into<ObjectId>, index: impl Into<IndexId>) -> EncodedKey {
716		Self {
717			object: object.into(),
718			index: index.into(),
719		}
720		.encode()
721	}
722
723	pub fn full_scan(object: impl Into<ObjectId>) -> TaggedKeyBoundRange {
724		TaggedKeyBoundRange::prefix(Self::TAG, object_fields(object.into()))
725	}
726}
727
728#[cfg(test)]
729pub mod index_key_tests {
730	use super::IndexKey;
731	use crate::interface::catalog::{id::IndexId, object::ObjectId};
732
733	#[test]
734	fn test_encode_decode() {
735		let key = IndexKey {
736			object: ObjectId::table(0xABCD),
737			index: IndexId::primary(0x123456789ABCDEF0u64),
738		};
739		let encoded = key.encode();
740
741		let expected: Vec<u8> = vec![
742			0xF3, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, 0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43,
743			0x21, 0x0F,
744		];
745
746		assert_eq!(encoded.as_slice(), expected);
747
748		let key = IndexKey::decode(&encoded).unwrap();
749		assert_eq!(key.object, 0xABCD);
750		assert_eq!(key.index, 0x123456789ABCDEF0);
751	}
752
753	#[test]
754	fn test_order_preserving() {
755		let key1 = IndexKey {
756			object: ObjectId::table(1),
757			index: IndexId::primary(100),
758		};
759		let key2 = IndexKey {
760			object: ObjectId::table(1),
761			index: IndexId::primary(200),
762		};
763		let key3 = IndexKey {
764			object: ObjectId::table(2),
765			index: IndexId::primary(50),
766		};
767
768		let encoded1 = key1.encode();
769		let encoded2 = key2.encode();
770		let encoded3 = key3.encode();
771
772		assert!(encoded3 < encoded2, "ordering not preserved");
773		assert!(encoded2 < encoded1, "ordering not preserved");
774	}
775}
776
777#[derive(Debug, Clone, PartialEq, Hash)]
778pub struct IndexEntryKey {
779	pub object: ObjectId,
780	pub index: IndexId,
781	pub key: EncodedIndexKey,
782}
783
784impl IndexEntryKey {
785	pub fn new(object: impl Into<ObjectId>, index: IndexId, key: EncodedIndexKey) -> Self {
786		Self {
787			object: object.into(),
788			index,
789			key,
790		}
791	}
792
793	pub fn encoded(object: impl Into<ObjectId>, index: IndexId, key: EncodedIndexKey) -> EncodedKey {
794		Self::new(object, index, key).encode()
795	}
796}
797
798#[derive(Debug, Clone, PartialEq)]
799pub struct IndexEntryKeyRange {
800	pub object: ObjectId,
801	pub index: IndexId,
802}
803
804impl IndexEntryKeyRange {
805	fn decode_key(key: &EncodedKey) -> Option<Self> {
806		let mut de = KeyDeserializer::from_bytes(key.as_slice());
807
808		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
809		if kind != Self::TAG {
810			return None;
811		}
812
813		let object = de.read_object_id().ok()?;
814		let index = de.read_index_id().ok()?;
815
816		Some(IndexEntryKeyRange {
817			object,
818			index,
819		})
820	}
821}
822
823impl KeyRangeCodec for IndexEntryKeyRange {
824	const TAG: KeyTag = KeyTag::IndexEntry;
825
826	fn start(&self) -> Option<EncodedKey> {
827		let mut serializer = KeySerializer::with_capacity(19);
828		serializer.extend_u8(Self::TAG as u8).extend_object_id(self.object).extend_index_id(self.index);
829		Some(serializer.to_encoded_key())
830	}
831
832	fn end(&self) -> Option<EncodedKey> {
833		let mut serializer = KeySerializer::with_capacity(19);
834		serializer.extend_u8(Self::TAG as u8).extend_object_id(self.object).extend_index_id(self.index.prev());
835		Some(serializer.to_encoded_key())
836	}
837
838	fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
839	where
840		Self: Sized,
841	{
842		let start_key = match &range.start {
843			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
844			Bound::Unbounded => None,
845		};
846
847		let end_key = match &range.end {
848			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
849			Bound::Unbounded => None,
850		};
851
852		(start_key, end_key)
853	}
854}
855
856impl IndexEntryKey {
857	pub const TAG: KeyTag = KeyTag::IndexEntry;
858
859	pub fn encode(&self) -> EncodedKey {
860		let mut serializer = KeySerializer::with_capacity(20 + self.key.len());
861		serializer
862			.extend_u8(Self::TAG as u8)
863			.extend_object_id(self.object)
864			.extend_index_id(self.index)
865			.extend_raw(self.key.as_slice());
866		serializer.to_encoded_key()
867	}
868
869	pub fn decode(key: &EncodedKey) -> Option<Self> {
870		let mut de = KeyDeserializer::from_bytes(key.as_slice());
871
872		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
873		if kind != Self::TAG {
874			return None;
875		}
876
877		let object = de.read_object_id().ok()?;
878		let index = de.read_index_id().ok()?;
879
880		let remaining = de.remaining();
881		let remaining_bytes = de.read_raw(remaining).ok()?;
882		Some(Self {
883			object,
884			index,
885			key: EncodedIndexKey::new(remaining_bytes),
886		})
887	}
888}
889
890impl IndexEntryKey {
891	pub fn index_range(object: impl Into<ObjectId>, index: IndexId) -> TaggedKeyBoundRange {
892		let object = object.into();
893		TaggedKeyBoundRange::prefix(
894			<IndexEntryKeyRange as KeyRangeCodec>::TAG,
895			object_fields(object)
896				.into_iter()
897				.chain([Field::UAsc(Width::U8, 1), Field::UDesc(Width::U64, index.as_u64() as u128)]),
898		)
899	}
900
901	pub fn object_range(object: impl Into<ObjectId>) -> TaggedKeyBoundRange {
902		TaggedKeyBoundRange::prefix(KeyTag::IndexEntry, object_fields(object.into()))
903	}
904
905	pub fn key_prefix_range(object: impl Into<ObjectId>, index: IndexId, key_prefix: &[u8]) -> TaggedKeyBoundRange {
906		let object = object.into();
907		TaggedKeyBoundRange::prefix(
908			KeyTag::IndexEntry,
909			object_fields(object).into_iter().chain([
910				Field::UAsc(Width::U8, 1),
911				Field::UDesc(Width::U64, index.as_u64() as u128),
912				Field::RawAsc(RawEncoding::Verbatim, Cow::Owned(key_prefix.to_vec())),
913			]),
914		)
915	}
916
917	pub fn key_range(
918		object: impl Into<ObjectId>,
919		index: IndexId,
920		index_range: EncodedIndexKeyRange,
921	) -> TaggedKeyBoundRange {
922		let object = object.into();
923		let head = || {
924			object_fields(object)
925				.into_iter()
926				.chain([Field::UAsc(Width::U8, 1), Field::UDesc(Width::U64, index.as_u64() as u128)])
927		};
928		let at = |key: &EncodedIndexKey| {
929			TaggedKeyBound::prefix(
930				KeyTag::IndexEntry,
931				head().chain([Field::RawAsc(
932					RawEncoding::Verbatim,
933					Cow::Owned(key.as_slice().to_vec()),
934				)]),
935			)
936		};
937
938		let start = match &index_range.start {
939			Bound::Included(key) => Bound::Included(at(key)),
940			Bound::Excluded(key) => Bound::Excluded(at(key)),
941			Bound::Unbounded => Bound::Included(TaggedKeyBound::prefix(KeyTag::IndexEntry, head())),
942		};
943
944		let end = match &index_range.end {
945			Bound::Included(key) => Bound::Included(at(key)),
946			Bound::Excluded(key) => Bound::Excluded(at(key)),
947			Bound::Unbounded => Bound::Excluded(TaggedKeyBound::prefix_end(KeyTag::IndexEntry, head())),
948		};
949
950		TaggedKeyBoundRange {
951			start,
952			end,
953		}
954	}
955}
956
957#[cfg(test)]
958pub mod index_entry_key_tests_2 {
959	use reifydb_value::value::value_type::ValueType;
960
961	use super::*;
962	use crate::{sort::SortDirection, value::index::shape::IndexShape};
963
964	#[test]
965	fn test_encode_decode() {
966		let layout = IndexShape::new(
967			&[ValueType::Uint8, ValueType::Uint8],
968			&[SortDirection::Asc, SortDirection::Asc],
969		)
970		.unwrap();
971
972		let mut index_key = layout.allocate_key();
973		layout.set_u64(&mut index_key, 0, 100u64);
974		layout.set_row_number(&mut index_key, 1, 1u64);
975
976		let entry = IndexEntryKey {
977			object: ObjectId::table(42),
978			index: IndexId::primary(7),
979			key: index_key.clone(),
980		};
981
982		let encoded = entry.encode();
983		let decoded = IndexEntryKey::decode(&encoded).unwrap();
984
985		assert_eq!(decoded.object, ObjectId::table(42));
986		assert_eq!(decoded.index, IndexId::primary(7));
987		assert_eq!(decoded.key.as_slice(), index_key.as_slice());
988	}
989
990	#[test]
991	fn test_ordering() {
992		let layout = IndexShape::new(&[ValueType::Uint8], &[SortDirection::Asc]).unwrap();
993
994		let mut key1 = layout.allocate_key();
995		layout.set_u64(&mut key1, 0, 100u64);
996
997		let mut key2 = layout.allocate_key();
998		layout.set_u64(&mut key2, 0, 200u64);
999
1000		let entry1 = IndexEntryKey {
1001			object: ObjectId::table(1),
1002			index: IndexId::primary(1),
1003			key: key1,
1004		};
1005
1006		let entry2 = IndexEntryKey {
1007			object: ObjectId::table(1),
1008			index: IndexId::primary(1),
1009			key: key2,
1010		};
1011
1012		let encoded1 = entry1.encode();
1013		let encoded2 = entry2.encode();
1014
1015		assert!(encoded1.as_slice() < encoded2.as_slice());
1016	}
1017
1018	#[test]
1019	fn test_index_range() {
1020		let range = IndexEntryKey::index_range(ObjectId::table(10), IndexId::primary(5)).encode();
1021
1022		let layout = IndexShape::new(&[ValueType::Uint8], &[SortDirection::Asc]).unwrap();
1023
1024		let mut key = layout.allocate_key();
1025		layout.set_u64(&mut key, 0, 50u64);
1026
1027		let entry = IndexEntryKey {
1028			object: ObjectId::table(10),
1029			index: IndexId::primary(5),
1030			key,
1031		};
1032
1033		let encoded = entry.encode();
1034
1035		if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
1036			assert!(encoded.as_slice() >= start.as_slice());
1037			assert!(encoded.as_slice() < end.as_slice());
1038		} else {
1039			panic!("Expected Included/Excluded bounds");
1040		}
1041
1042		let entry2 = IndexEntryKey {
1043			object: ObjectId::table(10),
1044			index: IndexId::primary(6),
1045			key: layout.allocate_key(),
1046		};
1047
1048		let encoded2 = entry2.encode();
1049
1050		if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
1051			assert!(encoded2.as_slice() < start.as_slice() || encoded2.as_slice() >= end.as_slice());
1052		}
1053	}
1054
1055	#[test]
1056	fn test_key_prefix_range() {
1057		let layout = IndexShape::new(
1058			&[ValueType::Uint8, ValueType::Uint8],
1059			&[SortDirection::Asc, SortDirection::Asc],
1060		)
1061		.unwrap();
1062
1063		let mut key = layout.allocate_key();
1064		layout.set_u64(&mut key, 0, 100u64);
1065		layout.set_row_number(&mut key, 1, 0u64);
1066
1067		let prefix = &key.as_slice()[..layout.fields[1].offset];
1068		let range = IndexEntryKey::key_prefix_range(ObjectId::table(1), IndexId::primary(1), prefix).encode();
1069
1070		layout.set_row_number(&mut key, 1, 999u64);
1071		let entry = IndexEntryKey {
1072			object: ObjectId::table(1),
1073			index: IndexId::primary(1),
1074			key: key.clone(),
1075		};
1076
1077		let encoded = entry.encode();
1078
1079		if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
1080			assert!(encoded.as_slice() >= start.as_slice());
1081			assert!(encoded.as_slice() < end.as_slice());
1082		}
1083
1084		let mut key2 = layout.allocate_key();
1085		layout.set_u64(&mut key2, 0, 200u64);
1086		layout.set_row_number(&mut key2, 1, 1u64);
1087
1088		let entry2 = IndexEntryKey {
1089			object: ObjectId::table(1),
1090			index: IndexId::primary(1),
1091			key: key2,
1092		};
1093
1094		let encoded2 = entry2.encode();
1095
1096		if let Bound::Excluded(end) = &range.end {
1097			assert!(encoded2.as_slice() >= end.as_slice());
1098		}
1099	}
1100}
1101
1102#[derive(Debug, Clone, PartialEq, Hash)]
1103pub struct SumTypeKey {
1104	pub sumtype: SumTypeId,
1105}
1106
1107impl SumTypeKey {
1108	pub fn new(sumtype: SumTypeId) -> Self {
1109		Self {
1110			sumtype,
1111		}
1112	}
1113
1114	pub fn encoded(sumtype: impl Into<SumTypeId>) -> EncodedKey {
1115		Self::new(sumtype.into()).encode()
1116	}
1117
1118	pub fn full_scan() -> TaggedKeyBoundRange {
1119		TaggedKeyBoundRange::kind(Self::TAG)
1120	}
1121}
1122
1123impl SumTypeKey {
1124	pub const TAG: KeyTag = KeyTag::SumType;
1125
1126	pub fn encode(&self) -> EncodedKey {
1127		let mut serializer = KeySerializer::with_capacity(9);
1128		serializer.extend_u8(SumTypeKey::TAG as u8).extend_u64(self.sumtype);
1129		serializer.to_encoded_key()
1130	}
1131
1132	pub fn decode(key: &EncodedKey) -> Option<Self> {
1133		let mut de = KeyDeserializer::from_bytes(key.as_slice());
1134
1135		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1136		if kind != SumTypeKey::TAG {
1137			return None;
1138		}
1139
1140		let sumtype = de.read_u64().ok()?;
1141
1142		Some(Self {
1143			sumtype: SumTypeId(sumtype),
1144		})
1145	}
1146}
1147
1148#[cfg(test)]
1149mod sum_type_key_tests {
1150	use reifydb_value::value::sumtype::SumTypeId;
1151
1152	use super::SumTypeKey;
1153
1154	#[test]
1155	fn test_encode_decode() {
1156		let key = SumTypeKey {
1157			sumtype: SumTypeId(0xABCD),
1158		};
1159		let encoded = key.encode();
1160		let decoded = SumTypeKey::decode(&encoded).unwrap();
1161		assert_eq!(decoded.sumtype, SumTypeId(0xABCD));
1162	}
1163}
1164
1165#[derive(Debug, Clone, PartialEq, Hash)]
1166pub struct ViewKey {
1167	pub view: ViewId,
1168}
1169
1170impl ViewKey {
1171	pub const TAG: KeyTag = KeyTag::View;
1172
1173	pub fn encode(&self) -> EncodedKey {
1174		let mut serializer = KeySerializer::with_capacity(9);
1175		serializer.extend_u8(ViewKey::TAG as u8).extend_u64(self.view);
1176		serializer.to_encoded_key()
1177	}
1178
1179	pub fn decode(key: &EncodedKey) -> Option<Self> {
1180		let mut de = KeyDeserializer::from_bytes(key.as_slice());
1181
1182		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1183		if kind != ViewKey::TAG {
1184			return None;
1185		}
1186
1187		let view = de.read_u64().ok()?;
1188
1189		Some(Self {
1190			view: ViewId(view),
1191		})
1192	}
1193}
1194
1195impl ViewKey {
1196	pub fn new(view: impl Into<ViewId>) -> Self {
1197		Self {
1198			view: view.into(),
1199		}
1200	}
1201
1202	pub fn encoded(view: impl Into<ViewId>) -> EncodedKey {
1203		Self::new(view).encode()
1204	}
1205
1206	pub fn full_scan() -> TaggedKeyBoundRange {
1207		TaggedKeyBoundRange::kind(Self::TAG)
1208	}
1209}
1210
1211#[cfg(test)]
1212pub mod view_key_tests {
1213	use super::ViewKey;
1214	use crate::interface::catalog::id::ViewId;
1215
1216	#[test]
1217	fn test_encode_decode() {
1218		let key = ViewKey {
1219			view: ViewId(0xABCD),
1220		};
1221		let encoded = key.encode();
1222		let expected = vec![0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32];
1223		assert_eq!(encoded.as_slice(), expected);
1224
1225		let key = ViewKey::decode(&encoded).unwrap();
1226		assert_eq!(key.view, 0xABCD);
1227	}
1228}
1229
1230#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1231#[key(tag = Table)]
1232pub struct TableKey {
1233	pub table: TableId,
1234}
1235
1236impl TableKey {
1237	pub fn new(table: impl Into<TableId>) -> Self {
1238		Self {
1239			table: table.into(),
1240		}
1241	}
1242
1243	pub fn encoded(table: impl Into<TableId>) -> EncodedKey {
1244		Self::new(table).encode()
1245	}
1246
1247	pub fn full_scan() -> TaggedKeyBoundRange {
1248		TaggedKeyBoundRange::kind(Self::TAG)
1249	}
1250}
1251
1252#[cfg(test)]
1253pub mod table_key_tests {
1254	use super::TableKey;
1255	use crate::interface::catalog::id::TableId;
1256
1257	#[test]
1258	fn test_encode_decode() {
1259		let key = TableKey {
1260			table: TableId(0xABCD),
1261		};
1262		let encoded = key.encode();
1263		let expected = vec![0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32];
1264		assert_eq!(encoded.as_slice(), expected);
1265
1266		let key = TableKey::decode(&encoded).unwrap();
1267		assert_eq!(key.table, 0xABCD);
1268	}
1269
1270	#[test]
1271	fn test_order_preserving() {
1272		let key1 = TableKey {
1273			table: TableId(1),
1274		};
1275		let key2 = TableKey {
1276			table: TableId(2),
1277		};
1278
1279		let encoded1 = key1.encode();
1280		let encoded2 = key2.encode();
1281
1282		assert!(encoded2 < encoded1, "ordering not preserved");
1283	}
1284}
1285
1286#[derive(Debug, Clone, PartialEq, Hash)]
1287pub struct SourceKey {
1288	pub source: SourceId,
1289}
1290
1291impl SourceKey {
1292	pub const TAG: KeyTag = KeyTag::Source;
1293
1294	pub fn encode(&self) -> EncodedKey {
1295		let mut serializer = KeySerializer::with_capacity(9);
1296		serializer.extend_u8(SourceKey::TAG as u8).extend_u64(self.source);
1297		serializer.to_encoded_key()
1298	}
1299
1300	pub fn decode(key: &EncodedKey) -> Option<Self> {
1301		let mut de = KeyDeserializer::from_bytes(key.as_slice());
1302
1303		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1304		if kind != SourceKey::TAG {
1305			return None;
1306		}
1307
1308		let source = de.read_u64().ok()?;
1309
1310		Some(Self {
1311			source: SourceId(source),
1312		})
1313	}
1314}
1315
1316impl SourceKey {
1317	pub fn new(source: impl Into<SourceId>) -> Self {
1318		Self {
1319			source: source.into(),
1320		}
1321	}
1322
1323	pub fn encoded(source: impl Into<SourceId>) -> EncodedKey {
1324		Self::new(source).encode()
1325	}
1326
1327	pub fn full_scan() -> TaggedKeyBoundRange {
1328		TaggedKeyBoundRange::kind(Self::TAG)
1329	}
1330}
1331
1332#[cfg(test)]
1333pub mod source_key_tests {
1334	use super::SourceKey;
1335	use crate::interface::catalog::id::SourceId;
1336
1337	#[test]
1338	fn test_encode_decode() {
1339		let key = SourceKey {
1340			source: SourceId(0x1234),
1341		};
1342		let encoded = key.encode();
1343		let decoded = SourceKey::decode(&encoded).unwrap();
1344		assert_eq!(decoded.source, SourceId(0x1234));
1345		assert_eq!(key, decoded);
1346	}
1347}
1348
1349#[derive(Debug, Clone, PartialEq, Hash)]
1350pub struct SinkKey {
1351	pub sink: SinkId,
1352}
1353
1354impl SinkKey {
1355	pub const TAG: KeyTag = KeyTag::Sink;
1356
1357	pub fn encode(&self) -> EncodedKey {
1358		let mut serializer = KeySerializer::with_capacity(9);
1359		serializer.extend_u8(SinkKey::TAG as u8).extend_u64(self.sink);
1360		serializer.to_encoded_key()
1361	}
1362
1363	pub fn decode(key: &EncodedKey) -> Option<Self> {
1364		let mut de = KeyDeserializer::from_bytes(key.as_slice());
1365
1366		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1367		if kind != SinkKey::TAG {
1368			return None;
1369		}
1370
1371		let sink = de.read_u64().ok()?;
1372
1373		Some(Self {
1374			sink: SinkId(sink),
1375		})
1376	}
1377}
1378
1379impl SinkKey {
1380	pub fn new(sink: impl Into<SinkId>) -> Self {
1381		Self {
1382			sink: sink.into(),
1383		}
1384	}
1385
1386	pub fn encoded(sink: impl Into<SinkId>) -> EncodedKey {
1387		Self::new(sink).encode()
1388	}
1389
1390	pub fn full_scan() -> TaggedKeyBoundRange {
1391		TaggedKeyBoundRange::kind(Self::TAG)
1392	}
1393}
1394
1395#[cfg(test)]
1396pub mod sink_key_tests {
1397	use super::SinkKey;
1398	use crate::interface::catalog::id::SinkId;
1399
1400	#[test]
1401	fn test_encode_decode() {
1402		let key = SinkKey {
1403			sink: SinkId(0x1234),
1404		};
1405		let encoded = key.encode();
1406		let decoded = SinkKey::decode(&encoded).unwrap();
1407		assert_eq!(decoded.sink, SinkId(0x1234));
1408		assert_eq!(key, decoded);
1409	}
1410}
1411
1412#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1413#[key(tag = Relationship)]
1414pub struct RelationshipKey {
1415	pub relationship: RelationshipId,
1416}
1417
1418impl RelationshipKey {
1419	pub fn new(relationship: impl Into<RelationshipId>) -> Self {
1420		Self {
1421			relationship: relationship.into(),
1422		}
1423	}
1424
1425	pub fn encoded(relationship: impl Into<RelationshipId>) -> EncodedKey {
1426		Self::new(relationship).encode()
1427	}
1428
1429	pub fn full_scan() -> TaggedKeyBoundRange {
1430		TaggedKeyBoundRange::kind(Self::TAG)
1431	}
1432}
1433
1434#[cfg(test)]
1435mod relationship_key_tests {
1436	use super::RelationshipKey;
1437	use crate::interface::catalog::id::RelationshipId;
1438
1439	#[test]
1440	fn test_encode_decode() {
1441		let key = RelationshipKey {
1442			relationship: RelationshipId(0xABCD),
1443		};
1444		let encoded = key.encode();
1445		let decoded = RelationshipKey::decode(&encoded).unwrap();
1446		assert_eq!(decoded.relationship, RelationshipId(0xABCD));
1447	}
1448}
1449
1450#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1451#[key(tag = ColumnProperty)]
1452pub struct ColumnPropertyKey {
1453	pub column: ColumnId,
1454	pub property: ColumnPropertyId,
1455}
1456
1457impl ColumnPropertyKey {
1458	pub fn new(column: impl Into<ColumnId>, property: impl Into<ColumnPropertyId>) -> Self {
1459		Self {
1460			column: column.into(),
1461			property: property.into(),
1462		}
1463	}
1464
1465	pub fn encoded(column: impl Into<ColumnId>, property: impl Into<ColumnPropertyId>) -> EncodedKey {
1466		Self::new(column, property).encode()
1467	}
1468
1469	pub fn full_scan(column: ColumnId) -> TaggedKeyBoundRange {
1470		TaggedKeyBoundRange::prefix(Self::TAG, [Field::UDesc(Width::U64, column.0 as u128)])
1471	}
1472}
1473
1474#[cfg(test)]
1475pub mod column_property_key_tests {
1476	use super::ColumnPropertyKey;
1477	use crate::interface::catalog::id::{ColumnId, ColumnPropertyId};
1478
1479	#[test]
1480	fn test_encode_decode() {
1481		let key = ColumnPropertyKey {
1482			column: ColumnId(0xABCD),
1483			property: ColumnPropertyId(0x123456789ABCDEF0),
1484		};
1485		let encoded = key.encode();
1486
1487		let expected: Vec<u8> = vec![
1488			0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, 0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43, 0x21,
1489			0x0F,
1490		];
1491
1492		assert_eq!(encoded.as_slice(), expected);
1493
1494		let key = ColumnPropertyKey::decode(&encoded).unwrap();
1495		assert_eq!(key.column, 0xABCD);
1496		assert_eq!(key.property, 0x123456789ABCDEF0);
1497	}
1498
1499	#[test]
1500	fn test_order_preserving() {
1501		let key1 = ColumnPropertyKey {
1502			column: ColumnId(1),
1503			property: ColumnPropertyId(100),
1504		};
1505		let key2 = ColumnPropertyKey {
1506			column: ColumnId(1),
1507			property: ColumnPropertyId(200),
1508		};
1509		let key3 = ColumnPropertyKey {
1510			column: ColumnId(2),
1511			property: ColumnPropertyId(0),
1512		};
1513
1514		let encoded1 = key1.encode();
1515		let encoded2 = key2.encode();
1516		let encoded3 = key3.encode();
1517
1518		assert!(encoded3 < encoded2, "ordering not preserved");
1519		assert!(encoded2 < encoded1, "ordering not preserved");
1520	}
1521}
1522
1523#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1524#[key(tag = Handler)]
1525pub struct HandlerKey {
1526	pub handler: HandlerId,
1527}
1528
1529impl HandlerKey {
1530	pub fn new(handler: HandlerId) -> Self {
1531		Self {
1532			handler,
1533		}
1534	}
1535
1536	pub fn encoded(handler: impl Into<HandlerId>) -> EncodedKey {
1537		Self::new(handler.into()).encode()
1538	}
1539
1540	pub fn full_scan() -> TaggedKeyBoundRange {
1541		TaggedKeyBoundRange::kind(Self::TAG)
1542	}
1543}
1544
1545#[cfg(test)]
1546pub mod handler_key_tests {
1547	use super::HandlerKey;
1548	use crate::interface::catalog::id::HandlerId;
1549
1550	#[test]
1551	fn test_encode_decode() {
1552		let key = HandlerKey {
1553			handler: HandlerId(0xABCD),
1554		};
1555		let encoded = key.encode();
1556		let expected = vec![0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32];
1557		assert_eq!(encoded.as_slice(), expected);
1558
1559		let decoded = HandlerKey::decode(&encoded).unwrap();
1560		assert_eq!(decoded.handler, HandlerId(0xABCD));
1561	}
1562
1563	#[test]
1564	fn test_order_preserving() {
1565		let key1 = HandlerKey {
1566			handler: HandlerId(1),
1567		};
1568		let key2 = HandlerKey {
1569			handler: HandlerId(2),
1570		};
1571
1572		let encoded1 = key1.encode();
1573		let encoded2 = key2.encode();
1574
1575		assert!(encoded2 < encoded1, "ordering not preserved");
1576	}
1577}
1578
1579#[cfg(test)]
1580mod verify_byte_identical_handler_key {
1581	use reifydb_codec::key::serializer::KeySerializer;
1582
1583	use super::HandlerKey;
1584	use crate::interface::catalog::id::HandlerId;
1585
1586	fn legacy_encode(key: &HandlerKey) -> Vec<u8> {
1587		let mut serializer = KeySerializer::with_capacity(9);
1588		serializer.extend_u8(HandlerKey::TAG as u8).extend_u64(key.handler);
1589		serializer.to_encoded_key().as_slice().to_vec()
1590	}
1591
1592	#[test]
1593	fn matches_legacy_byte_layout() {
1594		for handler in [0u64, 1, 42, 0xABCD, u64::MAX] {
1595			let key = HandlerKey {
1596				handler: HandlerId(handler),
1597			};
1598			assert_eq!(legacy_encode(&key), key.encode().as_slice().to_vec(), "handler={handler:#x}");
1599		}
1600	}
1601}
1602
1603#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1604#[key(tag = VariantHandler)]
1605pub struct VariantHandlerKey {
1606	pub namespace: NamespaceId,
1607	pub sumtype: SumTypeId,
1608	pub variant_tag: u8,
1609	pub handler: HandlerId,
1610}
1611
1612impl VariantHandlerKey {
1613	pub fn new(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8, handler: HandlerId) -> Self {
1614		Self {
1615			namespace,
1616			sumtype,
1617			variant_tag,
1618			handler,
1619		}
1620	}
1621
1622	pub fn encoded(
1623		namespace: impl Into<NamespaceId>,
1624		sumtype: impl Into<SumTypeId>,
1625		variant_tag: u8,
1626		handler: impl Into<HandlerId>,
1627	) -> EncodedKey {
1628		Self::new(namespace.into(), sumtype.into(), variant_tag, handler.into()).encode()
1629	}
1630
1631	pub fn variant_scan(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8) -> TaggedKeyBoundRange {
1632		TaggedKeyBoundRange::prefix(
1633			Self::TAG,
1634			[
1635				Field::UDesc(Width::U64, namespace.0 as u128),
1636				Field::UDesc(Width::U64, sumtype.0 as u128),
1637				Field::UDesc(Width::U8, variant_tag as u128),
1638			],
1639		)
1640	}
1641}
1642
1643#[cfg(test)]
1644pub mod variant_handler_key_tests {
1645	use std::ops::Bound;
1646
1647	use reifydb_value::value::sumtype::SumTypeId;
1648
1649	use super::VariantHandlerKey;
1650	use crate::interface::catalog::id::{HandlerId, NamespaceId};
1651
1652	#[test]
1653	fn test_encode_decode() {
1654		let key = VariantHandlerKey {
1655			namespace: NamespaceId(0xABCD),
1656			sumtype: SumTypeId(0x1234),
1657			variant_tag: 5,
1658			handler: HandlerId(0x6789),
1659		};
1660		let encoded = key.encode();
1661		let expected: Vec<u8> = vec![
1662			0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xED,
1663			0xCB, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x98, 0x76,
1664		];
1665		assert_eq!(encoded.as_slice(), expected);
1666
1667		let decoded = VariantHandlerKey::decode(&encoded).unwrap();
1668		assert_eq!(decoded.namespace, NamespaceId(0xABCD));
1669		assert_eq!(decoded.sumtype, SumTypeId(0x1234));
1670		assert_eq!(decoded.variant_tag, 5);
1671		assert_eq!(decoded.handler, HandlerId(0x6789));
1672	}
1673
1674	#[test]
1675	fn test_order_preserving() {
1676		let key1 = VariantHandlerKey {
1677			namespace: NamespaceId::SYSTEM,
1678			sumtype: SumTypeId(5),
1679			variant_tag: 3,
1680			handler: HandlerId(100),
1681		};
1682		let key2 = VariantHandlerKey {
1683			namespace: NamespaceId::SYSTEM,
1684			sumtype: SumTypeId(5),
1685			variant_tag: 3,
1686			handler: HandlerId(200),
1687		};
1688		let key3 = VariantHandlerKey {
1689			namespace: NamespaceId::SYSTEM,
1690			sumtype: SumTypeId(5),
1691			variant_tag: 4,
1692			handler: HandlerId(1),
1693		};
1694		let key4 = VariantHandlerKey {
1695			namespace: NamespaceId::DEFAULT,
1696			sumtype: SumTypeId(1),
1697			variant_tag: 0,
1698			handler: HandlerId(1),
1699		};
1700
1701		let encoded1 = key1.encode();
1702		let encoded2 = key2.encode();
1703		let encoded3 = key3.encode();
1704		let encoded4 = key4.encode();
1705
1706		assert!(encoded4 < encoded3, "ordering not preserved");
1707		assert!(encoded3 < encoded2, "ordering not preserved");
1708		assert!(encoded2 < encoded1, "ordering not preserved");
1709	}
1710
1711	#[test]
1712	fn test_variant_scan() {
1713		let ns = NamespaceId::SYSTEM;
1714		let st = SumTypeId(10);
1715		let tag = 5u8;
1716
1717		let range = VariantHandlerKey::variant_scan(ns, st, tag).encode();
1718		let start = match &range.start {
1719			Bound::Included(k) | Bound::Excluded(k) => k,
1720			Bound::Unbounded => panic!("expected bounded start"),
1721		};
1722		let end = match &range.end {
1723			Bound::Included(k) | Bound::Excluded(k) => k,
1724			Bound::Unbounded => panic!("expected bounded end"),
1725		};
1726
1727		let key = VariantHandlerKey {
1728			namespace: ns,
1729			sumtype: st,
1730			variant_tag: tag,
1731			handler: HandlerId(42),
1732		};
1733		let encoded = key.encode();
1734		assert!(encoded.as_slice() >= start.as_slice());
1735		assert!(encoded.as_slice() <= end.as_slice());
1736
1737		let other = VariantHandlerKey {
1738			namespace: ns,
1739			sumtype: st,
1740			variant_tag: tag + 1,
1741			handler: HandlerId(42),
1742		};
1743		let other_encoded = other.encode();
1744		assert!(other_encoded.as_slice() < start.as_slice());
1745	}
1746}
1747
1748#[cfg(test)]
1749mod verify_byte_identical_variant_handler_key {
1750	use reifydb_codec::key::serializer::KeySerializer;
1751	use reifydb_value::value::sumtype::SumTypeId;
1752
1753	use super::VariantHandlerKey;
1754	use crate::interface::catalog::id::{HandlerId, NamespaceId};
1755
1756	fn legacy_encode(key: &VariantHandlerKey) -> Vec<u8> {
1757		let mut serializer = KeySerializer::with_capacity(26);
1758		serializer
1759			.extend_u8(VariantHandlerKey::TAG as u8)
1760			.extend_u64(key.namespace)
1761			.extend_u64(key.sumtype)
1762			.extend_u8(key.variant_tag)
1763			.extend_u64(key.handler);
1764		serializer.to_encoded_key().as_slice().to_vec()
1765	}
1766
1767	#[test]
1768	fn matches_legacy_byte_layout() {
1769		for (namespace, sumtype, variant_tag, handler) in [
1770			(0u64, 0u64, 0u8, 0u64),
1771			(1, 2, 3, 4),
1772			(0xABCD, 0x1234, 5, 0x6789),
1773			(u64::MAX, u64::MAX, u8::MAX, u64::MAX),
1774		] {
1775			let key = VariantHandlerKey {
1776				namespace: NamespaceId(namespace),
1777				sumtype: SumTypeId(sumtype),
1778				variant_tag,
1779				handler: HandlerId(handler),
1780			};
1781			assert_eq!(
1782				legacy_encode(&key),
1783				key.encode().as_slice().to_vec(),
1784				"namespace={namespace:#x} sumtype={sumtype:#x} variant_tag={variant_tag:#x} handler={handler:#x}"
1785			);
1786		}
1787	}
1788}
1789
1790#[derive(Debug, Clone, PartialEq, Hash)]
1791pub struct BindingKey {
1792	pub binding: BindingId,
1793}
1794
1795impl BindingKey {
1796	pub const TAG: KeyTag = KeyTag::Binding;
1797
1798	pub fn encode(&self) -> EncodedKey {
1799		let mut serializer = KeySerializer::with_capacity(9);
1800		serializer.extend_u8(BindingKey::TAG as u8).extend_u64(self.binding);
1801		serializer.to_encoded_key()
1802	}
1803
1804	pub fn decode(key: &EncodedKey) -> Option<Self> {
1805		let mut de = KeyDeserializer::from_bytes(key.as_slice());
1806
1807		let kind: KeyTag = de.read_u8().ok()?.try_into().ok()?;
1808		if kind != BindingKey::TAG {
1809			return None;
1810		}
1811
1812		let binding = de.read_u64().ok()?;
1813
1814		Some(Self {
1815			binding: BindingId(binding),
1816		})
1817	}
1818}
1819
1820impl BindingKey {
1821	pub fn new(binding: impl Into<BindingId>) -> Self {
1822		Self {
1823			binding: binding.into(),
1824		}
1825	}
1826
1827	pub fn encoded(binding: impl Into<BindingId>) -> EncodedKey {
1828		Self::new(binding).encode()
1829	}
1830
1831	pub fn full_scan() -> TaggedKeyBoundRange {
1832		TaggedKeyBoundRange::kind(Self::TAG)
1833	}
1834}
1835
1836#[cfg(test)]
1837pub mod binding_key_tests {
1838	use super::BindingKey;
1839	use crate::interface::catalog::id::BindingId;
1840
1841	#[test]
1842	fn test_encode_decode() {
1843		let key = BindingKey {
1844			binding: BindingId(0xABCD),
1845		};
1846		let encoded = key.encode();
1847		let decoded = BindingKey::decode(&encoded).unwrap();
1848		assert_eq!(decoded.binding, 0xABCD);
1849	}
1850}
1851
1852#[derive(Debug, Clone, PartialEq, KeyCodec, Hash)]
1853#[key(tag = PrimaryKey)]
1854pub struct PrimaryKeyKey {
1855	pub primary_key: PrimaryKeyId,
1856}
1857
1858impl PrimaryKeyKey {
1859	pub fn new(primary_key: impl Into<PrimaryKeyId>) -> Self {
1860		Self {
1861			primary_key: primary_key.into(),
1862		}
1863	}
1864
1865	pub fn encoded(primary_key: impl Into<PrimaryKeyId>) -> EncodedKey {
1866		Self::new(primary_key).encode()
1867	}
1868
1869	pub fn full_scan() -> TaggedKeyBoundRange {
1870		TaggedKeyBoundRange::kind(Self::TAG)
1871	}
1872}
1873
1874#[cfg(test)]
1875mod primary_key_key_tests {
1876	use super::PrimaryKeyKey;
1877	use crate::interface::catalog::id::PrimaryKeyId;
1878
1879	#[test]
1880	fn test_encode_decode() {
1881		let key = PrimaryKeyKey {
1882			primary_key: PrimaryKeyId(0xABCD),
1883		};
1884		let encoded = key.encode();
1885		let decoded = PrimaryKeyKey::decode(&encoded).unwrap();
1886		assert_eq!(decoded.primary_key, PrimaryKeyId(0xABCD));
1887	}
1888}
1889
1890impl KeyFields for DictionaryEntryIndexKey {
1891	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1892		smallvec![Field::UDesc(Width::U64, self.dictionary.0 as u128), Field::UDesc(Width::Varint, self.id)]
1893	}
1894}
1895
1896impl KeyFields for IndexEntryKey {
1897	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1898		smallvec![
1899			Field::UAsc(Width::U8, self.object.type_tag() as u128),
1900			Field::UDesc(Width::U64, self.object.as_u64() as u128),
1901			Field::UAsc(Width::U8, index_tag(&self.index) as u128),
1902			Field::UDesc(Width::U64, self.index.as_u64() as u128),
1903			Field::RawAsc(RawEncoding::Verbatim, Cow::Borrowed(self.key.as_slice())),
1904		]
1905	}
1906}
1907
1908impl KeyFields for BindingKey {
1909	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1910		smallvec![Field::UDesc(Width::U64, self.binding.0 as u128)]
1911	}
1912}
1913
1914impl KeyFields for SinkKey {
1915	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1916		smallvec![Field::UDesc(Width::U64, self.sink.0 as u128)]
1917	}
1918}
1919
1920impl KeyFields for SourceKey {
1921	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1922		smallvec![Field::UDesc(Width::U64, self.source.0 as u128)]
1923	}
1924}
1925
1926impl KeyFields for ViewKey {
1927	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1928		smallvec![Field::UDesc(Width::U64, self.view.0 as u128)]
1929	}
1930}
1931
1932impl KeyFields for SumTypeKey {
1933	fn fields(&self) -> SmallVec<[Field<'_>; 6]> {
1934		smallvec![Field::UDesc(Width::U64, self.sumtype.0 as u128)]
1935	}
1936}