1use std::collections::Bound;
5
6use reifydb_type::util::cowvec::CowVec;
7
8use super::{EncodableKey, EncodableKeyRange, KeyKind};
9use crate::{
10 encoded::key::{EncodedKey, EncodedKeyRange},
11 interface::catalog::{id::IndexId, primitive::PrimitiveId},
12 util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
13 value::index::{encoded::EncodedIndexKey, range::EncodedIndexKeyRange},
14};
15
16const VERSION: u8 = 1;
17
18#[derive(Debug, Clone, PartialEq)]
20pub struct IndexEntryKey {
21 pub primitive: PrimitiveId,
22 pub index: IndexId,
23 pub key: EncodedIndexKey,
24}
25
26impl IndexEntryKey {
27 pub fn new(primitive: impl Into<PrimitiveId>, index: IndexId, key: EncodedIndexKey) -> Self {
28 Self {
29 primitive: primitive.into(),
30 index,
31 key,
32 }
33 }
34
35 pub fn encoded(primitive: impl Into<PrimitiveId>, index: IndexId, key: EncodedIndexKey) -> EncodedKey {
36 Self::new(primitive, index, key).encode()
37 }
38}
39
40#[derive(Debug, Clone, PartialEq)]
41pub struct IndexEntryKeyRange {
42 pub primitive: PrimitiveId,
43 pub index: IndexId,
44}
45
46impl IndexEntryKeyRange {
47 fn decode_key(key: &EncodedKey) -> Option<Self> {
48 let mut de = KeyDeserializer::from_bytes(key.as_slice());
49
50 let version = de.read_u8().ok()?;
51 if version != VERSION {
52 return None;
53 }
54
55 let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
56 if kind != Self::KIND {
57 return None;
58 }
59
60 let primitive = de.read_primitive_id().ok()?;
61 let index = de.read_index_id().ok()?;
62
63 Some(IndexEntryKeyRange {
64 primitive,
65 index,
66 })
67 }
68}
69
70impl EncodableKeyRange for IndexEntryKeyRange {
71 const KIND: KeyKind = KeyKind::IndexEntry;
72
73 fn start(&self) -> Option<EncodedKey> {
74 let mut serializer = KeySerializer::with_capacity(20); serializer
76 .extend_u8(VERSION)
77 .extend_u8(Self::KIND as u8)
78 .extend_primitive_id(self.primitive)
79 .extend_index_id(self.index);
80 Some(serializer.to_encoded_key())
81 }
82
83 fn end(&self) -> Option<EncodedKey> {
84 let mut serializer = KeySerializer::with_capacity(20);
85 serializer
86 .extend_u8(VERSION)
87 .extend_u8(Self::KIND as u8)
88 .extend_primitive_id(self.primitive)
89 .extend_index_id(self.index.prev());
90 Some(serializer.to_encoded_key())
91 }
92
93 fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
94 where
95 Self: Sized,
96 {
97 let start_key = match &range.start {
98 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
99 Bound::Unbounded => None,
100 };
101
102 let end_key = match &range.end {
103 Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
104 Bound::Unbounded => None,
105 };
106
107 (start_key, end_key)
108 }
109}
110
111impl EncodableKey for IndexEntryKey {
112 const KIND: KeyKind = KeyKind::IndexEntry;
113
114 fn encode(&self) -> EncodedKey {
115 let mut serializer = KeySerializer::with_capacity(20 + self.key.len());
116 serializer
117 .extend_u8(VERSION)
118 .extend_u8(Self::KIND as u8)
119 .extend_primitive_id(self.primitive)
120 .extend_index_id(self.index)
121 .extend_raw(self.key.as_slice());
123 serializer.to_encoded_key()
124 }
125
126 fn decode(key: &EncodedKey) -> Option<Self> {
127 let mut de = KeyDeserializer::from_bytes(key.as_slice());
128
129 let version = de.read_u8().ok()?;
130 if version != VERSION {
131 return None;
132 }
133
134 let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
135 if kind != Self::KIND {
136 return None;
137 }
138
139 let primitive = de.read_primitive_id().ok()?;
140 let index = de.read_index_id().ok()?;
141
142 let remaining = de.remaining();
144 if remaining > 0 {
145 let remaining_bytes = de.read_raw(remaining).ok()?;
146 let index_key = EncodedIndexKey(CowVec::new(remaining_bytes.to_vec()));
147 Some(Self {
148 primitive,
149 index,
150 key: index_key,
151 })
152 } else {
153 None
154 }
155 }
156}
157
158impl IndexEntryKey {
159 pub fn index_range(primitive: impl Into<PrimitiveId>, index: IndexId) -> EncodedKeyRange {
161 let range = IndexEntryKeyRange {
162 primitive: primitive.into(),
163 index,
164 };
165 EncodedKeyRange::new(Bound::Included(range.start().unwrap()), Bound::Excluded(range.end().unwrap()))
166 }
167
168 pub fn primitive_range(primitive: impl Into<PrimitiveId>) -> EncodedKeyRange {
170 let primitive = primitive.into();
171 let mut start_serializer = KeySerializer::with_capacity(11);
172 start_serializer.extend_u8(VERSION).extend_u8(KeyKind::IndexEntry as u8).extend_primitive_id(primitive);
173
174 let next_primitive = primitive.next();
175 let mut end_serializer = KeySerializer::with_capacity(11);
176 end_serializer
177 .extend_u8(VERSION)
178 .extend_u8(KeyKind::IndexEntry as u8)
179 .extend_primitive_id(next_primitive);
180
181 EncodedKeyRange {
182 start: Bound::Included(start_serializer.to_encoded_key()),
183 end: Bound::Excluded(end_serializer.to_encoded_key()),
184 }
185 }
186
187 pub fn key_prefix_range(
190 primitive: impl Into<PrimitiveId>,
191 index: IndexId,
192 key_prefix: &[u8],
193 ) -> EncodedKeyRange {
194 let primitive = primitive.into();
195 let mut serializer = KeySerializer::with_capacity(20 + key_prefix.len());
196 serializer
197 .extend_u8(VERSION)
198 .extend_u8(KeyKind::IndexEntry as u8)
199 .extend_primitive_id(primitive)
200 .extend_index_id(index)
201 .extend_raw(key_prefix);
202 let start = serializer.to_encoded_key();
203
204 let mut end = start.as_slice().to_vec();
206 end.push(0xFF);
207
208 EncodedKeyRange {
209 start: Bound::Included(start),
210 end: Bound::Excluded(EncodedKey::new(end)),
211 }
212 }
213
214 pub fn key_range(
218 primitive: impl Into<PrimitiveId>,
219 index: IndexId,
220 index_range: EncodedIndexKeyRange,
221 ) -> EncodedKeyRange {
222 let primitive = primitive.into();
223 let mut prefix_serializer = KeySerializer::with_capacity(20);
225 prefix_serializer
226 .extend_u8(VERSION)
227 .extend_u8(KeyKind::IndexEntry as u8)
228 .extend_primitive_id(primitive)
229 .extend_index_id(index);
230 let prefix = prefix_serializer.to_encoded_key().to_vec();
231
232 let start = match index_range.start {
234 Bound::Included(key) => {
235 let mut bytes = prefix.clone();
236 bytes.extend_from_slice(key.as_slice());
237 Bound::Included(EncodedKey::new(bytes))
238 }
239 Bound::Excluded(key) => {
240 let mut bytes = prefix.clone();
241 bytes.extend_from_slice(key.as_slice());
242 Bound::Excluded(EncodedKey::new(bytes))
243 }
244 Bound::Unbounded => {
245 Bound::Included(EncodedKey::new(prefix.clone()))
247 }
248 };
249
250 let end = match index_range.end {
251 Bound::Included(key) => {
252 let mut bytes = prefix.clone();
253 bytes.extend_from_slice(key.as_slice());
254 Bound::Included(EncodedKey::new(bytes))
255 }
256 Bound::Excluded(key) => {
257 let mut bytes = prefix.clone();
258 bytes.extend_from_slice(key.as_slice());
259 Bound::Excluded(EncodedKey::new(bytes))
260 }
261 Bound::Unbounded => {
262 let mut serializer = KeySerializer::with_capacity(20);
264 serializer
265 .extend_u8(VERSION)
266 .extend_u8(KeyKind::IndexEntry as u8)
267 .extend_primitive_id(primitive)
268 .extend_index_id(index.prev());
270 Bound::Excluded(serializer.to_encoded_key())
271 }
272 };
273
274 EncodedKeyRange {
275 start,
276 end,
277 }
278 }
279}
280
281#[cfg(test)]
282pub mod tests {
283 use reifydb_type::value::r#type::Type;
284
285 use super::*;
286 use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
287
288 #[test]
289 fn test_encode_decode() {
290 let layout =
292 EncodedIndexLayout::new(&[Type::Uint8, Type::Uint8], &[SortDirection::Asc, SortDirection::Asc])
293 .unwrap();
294
295 let mut index_key = layout.allocate_key();
296 layout.set_u64(&mut index_key, 0, 100u64);
297 layout.set_row_number(&mut index_key, 1, 1u64);
298
299 let entry = IndexEntryKey {
300 primitive: PrimitiveId::table(42),
301 index: IndexId::primary(7),
302 key: index_key.clone(),
303 };
304
305 let encoded = entry.encode();
306 let decoded = IndexEntryKey::decode(&encoded).unwrap();
307
308 assert_eq!(decoded.primitive, PrimitiveId::table(42));
309 assert_eq!(decoded.index, IndexId::primary(7));
310 assert_eq!(decoded.key.as_slice(), index_key.as_slice());
311 }
312
313 #[test]
314 fn test_ordering() {
315 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
316
317 let mut key1 = layout.allocate_key();
318 layout.set_u64(&mut key1, 0, 100u64);
319
320 let mut key2 = layout.allocate_key();
321 layout.set_u64(&mut key2, 0, 200u64);
322
323 let entry1 = IndexEntryKey {
325 primitive: PrimitiveId::table(1),
326 index: IndexId::primary(1),
327 key: key1,
328 };
329
330 let entry2 = IndexEntryKey {
331 primitive: PrimitiveId::table(1),
332 index: IndexId::primary(1),
333 key: key2,
334 };
335
336 let encoded1 = entry1.encode();
337 let encoded2 = entry2.encode();
338
339 assert!(encoded1.as_slice() < encoded2.as_slice());
341 }
342
343 #[test]
344 fn test_index_range() {
345 let range = IndexEntryKey::index_range(PrimitiveId::table(10), IndexId::primary(5));
346
347 let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
349
350 let mut key = layout.allocate_key();
351 layout.set_u64(&mut key, 0, 50u64);
352
353 let entry = IndexEntryKey {
354 primitive: PrimitiveId::table(10),
355 index: IndexId::primary(5),
356 key,
357 };
358
359 let encoded = entry.encode();
360
361 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
363 assert!(encoded.as_slice() >= start.as_slice());
364 assert!(encoded.as_slice() < end.as_slice());
365 } else {
366 panic!("Expected Included/Excluded bounds");
367 }
368
369 let entry2 = IndexEntryKey {
374 primitive: PrimitiveId::table(10),
375 index: IndexId::primary(6),
376 key: layout.allocate_key(),
377 };
378
379 let encoded2 = entry2.encode();
380 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
383 assert!(encoded2.as_slice() < start.as_slice() || encoded2.as_slice() >= end.as_slice());
385 }
386 }
387
388 #[test]
389 fn test_key_prefix_range() {
390 let layout =
391 EncodedIndexLayout::new(&[Type::Uint8, Type::Uint8], &[SortDirection::Asc, SortDirection::Asc])
392 .unwrap();
393
394 let mut key = layout.allocate_key();
395 layout.set_u64(&mut key, 0, 100u64);
396 layout.set_row_number(&mut key, 1, 0u64); let prefix = &key.as_slice()[..layout.fields[1].offset]; let range = IndexEntryKey::key_prefix_range(PrimitiveId::table(1), IndexId::primary(1), prefix);
401
402 layout.set_row_number(&mut key, 1, 999u64);
404 let entry = IndexEntryKey {
405 primitive: PrimitiveId::table(1),
406 index: IndexId::primary(1),
407 key: key.clone(),
408 };
409
410 let encoded = entry.encode();
411
412 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
414 assert!(encoded.as_slice() >= start.as_slice());
415 assert!(encoded.as_slice() < end.as_slice());
416 }
417
418 let mut key2 = layout.allocate_key();
420 layout.set_u64(&mut key2, 0, 200u64); layout.set_row_number(&mut key2, 1, 1u64);
422
423 let entry2 = IndexEntryKey {
424 primitive: PrimitiveId::table(1),
425 index: IndexId::primary(1),
426 key: key2,
427 };
428
429 let encoded2 = entry2.encode();
430
431 if let Bound::Excluded(end) = &range.end {
433 assert!(encoded2.as_slice() >= end.as_slice());
434 }
435 }
436}