reifydb_core/key/
index.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use std::collections::Bound;
5
6use super::{EncodableKey, KeyKind};
7use crate::{
8	EncodedKey, EncodedKeyRange,
9	interface::{
10		EncodableKeyRange,
11		catalog::{IndexId, PrimaryKeyId, SourceId},
12	},
13	util::encoding::keycode::{KeyDeserializer, KeySerializer},
14};
15
16const VERSION: u8 = 1;
17
18#[derive(Debug, Clone, PartialEq)]
19pub struct IndexKey {
20	pub source: SourceId,
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_source_id(self.source)
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 source = de.read_source_id().ok()?;
51		let index_value = de.read_u64().ok()?;
52
53		Some(Self {
54			source,
55			index: IndexId::Primary(PrimaryKeyId(index_value)),
56		})
57	}
58}
59
60#[derive(Debug, Clone, PartialEq)]
61pub struct SourceIndexKeyRange {
62	pub source: SourceId,
63}
64
65impl SourceIndexKeyRange {
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 source = de.read_source_id().ok()?;
80
81		Some(SourceIndexKeyRange {
82			source,
83		})
84	}
85}
86
87impl EncodableKeyRange for SourceIndexKeyRange {
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_source_id(self.source);
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_source_id(self.source.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(source: impl Into<SourceId>, index: impl Into<IndexId>) -> EncodedKey {
122		Self {
123			source: source.into(),
124			index: index.into(),
125		}
126		.encode()
127	}
128
129	pub fn full_scan(source: impl Into<SourceId>) -> EncodedKeyRange {
130		let source = source.into();
131		EncodedKeyRange::start_end(Some(Self::source_start(source)), Some(Self::source_end(source)))
132	}
133
134	pub fn source_start(source: impl Into<SourceId>) -> EncodedKey {
135		let source = source.into();
136		let mut serializer = KeySerializer::with_capacity(11);
137		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_source_id(source);
138		serializer.to_encoded_key()
139	}
140
141	pub fn source_end(source: impl Into<SourceId>) -> EncodedKey {
142		let source = source.into();
143		let mut serializer = KeySerializer::with_capacity(11);
144		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_source_id(source.prev());
145		serializer.to_encoded_key()
146	}
147}
148
149#[cfg(test)]
150mod tests {
151	use super::{EncodableKey, IndexKey};
152	use crate::interface::catalog::{IndexId, SourceId};
153
154	#[test]
155	fn test_encode_decode() {
156		let key = IndexKey {
157			source: SourceId::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, // SourceId type discriminator (Table)
166			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, // source 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.source, 0xABCD);
174		assert_eq!(key.index, 0x123456789ABCDEF0);
175	}
176
177	#[test]
178	fn test_order_preserving() {
179		let key1 = IndexKey {
180			source: SourceId::table(1),
181			index: IndexId::primary(100),
182		};
183		let key2 = IndexKey {
184			source: SourceId::table(1),
185			index: IndexId::primary(200),
186		};
187		let key3 = IndexKey {
188			source: SourceId::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}