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