Skip to main content

reifydb_core/value/index/
get.rs

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