Skip to main content

reifydb_core/value/index/
get.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::ptr;
5
6use reifydb_type::value::{
7	date::Date,
8	datetime::DateTime,
9	duration::Duration,
10	identity::IdentityId,
11	time::Time,
12	r#type::Type,
13	uuid::{Uuid4, Uuid7},
14};
15use uuid::Uuid;
16
17use crate::{
18	sort::SortDirection,
19	value::index::{encoded::EncodedIndexKey, shape::IndexShape},
20};
21
22impl IndexShape {
23	pub fn get_bool(&self, key: &EncodedIndexKey, index: usize) -> bool {
24		let field = &self.fields[index];
25		debug_assert_eq!(field.value, Type::Boolean);
26
27		let byte = unsafe { *key.as_ptr().add(field.offset) };
28
29		match field.direction {
30			SortDirection::Asc => byte != 0,
31			SortDirection::Desc => byte == 0,
32		}
33	}
34
35	pub fn get_f32(&self, key: &EncodedIndexKey, index: usize) -> f32 {
36		let field = &self.fields[index];
37		debug_assert_eq!(field.value, Type::Float4);
38
39		let mut bytes = [0u8; 4];
40		unsafe {
41			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 4);
42		}
43
44		// For DESC, undo the inversion first
45		if field.direction == SortDirection::Desc {
46			for b in bytes.iter_mut() {
47				*b = !*b;
48			}
49		}
50
51		// Now undo the ASC encoding
52		if bytes[0] & 0x80 != 0 {
53			bytes[0] ^= 0x80;
54		} else {
55			for b in bytes.iter_mut() {
56				*b = !*b;
57			}
58		}
59
60		f32::from_bits(u32::from_be_bytes(bytes))
61	}
62
63	pub fn get_f64(&self, key: &EncodedIndexKey, index: usize) -> f64 {
64		let field = &self.fields[index];
65		debug_assert_eq!(field.value, Type::Float8);
66
67		let mut bytes = [0u8; 8];
68		unsafe {
69			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
70		}
71
72		// For DESC, undo the inversion first
73		if field.direction == SortDirection::Desc {
74			for b in bytes.iter_mut() {
75				*b = !*b;
76			}
77		}
78
79		// Now undo the ASC encoding
80		if bytes[0] & 0x80 != 0 {
81			bytes[0] ^= 0x80;
82		} else {
83			for b in bytes.iter_mut() {
84				*b = !*b;
85			}
86		}
87
88		f64::from_bits(u64::from_be_bytes(bytes))
89	}
90
91	pub fn get_i8(&self, key: &EncodedIndexKey, index: usize) -> i8 {
92		let field = &self.fields[index];
93		debug_assert_eq!(field.value, Type::Int1);
94
95		let mut byte = unsafe { *key.as_ptr().add(field.offset) };
96
97		match field.direction {
98			SortDirection::Asc => {
99				byte ^= 0x80;
100			}
101			SortDirection::Desc => {
102				byte = !byte;
103				byte ^= 0x80;
104			}
105		}
106
107		i8::from_be_bytes([byte])
108	}
109
110	pub fn get_i16(&self, key: &EncodedIndexKey, index: usize) -> i16 {
111		let field = &self.fields[index];
112		debug_assert_eq!(field.value, Type::Int2);
113
114		let mut bytes = [0u8; 2];
115		unsafe {
116			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 2);
117		}
118
119		match field.direction {
120			SortDirection::Asc => {
121				bytes[0] ^= 0x80;
122			}
123			SortDirection::Desc => {
124				for b in bytes.iter_mut() {
125					*b = !*b;
126				}
127				bytes[0] ^= 0x80;
128			}
129		}
130
131		i16::from_be_bytes(bytes)
132	}
133
134	pub fn get_i32(&self, key: &EncodedIndexKey, index: usize) -> i32 {
135		let field = &self.fields[index];
136		debug_assert_eq!(field.value, Type::Int4);
137
138		let mut bytes = [0u8; 4];
139		unsafe {
140			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 4);
141		}
142
143		match field.direction {
144			SortDirection::Asc => {
145				bytes[0] ^= 0x80;
146			}
147			SortDirection::Desc => {
148				for b in bytes.iter_mut() {
149					*b = !*b;
150				}
151				bytes[0] ^= 0x80;
152			}
153		}
154
155		i32::from_be_bytes(bytes)
156	}
157
158	pub fn get_i64(&self, key: &EncodedIndexKey, index: usize) -> i64 {
159		let field = &self.fields[index];
160		debug_assert_eq!(field.value, Type::Int8);
161
162		let mut bytes = [0u8; 8];
163		unsafe {
164			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
165		}
166
167		match field.direction {
168			SortDirection::Asc => {
169				bytes[0] ^= 0x80;
170			}
171			SortDirection::Desc => {
172				for b in bytes.iter_mut() {
173					*b = !*b;
174				}
175				bytes[0] ^= 0x80;
176			}
177		}
178
179		i64::from_be_bytes(bytes)
180	}
181
182	pub fn get_i128(&self, key: &EncodedIndexKey, index: usize) -> i128 {
183		let field = &self.fields[index];
184		debug_assert_eq!(field.value, Type::Int16);
185
186		let mut bytes = [0u8; 16];
187		unsafe {
188			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 16);
189		}
190
191		match field.direction {
192			SortDirection::Asc => {
193				bytes[0] ^= 0x80;
194			}
195			SortDirection::Desc => {
196				for b in bytes.iter_mut() {
197					*b = !*b;
198				}
199				bytes[0] ^= 0x80;
200			}
201		}
202
203		i128::from_be_bytes(bytes)
204	}
205
206	pub fn get_u8(&self, key: &EncodedIndexKey, index: usize) -> u8 {
207		let field = &self.fields[index];
208		debug_assert_eq!(field.value, Type::Uint1);
209
210		let byte = unsafe { *key.as_ptr().add(field.offset) };
211
212		match field.direction {
213			SortDirection::Asc => byte,
214			SortDirection::Desc => !byte,
215		}
216	}
217
218	pub fn get_u16(&self, key: &EncodedIndexKey, index: usize) -> u16 {
219		let field = &self.fields[index];
220		debug_assert_eq!(field.value, Type::Uint2);
221
222		let mut bytes = [0u8; 2];
223		unsafe {
224			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 2);
225		}
226
227		match field.direction {
228			SortDirection::Asc => u16::from_be_bytes(bytes),
229			SortDirection::Desc => !u16::from_be_bytes(bytes),
230		}
231	}
232
233	pub fn get_u32(&self, key: &EncodedIndexKey, index: usize) -> u32 {
234		let field = &self.fields[index];
235		debug_assert_eq!(field.value, Type::Uint4);
236
237		let mut bytes = [0u8; 4];
238		unsafe {
239			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 4);
240		}
241
242		match field.direction {
243			SortDirection::Asc => u32::from_be_bytes(bytes),
244			SortDirection::Desc => !u32::from_be_bytes(bytes),
245		}
246	}
247
248	pub fn get_u64(&self, key: &EncodedIndexKey, index: usize) -> u64 {
249		let field = &self.fields[index];
250		debug_assert_eq!(field.value, Type::Uint8);
251
252		let mut bytes = [0u8; 8];
253		unsafe {
254			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
255		}
256
257		match field.direction {
258			SortDirection::Asc => u64::from_be_bytes(bytes),
259			SortDirection::Desc => !u64::from_be_bytes(bytes),
260		}
261	}
262
263	pub fn get_u128(&self, key: &EncodedIndexKey, index: usize) -> u128 {
264		let field = &self.fields[index];
265		debug_assert_eq!(field.value, Type::Uint16);
266
267		let mut bytes = [0u8; 16];
268		unsafe {
269			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 16);
270		}
271
272		match field.direction {
273			SortDirection::Asc => u128::from_be_bytes(bytes),
274			SortDirection::Desc => !u128::from_be_bytes(bytes),
275		}
276	}
277
278	pub fn get_row_number(&self, key: &EncodedIndexKey, index: usize) -> u64 {
279		let field = &self.fields[index];
280		debug_assert_eq!(field.value, Type::Uint8);
281
282		let mut bytes = [0u8; 8];
283		unsafe {
284			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
285		}
286
287		match field.direction {
288			SortDirection::Asc => u64::from_be_bytes(bytes),
289			SortDirection::Desc => !u64::from_be_bytes(bytes),
290		}
291	}
292
293	pub fn get_date(&self, key: &EncodedIndexKey, index: usize) -> Date {
294		let field = &self.fields[index];
295		debug_assert_eq!(field.value, Type::Date);
296
297		let mut bytes = [0u8; 4];
298		unsafe {
299			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 4);
300		}
301
302		match field.direction {
303			SortDirection::Asc => {
304				bytes[0] ^= 0x80;
305			}
306			SortDirection::Desc => {
307				for b in bytes.iter_mut() {
308					*b = !*b;
309				}
310				bytes[0] ^= 0x80;
311			}
312		}
313
314		let days = i32::from_be_bytes(bytes);
315		Date::from_days_since_epoch(days).unwrap()
316	}
317
318	pub fn get_datetime(&self, key: &EncodedIndexKey, index: usize) -> DateTime {
319		let field = &self.fields[index];
320		debug_assert_eq!(field.value, Type::DateTime);
321
322		let mut bytes = [0u8; 8];
323
324		unsafe {
325			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
326		}
327
328		let nanos = match field.direction {
329			SortDirection::Asc => u64::from_be_bytes(bytes),
330			SortDirection::Desc => !u64::from_be_bytes(bytes),
331		};
332
333		DateTime::from_nanos(nanos)
334	}
335
336	pub fn get_time(&self, key: &EncodedIndexKey, index: usize) -> Time {
337		let field = &self.fields[index];
338		debug_assert_eq!(field.value, Type::Time);
339
340		let mut bytes = [0u8; 8];
341		unsafe {
342			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 8);
343		}
344
345		let nanos = match field.direction {
346			SortDirection::Asc => u64::from_be_bytes(bytes),
347			SortDirection::Desc => !u64::from_be_bytes(bytes),
348		};
349
350		Time::from_nanos_since_midnight(nanos).unwrap()
351	}
352
353	pub fn get_duration(&self, key: &EncodedIndexKey, index: usize) -> Duration {
354		let field = &self.fields[index];
355		debug_assert_eq!(field.value, Type::Duration);
356
357		let mut months_bytes = [0u8; 4];
358		let mut days_bytes = [0u8; 4];
359		let mut nanos_bytes = [0u8; 8];
360
361		unsafe {
362			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), months_bytes.as_mut_ptr(), 4);
363			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset + 4), days_bytes.as_mut_ptr(), 4);
364			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset + 8), nanos_bytes.as_mut_ptr(), 8);
365		}
366
367		match field.direction {
368			SortDirection::Asc => {
369				months_bytes[0] ^= 0x80;
370				days_bytes[0] ^= 0x80;
371				nanos_bytes[0] ^= 0x80;
372			}
373			SortDirection::Desc => {
374				for b in months_bytes.iter_mut() {
375					*b = !*b;
376				}
377				months_bytes[0] ^= 0x80;
378				for b in days_bytes.iter_mut() {
379					*b = !*b;
380				}
381				days_bytes[0] ^= 0x80;
382				for b in nanos_bytes.iter_mut() {
383					*b = !*b;
384				}
385				nanos_bytes[0] ^= 0x80;
386			}
387		}
388
389		let months = i32::from_be_bytes(months_bytes);
390		let days = i32::from_be_bytes(days_bytes);
391		let nanos = i64::from_be_bytes(nanos_bytes);
392		Duration::new(months, days, nanos).expect("stored duration must be valid")
393	}
394
395	pub fn get_uuid4(&self, key: &EncodedIndexKey, index: usize) -> Uuid4 {
396		let field = &self.fields[index];
397		debug_assert_eq!(field.value, Type::Uuid4);
398
399		let mut bytes = [0u8; 16];
400		unsafe {
401			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 16);
402		}
403
404		if field.direction == SortDirection::Desc {
405			for b in bytes.iter_mut() {
406				*b = !*b;
407			}
408		}
409
410		let uuid = Uuid::from_bytes(bytes);
411		Uuid4::from(uuid)
412	}
413
414	pub fn get_uuid7(&self, key: &EncodedIndexKey, index: usize) -> Uuid7 {
415		let field = &self.fields[index];
416		debug_assert_eq!(field.value, Type::Uuid7);
417
418		let mut bytes = [0u8; 16];
419		unsafe {
420			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 16);
421		}
422
423		if field.direction == SortDirection::Desc {
424			for b in bytes.iter_mut() {
425				*b = !*b;
426			}
427		}
428
429		let uuid = Uuid::from_bytes(bytes);
430		Uuid7::from(uuid)
431	}
432
433	pub fn get_identity_id(&self, key: &EncodedIndexKey, index: usize) -> IdentityId {
434		let field = &self.fields[index];
435		debug_assert_eq!(field.value, Type::IdentityId);
436
437		let mut bytes = [0u8; 16];
438		unsafe {
439			ptr::copy_nonoverlapping(key.as_ptr().add(field.offset), bytes.as_mut_ptr(), 16);
440		}
441
442		if field.direction == SortDirection::Desc {
443			for b in bytes.iter_mut() {
444				*b = !*b;
445			}
446		}
447
448		let uuid = Uuid::from_bytes(bytes);
449		let uuid7 = Uuid7::from(uuid);
450		IdentityId::from(uuid7)
451	}
452}
453
454#[cfg(test)]
455pub mod tests {
456	use reifydb_type::value::r#type::Type;
457
458	use crate::{sort::SortDirection, value::index::shape::IndexShape};
459
460	mod bool {
461		use super::*;
462
463		#[test]
464		fn test_asc() {
465			let layout = IndexShape::new(&[Type::Boolean], &[SortDirection::Asc]).unwrap();
466			let mut key1 = layout.allocate_key();
467			let mut key2 = layout.allocate_key();
468
469			layout.set_bool(&mut key1, 0, false);
470			layout.set_bool(&mut key2, 0, true);
471
472			assert!(key1.as_slice() < key2.as_slice());
473			assert_eq!(layout.get_bool(&key1, 0), false);
474			assert_eq!(layout.get_bool(&key2, 0), true);
475		}
476
477		#[test]
478		fn test_desc() {
479			let layout = IndexShape::new(&[Type::Boolean], &[SortDirection::Desc]).unwrap();
480			let mut key1 = layout.allocate_key();
481			let mut key2 = layout.allocate_key();
482
483			layout.set_bool(&mut key1, 0, false);
484			layout.set_bool(&mut key2, 0, true);
485
486			assert!(key1.as_slice() > key2.as_slice());
487			assert_eq!(layout.get_bool(&key1, 0), false);
488			assert_eq!(layout.get_bool(&key2, 0), true);
489		}
490	}
491
492	mod i8 {
493		use reifydb_type::value::r#type::Type;
494
495		use crate::{sort::SortDirection, value::index::shape::IndexShape};
496
497		#[test]
498		fn test_asc() {
499			let layout = IndexShape::new(&[Type::Int1], &[SortDirection::Asc]).unwrap();
500			let mut key1 = layout.allocate_key();
501			let mut key2 = layout.allocate_key();
502			let mut key3 = layout.allocate_key();
503
504			layout.set_i8(&mut key1, 0, -10);
505			layout.set_i8(&mut key2, 0, 0);
506			layout.set_i8(&mut key3, 0, 10);
507
508			assert!(key1.as_slice() < key2.as_slice());
509			assert!(key2.as_slice() < key3.as_slice());
510			assert_eq!(layout.get_i8(&key1, 0), -10);
511			assert_eq!(layout.get_i8(&key2, 0), 0);
512			assert_eq!(layout.get_i8(&key3, 0), 10);
513		}
514
515		#[test]
516		fn test_desc() {
517			let layout = IndexShape::new(&[Type::Int1], &[SortDirection::Desc]).unwrap();
518			let mut key1 = layout.allocate_key();
519			let mut key2 = layout.allocate_key();
520			let mut key3 = layout.allocate_key();
521
522			layout.set_i8(&mut key1, 0, -10);
523			layout.set_i8(&mut key2, 0, 0);
524			layout.set_i8(&mut key3, 0, 10);
525
526			assert!(key1.as_slice() > key2.as_slice());
527			assert!(key2.as_slice() > key3.as_slice());
528			assert_eq!(layout.get_i8(&key1, 0), -10);
529			assert_eq!(layout.get_i8(&key2, 0), 0);
530			assert_eq!(layout.get_i8(&key3, 0), 10);
531		}
532	}
533
534	mod i32 {
535		use reifydb_type::value::r#type::Type;
536
537		use crate::{sort::SortDirection, value::index::shape::IndexShape};
538
539		#[test]
540		fn test_asc() {
541			let layout = IndexShape::new(&[Type::Int4], &[SortDirection::Asc]).unwrap();
542			let mut key1 = layout.allocate_key();
543			let mut key2 = layout.allocate_key();
544			let mut key3 = layout.allocate_key();
545
546			layout.set_i32(&mut key1, 0, -1000);
547			layout.set_i32(&mut key2, 0, 0);
548			layout.set_i32(&mut key3, 0, 1000);
549
550			assert!(key1.as_slice() < key2.as_slice());
551			assert!(key2.as_slice() < key3.as_slice());
552			assert_eq!(layout.get_i32(&key1, 0), -1000);
553			assert_eq!(layout.get_i32(&key2, 0), 0);
554			assert_eq!(layout.get_i32(&key3, 0), 1000);
555		}
556
557		#[test]
558		fn test_desc() {
559			let layout = IndexShape::new(&[Type::Int4], &[SortDirection::Desc]).unwrap();
560			let mut key1 = layout.allocate_key();
561			let mut key2 = layout.allocate_key();
562			let mut key3 = layout.allocate_key();
563
564			layout.set_i32(&mut key1, 0, -1000);
565			layout.set_i32(&mut key2, 0, 0);
566			layout.set_i32(&mut key3, 0, 1000);
567
568			assert!(key1.as_slice() > key2.as_slice());
569			assert!(key2.as_slice() > key3.as_slice());
570			assert_eq!(layout.get_i32(&key1, 0), -1000);
571			assert_eq!(layout.get_i32(&key2, 0), 0);
572			assert_eq!(layout.get_i32(&key3, 0), 1000);
573		}
574	}
575
576	mod i64 {
577		use reifydb_type::value::r#type::Type;
578
579		use crate::{sort::SortDirection, value::index::shape::IndexShape};
580
581		#[test]
582		fn test_asc() {
583			let layout = IndexShape::new(&[Type::Int8], &[SortDirection::Asc]).unwrap();
584			let mut key1 = layout.allocate_key();
585			let mut key2 = layout.allocate_key();
586			let mut key3 = layout.allocate_key();
587
588			layout.set_i64(&mut key1, 0, i64::MIN);
589			layout.set_i64(&mut key2, 0, 0);
590			layout.set_i64(&mut key3, 0, i64::MAX);
591
592			assert!(key1.as_slice() < key2.as_slice());
593			assert!(key2.as_slice() < key3.as_slice());
594			assert_eq!(layout.get_i64(&key1, 0), i64::MIN);
595			assert_eq!(layout.get_i64(&key2, 0), 0);
596			assert_eq!(layout.get_i64(&key3, 0), i64::MAX);
597		}
598
599		#[test]
600		fn test_desc() {
601			let layout = IndexShape::new(&[Type::Int8], &[SortDirection::Desc]).unwrap();
602			let mut key1 = layout.allocate_key();
603			let mut key2 = layout.allocate_key();
604			let mut key3 = layout.allocate_key();
605
606			layout.set_i64(&mut key1, 0, i64::MIN);
607			layout.set_i64(&mut key2, 0, 0);
608			layout.set_i64(&mut key3, 0, i64::MAX);
609
610			assert!(key1.as_slice() > key2.as_slice());
611			assert!(key2.as_slice() > key3.as_slice());
612			assert_eq!(layout.get_i64(&key1, 0), i64::MIN);
613			assert_eq!(layout.get_i64(&key2, 0), 0);
614			assert_eq!(layout.get_i64(&key3, 0), i64::MAX);
615		}
616	}
617
618	mod u8 {
619		use reifydb_type::value::r#type::Type;
620
621		use crate::{sort::SortDirection, value::index::shape::IndexShape};
622
623		#[test]
624		fn test_asc() {
625			let layout = IndexShape::new(&[Type::Uint1], &[SortDirection::Asc]).unwrap();
626			let mut key1 = layout.allocate_key();
627			let mut key2 = layout.allocate_key();
628			let mut key3 = layout.allocate_key();
629
630			layout.set_u8(&mut key1, 0, 0);
631			layout.set_u8(&mut key2, 0, 128);
632			layout.set_u8(&mut key3, 0, 255);
633
634			assert!(key1.as_slice() < key2.as_slice());
635			assert!(key2.as_slice() < key3.as_slice());
636			assert_eq!(layout.get_u8(&key1, 0), 0);
637			assert_eq!(layout.get_u8(&key2, 0), 128);
638			assert_eq!(layout.get_u8(&key3, 0), 255);
639		}
640
641		#[test]
642		fn test_desc() {
643			let layout = IndexShape::new(&[Type::Uint1], &[SortDirection::Desc]).unwrap();
644			let mut key1 = layout.allocate_key();
645			let mut key2 = layout.allocate_key();
646			let mut key3 = layout.allocate_key();
647
648			layout.set_u8(&mut key1, 0, 0);
649			layout.set_u8(&mut key2, 0, 128);
650			layout.set_u8(&mut key3, 0, 255);
651
652			assert!(key1.as_slice() > key2.as_slice());
653			assert!(key2.as_slice() > key3.as_slice());
654			assert_eq!(layout.get_u8(&key1, 0), 0);
655			assert_eq!(layout.get_u8(&key2, 0), 128);
656			assert_eq!(layout.get_u8(&key3, 0), 255);
657		}
658	}
659
660	mod u32 {
661		use reifydb_type::value::r#type::Type;
662
663		use crate::{sort::SortDirection, value::index::shape::IndexShape};
664
665		#[test]
666		fn test_asc() {
667			let layout = IndexShape::new(&[Type::Uint4], &[SortDirection::Asc]).unwrap();
668			let mut key1 = layout.allocate_key();
669			let mut key2 = layout.allocate_key();
670			let mut key3 = layout.allocate_key();
671
672			layout.set_u32(&mut key1, 0, 0u32);
673			layout.set_u32(&mut key2, 0, 1000000u32);
674			layout.set_u32(&mut key3, 0, u32::MAX);
675
676			assert!(key1.as_slice() < key2.as_slice());
677			assert!(key2.as_slice() < key3.as_slice());
678			assert_eq!(layout.get_u32(&key1, 0), 0);
679			assert_eq!(layout.get_u32(&key2, 0), 1000000);
680			assert_eq!(layout.get_u32(&key3, 0), u32::MAX);
681		}
682
683		#[test]
684		fn test_desc() {
685			let layout = IndexShape::new(&[Type::Uint4], &[SortDirection::Desc]).unwrap();
686			let mut key1 = layout.allocate_key();
687			let mut key2 = layout.allocate_key();
688			let mut key3 = layout.allocate_key();
689
690			layout.set_u32(&mut key1, 0, 0u32);
691			layout.set_u32(&mut key2, 0, 1000000u32);
692			layout.set_u32(&mut key3, 0, u32::MAX);
693
694			assert!(key1.as_slice() > key2.as_slice());
695			assert!(key2.as_slice() > key3.as_slice());
696			assert_eq!(layout.get_u32(&key1, 0), 0);
697			assert_eq!(layout.get_u32(&key2, 0), 1000000);
698			assert_eq!(layout.get_u32(&key3, 0), u32::MAX);
699		}
700	}
701
702	mod u64 {
703		use reifydb_type::value::r#type::Type;
704
705		use crate::{sort::SortDirection, value::index::shape::IndexShape};
706
707		#[test]
708		fn test_asc() {
709			let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
710			let mut key1 = layout.allocate_key();
711			let mut key2 = layout.allocate_key();
712			let mut key3 = layout.allocate_key();
713
714			layout.set_u64(&mut key1, 0, 0u64);
715			layout.set_u64(&mut key2, 0, 1_000_000_000u64);
716			layout.set_u64(&mut key3, 0, u64::MAX);
717
718			assert!(key1.as_slice() < key2.as_slice());
719			assert!(key2.as_slice() < key3.as_slice());
720			assert_eq!(layout.get_u64(&key1, 0), 0);
721			assert_eq!(layout.get_u64(&key2, 0), 1_000_000_000);
722			assert_eq!(layout.get_u64(&key3, 0), u64::MAX);
723		}
724
725		#[test]
726		fn test_desc() {
727			let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Desc]).unwrap();
728			let mut key1 = layout.allocate_key();
729			let mut key2 = layout.allocate_key();
730			let mut key3 = layout.allocate_key();
731
732			layout.set_u64(&mut key1, 0, 0u64);
733			layout.set_u64(&mut key2, 0, 1_000_000_000u64);
734			layout.set_u64(&mut key3, 0, u64::MAX);
735
736			assert!(key1.as_slice() > key2.as_slice());
737			assert!(key2.as_slice() > key3.as_slice());
738			assert_eq!(layout.get_u64(&key1, 0), 0);
739			assert_eq!(layout.get_u64(&key2, 0), 1_000_000_000);
740			assert_eq!(layout.get_u64(&key3, 0), u64::MAX);
741		}
742	}
743
744	mod f32 {
745		use reifydb_type::value::r#type::Type;
746
747		use crate::{sort::SortDirection, value::index::shape::IndexShape};
748
749		#[test]
750		fn test_asc() {
751			let layout = IndexShape::new(&[Type::Float4], &[SortDirection::Asc]).unwrap();
752			let mut key1 = layout.allocate_key();
753			let mut key2 = layout.allocate_key();
754			let mut key3 = layout.allocate_key();
755
756			layout.set_f32(&mut key1, 0, -100.5);
757			layout.set_f32(&mut key2, 0, 0.0);
758			layout.set_f32(&mut key3, 0, 100.5);
759
760			assert!(key1.as_slice() < key2.as_slice());
761			assert!(key2.as_slice() < key3.as_slice());
762			assert_eq!(layout.get_f32(&key1, 0), -100.5);
763			assert_eq!(layout.get_f32(&key2, 0), 0.0);
764			assert_eq!(layout.get_f32(&key3, 0), 100.5);
765		}
766
767		#[test]
768		fn test_desc() {
769			let layout = IndexShape::new(&[Type::Float4], &[SortDirection::Desc]).unwrap();
770			let mut key1 = layout.allocate_key();
771			let mut key2 = layout.allocate_key();
772			let mut key3 = layout.allocate_key();
773
774			layout.set_f32(&mut key1, 0, -100.5);
775			layout.set_f32(&mut key2, 0, 0.0);
776			layout.set_f32(&mut key3, 0, 100.5);
777
778			assert!(key1.as_slice() > key2.as_slice());
779			assert!(key2.as_slice() > key3.as_slice());
780			assert_eq!(layout.get_f32(&key1, 0), -100.5);
781			assert_eq!(layout.get_f32(&key2, 0), 0.0);
782			assert_eq!(layout.get_f32(&key3, 0), 100.5);
783		}
784	}
785
786	mod f64 {
787		use reifydb_type::value::r#type::Type;
788
789		use crate::{sort::SortDirection, value::index::shape::IndexShape};
790
791		#[test]
792		fn test_asc() {
793			let layout = IndexShape::new(&[Type::Float8], &[SortDirection::Asc]).unwrap();
794			let mut key1 = layout.allocate_key();
795			let mut key2 = layout.allocate_key();
796			let mut key3 = layout.allocate_key();
797
798			layout.set_f64(&mut key1, 0, -1000.123456);
799			layout.set_f64(&mut key2, 0, 0.0);
800			layout.set_f64(&mut key3, 0, 1000.123456);
801
802			assert!(key1.as_slice() < key2.as_slice());
803			assert!(key2.as_slice() < key3.as_slice());
804			assert_eq!(layout.get_f64(&key1, 0), -1000.123456);
805			assert_eq!(layout.get_f64(&key2, 0), 0.0);
806			assert_eq!(layout.get_f64(&key3, 0), 1000.123456);
807		}
808
809		#[test]
810		fn test_desc() {
811			let layout = IndexShape::new(&[Type::Float8], &[SortDirection::Desc]).unwrap();
812			let mut key1 = layout.allocate_key();
813			let mut key2 = layout.allocate_key();
814			let mut key3 = layout.allocate_key();
815
816			layout.set_f64(&mut key1, 0, -1000.123456);
817			layout.set_f64(&mut key2, 0, 0.0);
818			layout.set_f64(&mut key3, 0, 1000.123456);
819
820			assert!(key1.as_slice() > key2.as_slice());
821			assert!(key2.as_slice() > key3.as_slice());
822			assert_eq!(layout.get_f64(&key1, 0), -1000.123456);
823			assert_eq!(layout.get_f64(&key2, 0), 0.0);
824			assert_eq!(layout.get_f64(&key3, 0), 1000.123456);
825		}
826	}
827
828	mod date {
829		use reifydb_type::value::{date::Date, r#type::Type};
830
831		use crate::{sort::SortDirection, value::index::shape::IndexShape};
832
833		#[test]
834		fn test_asc() {
835			let layout = IndexShape::new(&[Type::Date], &[SortDirection::Asc]).unwrap();
836			let mut key1 = layout.allocate_key();
837			let mut key2 = layout.allocate_key();
838			let mut key3 = layout.allocate_key();
839
840			let date1 = Date::new(2020, 1, 1).unwrap();
841			let date2 = Date::new(2023, 6, 15).unwrap();
842			let date3 = Date::new(2025, 12, 31).unwrap();
843
844			layout.set_date(&mut key1, 0, date1.clone());
845			layout.set_date(&mut key2, 0, date2.clone());
846			layout.set_date(&mut key3, 0, date3.clone());
847
848			assert!(key1.as_slice() < key2.as_slice());
849			assert!(key2.as_slice() < key3.as_slice());
850			assert_eq!(layout.get_date(&key1, 0), date1);
851			assert_eq!(layout.get_date(&key2, 0), date2);
852			assert_eq!(layout.get_date(&key3, 0), date3);
853		}
854
855		#[test]
856		fn test_desc() {
857			let layout = IndexShape::new(&[Type::Date], &[SortDirection::Desc]).unwrap();
858			let mut key1 = layout.allocate_key();
859			let mut key2 = layout.allocate_key();
860			let mut key3 = layout.allocate_key();
861
862			let date1 = Date::new(2020, 1, 1).unwrap();
863			let date2 = Date::new(2023, 6, 15).unwrap();
864			let date3 = Date::new(2025, 12, 31).unwrap();
865
866			layout.set_date(&mut key1, 0, date1.clone());
867			layout.set_date(&mut key2, 0, date2.clone());
868			layout.set_date(&mut key3, 0, date3.clone());
869
870			assert!(key1.as_slice() > key2.as_slice());
871			assert!(key2.as_slice() > key3.as_slice());
872			assert_eq!(layout.get_date(&key1, 0), date1);
873			assert_eq!(layout.get_date(&key2, 0), date2);
874			assert_eq!(layout.get_date(&key3, 0), date3);
875		}
876	}
877
878	mod row_number {
879		use reifydb_type::value::r#type::Type;
880
881		use crate::{sort::SortDirection, value::index::shape::IndexShape};
882
883		#[test]
884		fn test_asc() {
885			let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
886			let mut key1 = layout.allocate_key();
887			let mut key2 = layout.allocate_key();
888			let mut key3 = layout.allocate_key();
889
890			layout.set_row_number(&mut key1, 0, 1u64);
891			layout.set_row_number(&mut key2, 0, 1000u64);
892			layout.set_row_number(&mut key3, 0, u64::MAX);
893
894			assert!(key1.as_slice() < key2.as_slice());
895			assert!(key2.as_slice() < key3.as_slice());
896			assert_eq!(layout.get_row_number(&key1, 0), 1);
897			assert_eq!(layout.get_row_number(&key2, 0), 1000);
898			assert_eq!(layout.get_row_number(&key3, 0), u64::MAX);
899		}
900
901		#[test]
902		fn test_desc() {
903			let layout = IndexShape::new(&[Type::Uint8], &[SortDirection::Desc]).unwrap();
904			let mut key1 = layout.allocate_key();
905			let mut key2 = layout.allocate_key();
906			let mut key3 = layout.allocate_key();
907
908			layout.set_row_number(&mut key1, 0, 1u64);
909			layout.set_row_number(&mut key2, 0, 1000u64);
910			layout.set_row_number(&mut key3, 0, u64::MAX);
911
912			assert!(key1.as_slice() > key2.as_slice());
913			assert!(key2.as_slice() > key3.as_slice());
914			assert_eq!(layout.get_row_number(&key1, 0), 1);
915			assert_eq!(layout.get_row_number(&key2, 0), 1000);
916			assert_eq!(layout.get_row_number(&key3, 0), u64::MAX);
917		}
918	}
919
920	mod identity_id {
921		use reifydb_runtime::context::{
922			clock::{Clock, MockClock},
923			rng::Rng,
924		};
925		use reifydb_type::value::{identity::IdentityId, r#type::Type};
926
927		use crate::{sort::SortDirection, value::index::shape::IndexShape};
928
929		fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
930			let mock = MockClock::from_millis(1000);
931			let clock = Clock::Mock(mock.clone());
932			let rng = Rng::seeded(42);
933			(mock, clock, rng)
934		}
935
936		#[test]
937		fn test_asc() {
938			let (mock, clock, rng) = test_clock_and_rng();
939			let layout = IndexShape::new(&[Type::IdentityId], &[SortDirection::Asc]).unwrap();
940			let mut key1 = layout.allocate_key();
941			let mut key2 = layout.allocate_key();
942
943			let id1 = IdentityId::generate(&clock, &rng);
944			// Advance clock to ensure different timestamps
945			mock.advance_millis(10);
946			let id2 = IdentityId::generate(&clock, &rng);
947
948			layout.set_identity_id(&mut key1, 0, id1.clone());
949			layout.set_identity_id(&mut key2, 0, id2.clone());
950
951			// Should be ordered by timestamp
952			assert!(key1.as_slice() < key2.as_slice());
953			// Should decode back to original values
954			assert_eq!(layout.get_identity_id(&key1, 0), id1);
955			assert_eq!(layout.get_identity_id(&key2, 0), id2);
956		}
957
958		#[test]
959		fn test_desc() {
960			let (mock, clock, rng) = test_clock_and_rng();
961			let layout = IndexShape::new(&[Type::IdentityId], &[SortDirection::Desc]).unwrap();
962			let mut key1 = layout.allocate_key();
963			let mut key2 = layout.allocate_key();
964
965			let id1 = IdentityId::generate(&clock, &rng);
966			// Advance clock to ensure different timestamps
967			mock.advance_millis(10);
968			let id2 = IdentityId::generate(&clock, &rng);
969
970			layout.set_identity_id(&mut key1, 0, id1.clone());
971			layout.set_identity_id(&mut key2, 0, id2.clone());
972
973			// Should be reverse ordered for DESC
974			assert!(key1.as_slice() > key2.as_slice());
975			// Should decode back to original values
976			assert_eq!(layout.get_identity_id(&key1, 0), id1);
977			assert_eq!(layout.get_identity_id(&key2, 0), id2);
978		}
979
980		#[test]
981		fn test_roundtrip() {
982			let (_mock, clock, rng) = test_clock_and_rng();
983			let layout = IndexShape::new(&[Type::IdentityId], &[SortDirection::Asc]).unwrap();
984
985			let id = IdentityId::generate(&clock, &rng);
986			let mut key = layout.allocate_key();
987
988			// Set and get should preserve the value
989			layout.set_identity_id(&mut key, 0, id.clone());
990			let retrieved = layout.get_identity_id(&key, 0);
991			assert_eq!(retrieved, id);
992		}
993	}
994
995	mod composite {
996		use reifydb_type::value::r#type::Type;
997
998		use crate::{sort::SortDirection, value::index::shape::IndexShape};
999
1000		#[test]
1001		fn test_mixed_directions() {
1002			let layout = IndexShape::new(
1003				&[Type::Int4, Type::Uint8, Type::Uint8],
1004				&[SortDirection::Desc, SortDirection::Asc, SortDirection::Asc],
1005			)
1006			.unwrap();
1007
1008			let mut key1 = layout.allocate_key();
1009			let mut key2 = layout.allocate_key();
1010			let mut key3 = layout.allocate_key();
1011			let mut key4 = layout.allocate_key();
1012
1013			layout.set_i32(&mut key1, 0, 100);
1014			layout.set_u64(&mut key1, 1, 1u64);
1015			layout.set_row_number(&mut key1, 2, 1u64);
1016
1017			layout.set_i32(&mut key2, 0, 100);
1018			layout.set_u64(&mut key2, 1, 2u64);
1019			layout.set_row_number(&mut key2, 2, 1u64);
1020
1021			layout.set_i32(&mut key3, 0, 50);
1022			layout.set_u64(&mut key3, 1, 1u64);
1023			layout.set_row_number(&mut key3, 2, 1u64);
1024
1025			layout.set_i32(&mut key4, 0, 50);
1026			layout.set_u64(&mut key4, 1, 1u64);
1027			layout.set_row_number(&mut key4, 2, 2u64);
1028
1029			// key1 (100, 1, 1) vs key2 (100, 2, 1): same first
1030			// field, second field ascending
1031			assert!(key1.as_slice() < key2.as_slice());
1032			// key1 (100, 1, 1) vs key3 (50, 1, 1): first field is
1033			// DESC, so 100 < 50 in byte order
1034			assert!(key1.as_slice() < key3.as_slice());
1035			// key3 (50, 1, 1) vs key4 (50, 1, 2): same first two
1036			// fields, third field ascending
1037			assert!(key3.as_slice() < key4.as_slice());
1038		}
1039	}
1040}