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