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