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