reifydb_core/value/index/
get.rs

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