Skip to main content

reifydb_core/key/
index.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::collections::Bound;
5
6use super::{EncodableKey, EncodableKeyRange, KeyKind};
7use crate::{
8	encoded::key::{EncodedKey, EncodedKeyRange},
9	interface::catalog::{
10		id::{IndexId, PrimaryKeyId},
11		primitive::PrimitiveId,
12	},
13	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
14};
15
16const VERSION: u8 = 1;
17
18#[derive(Debug, Clone, PartialEq)]
19pub struct IndexKey {
20	pub primitive: PrimitiveId,
21	pub index: IndexId,
22}
23
24impl EncodableKey for IndexKey {
25	const KIND: KeyKind = KeyKind::Index;
26
27	fn encode(&self) -> EncodedKey {
28		let mut serializer = KeySerializer::with_capacity(19);
29		serializer
30			.extend_u8(VERSION)
31			.extend_u8(Self::KIND as u8)
32			.extend_primitive_id(self.primitive)
33			.extend_u64(self.index);
34		serializer.to_encoded_key()
35	}
36
37	fn decode(key: &EncodedKey) -> Option<Self> {
38		let mut de = KeyDeserializer::from_bytes(key.as_slice());
39
40		let version = de.read_u8().ok()?;
41		if version != VERSION {
42			return None;
43		}
44
45		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
46		if kind != Self::KIND {
47			return None;
48		}
49
50		let primitive = de.read_primitive_id().ok()?;
51		let index_value = de.read_u64().ok()?;
52
53		Some(Self {
54			primitive,
55			index: IndexId::Primary(PrimaryKeyId(index_value)),
56		})
57	}
58}
59
60#[derive(Debug, Clone, PartialEq)]
61pub struct PrimitiveIndexKeyRange {
62	pub primitive: PrimitiveId,
63}
64
65impl PrimitiveIndexKeyRange {
66	fn decode_key(key: &EncodedKey) -> Option<Self> {
67		let mut de = KeyDeserializer::from_bytes(key.as_slice());
68
69		let version = de.read_u8().ok()?;
70		if version != VERSION {
71			return None;
72		}
73
74		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
75		if kind != Self::KIND {
76			return None;
77		}
78
79		let primitive = de.read_primitive_id().ok()?;
80
81		Some(PrimitiveIndexKeyRange {
82			primitive,
83		})
84	}
85}
86
87impl EncodableKeyRange for PrimitiveIndexKeyRange {
88	const KIND: KeyKind = KeyKind::Index;
89
90	fn start(&self) -> Option<EncodedKey> {
91		let mut serializer = KeySerializer::with_capacity(11);
92		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(self.primitive);
93		Some(serializer.to_encoded_key())
94	}
95
96	fn end(&self) -> Option<EncodedKey> {
97		let mut serializer = KeySerializer::with_capacity(11);
98		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(self.primitive.prev());
99		Some(serializer.to_encoded_key())
100	}
101
102	fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
103	where
104		Self: Sized,
105	{
106		let start_key = match &range.start {
107			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
108			Bound::Unbounded => None,
109		};
110
111		let end_key = match &range.end {
112			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
113			Bound::Unbounded => None,
114		};
115
116		(start_key, end_key)
117	}
118}
119
120impl IndexKey {
121	pub fn encoded(primitive: impl Into<PrimitiveId>, index: impl Into<IndexId>) -> EncodedKey {
122		Self {
123			primitive: primitive.into(),
124			index: index.into(),
125		}
126		.encode()
127	}
128
129	pub fn full_scan(primitive: impl Into<PrimitiveId>) -> EncodedKeyRange {
130		let primitive = primitive.into();
131		EncodedKeyRange::start_end(Some(Self::primitive_start(primitive)), Some(Self::primitive_end(primitive)))
132	}
133
134	pub fn primitive_start(primitive: impl Into<PrimitiveId>) -> EncodedKey {
135		let primitive = primitive.into();
136		let mut serializer = KeySerializer::with_capacity(11);
137		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(primitive);
138		serializer.to_encoded_key()
139	}
140
141	pub fn primitive_end(primitive: impl Into<PrimitiveId>) -> EncodedKey {
142		let primitive = primitive.into();
143		let mut serializer = KeySerializer::with_capacity(11);
144		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(primitive.prev());
145		serializer.to_encoded_key()
146	}
147}
148
149#[cfg(test)]
150pub mod tests {
151	use super::{EncodableKey, IndexKey};
152	use crate::interface::catalog::{id::IndexId, primitive::PrimitiveId};
153
154	#[test]
155	fn test_encode_decode() {
156		let key = IndexKey {
157			primitive: PrimitiveId::table(0xABCD),
158			index: IndexId::primary(0x123456789ABCDEF0u64),
159		};
160		let encoded = key.encode();
161
162		let expected: Vec<u8> = vec![
163			0xFE, // version
164			0xF3, // kind
165			0x01, // PrimitiveId type discriminator (Table)
166			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, // primitive id bytes
167			0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43, 0x21, 0x0F, // index id bytes
168		];
169
170		assert_eq!(encoded.as_slice(), expected);
171
172		let key = IndexKey::decode(&encoded).unwrap();
173		assert_eq!(key.primitive, 0xABCD);
174		assert_eq!(key.index, 0x123456789ABCDEF0);
175	}
176
177	#[test]
178	fn test_order_preserving() {
179		let key1 = IndexKey {
180			primitive: PrimitiveId::table(1),
181			index: IndexId::primary(100),
182		};
183		let key2 = IndexKey {
184			primitive: PrimitiveId::table(1),
185			index: IndexId::primary(200),
186		};
187		let key3 = IndexKey {
188			primitive: PrimitiveId::table(2),
189			index: IndexId::primary(50),
190		};
191
192		let encoded1 = key1.encode();
193		let encoded2 = key2.encode();
194		let encoded3 = key3.encode();
195
196		assert!(encoded3 < encoded2, "ordering not preserved");
197		assert!(encoded2 < encoded1, "ordering not preserved");
198	}
199}