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_type::value::r#type::Type;
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(&[Type::Uint8, Type::Uint8], &[SortDirection::Asc, SortDirection::Asc])
238 .unwrap();
239
240 let mut index_key = layout.allocate_key();
241 layout.set_u64(&mut index_key, 0, 100u64);
242 layout.set_row_number(&mut index_key, 1, 1u64);
243
244 let entry = IndexEntryKey {
245 shape: ShapeId::table(42),
246 index: IndexId::primary(7),
247 key: index_key.clone(),
248 };
249
250 let encoded = entry.encode();
251 let decoded = IndexEntryKey::decode(&encoded).unwrap();
252
253 assert_eq!(decoded.shape, ShapeId::table(42));
254 assert_eq!(decoded.index, IndexId::primary(7));
255 assert_eq!(decoded.key.as_slice(), index_key.as_slice());
256 }
257
258 #[test]
259 fn test_ordering() {
260 let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
261
262 let mut key1 = layout.allocate_key();
263 layout.set_u64(&mut key1, 0, 100u64);
264
265 let mut key2 = layout.allocate_key();
266 layout.set_u64(&mut key2, 0, 200u64);
267
268 let entry1 = IndexEntryKey {
269 shape: ShapeId::table(1),
270 index: IndexId::primary(1),
271 key: key1,
272 };
273
274 let entry2 = IndexEntryKey {
275 shape: ShapeId::table(1),
276 index: IndexId::primary(1),
277 key: key2,
278 };
279
280 let encoded1 = entry1.encode();
281 let encoded2 = entry2.encode();
282
283 assert!(encoded1.as_slice() < encoded2.as_slice());
284 }
285
286 #[test]
287 fn test_index_range() {
288 let range = IndexEntryKey::index_range(ShapeId::table(10), IndexId::primary(5));
289
290 let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
291
292 let mut key = layout.allocate_key();
293 layout.set_u64(&mut key, 0, 50u64);
294
295 let entry = IndexEntryKey {
296 shape: ShapeId::table(10),
297 index: IndexId::primary(5),
298 key,
299 };
300
301 let encoded = entry.encode();
302
303 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
304 assert!(encoded.as_slice() >= start.as_slice());
305 assert!(encoded.as_slice() < end.as_slice());
306 } else {
307 panic!("Expected Included/Excluded bounds");
308 }
309
310 let entry2 = IndexEntryKey {
311 shape: ShapeId::table(10),
312 index: IndexId::primary(6),
313 key: layout.allocate_key(),
314 };
315
316 let encoded2 = entry2.encode();
317
318 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
319 assert!(encoded2.as_slice() < start.as_slice() || encoded2.as_slice() >= end.as_slice());
320 }
321 }
322
323 #[test]
324 fn test_key_prefix_range() {
325 let layout = IndexShape::new(&[Type::Uint8, Type::Uint8], &[SortDirection::Asc, SortDirection::Asc])
326 .unwrap();
327
328 let mut key = layout.allocate_key();
329 layout.set_u64(&mut key, 0, 100u64);
330 layout.set_row_number(&mut key, 1, 0u64);
331
332 let prefix = &key.as_slice()[..layout.fields[1].offset];
333 let range = IndexEntryKey::key_prefix_range(ShapeId::table(1), IndexId::primary(1), prefix);
334
335 layout.set_row_number(&mut key, 1, 999u64);
336 let entry = IndexEntryKey {
337 shape: ShapeId::table(1),
338 index: IndexId::primary(1),
339 key: key.clone(),
340 };
341
342 let encoded = entry.encode();
343
344 if let (Bound::Included(start), Bound::Excluded(end)) = (&range.start, &range.end) {
345 assert!(encoded.as_slice() >= start.as_slice());
346 assert!(encoded.as_slice() < end.as_slice());
347 }
348
349 let mut key2 = layout.allocate_key();
350 layout.set_u64(&mut key2, 0, 200u64);
351 layout.set_row_number(&mut key2, 1, 1u64);
352
353 let entry2 = IndexEntryKey {
354 shape: ShapeId::table(1),
355 index: IndexId::primary(1),
356 key: key2,
357 };
358
359 let encoded2 = entry2.encode();
360
361 if let Bound::Excluded(end) = &range.end {
362 assert!(encoded2.as_slice() >= end.as_slice());
363 }
364 }
365}