Skip to main content

reifydb_core/value/index/
get.rs

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