Skip to main content

reifydb_core/value/index/
set.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::{f64, 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, layout::EncodedIndexLayout},
20};
21
22impl EncodedIndexLayout {
23	pub fn set_bool(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<bool>) {
24		let field = &self.fields[index];
25		debug_assert_eq!(field.value, Type::Boolean);
26		key.set_valid(index, true);
27
28		let byte_value = match field.direction {
29			SortDirection::Asc => {
30				if value.into() {
31					1u8
32				} else {
33					0u8
34				}
35			}
36			SortDirection::Desc => {
37				if value.into() {
38					0u8
39				} else {
40					1u8
41				}
42			}
43		};
44
45		unsafe { ptr::write_unaligned(key.make_mut().as_mut_ptr().add(field.offset), byte_value) }
46	}
47
48	pub fn set_f32(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<f32>) {
49		let field = &self.fields[index];
50		debug_assert_eq!(field.value, Type::Float4);
51		key.set_valid(index, true);
52
53		let v = value.into();
54		let mut bytes = v.to_bits().to_be_bytes();
55
56		// Apply ASC encoding first
57		if v.is_sign_negative() {
58			for b in bytes.iter_mut() {
59				*b = !*b;
60			}
61		} else {
62			bytes[0] ^= 0x80;
63		}
64
65		// For DESC, invert all bytes
66		if field.direction == SortDirection::Desc {
67			for b in bytes.iter_mut() {
68				*b = !*b;
69			}
70		}
71
72		unsafe {
73			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 4);
74		}
75	}
76
77	pub fn set_f64(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<f64>) {
78		let field = &self.fields[index];
79		debug_assert_eq!(field.value, Type::Float8);
80		key.set_valid(index, true);
81
82		let v = value.into();
83		let mut bytes = v.to_bits().to_be_bytes();
84
85		// Apply ASC encoding first
86		if v.is_sign_negative() {
87			for b in bytes.iter_mut() {
88				*b = !*b;
89			}
90		} else {
91			bytes[0] ^= 0x80;
92		}
93
94		// For DESC, invert all bytes
95		if field.direction == SortDirection::Desc {
96			for b in bytes.iter_mut() {
97				*b = !*b;
98			}
99		}
100
101		unsafe {
102			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
103		}
104	}
105
106	pub fn set_i8(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<i8>) {
107		let field = &self.fields[index];
108		debug_assert_eq!(field.value, Type::Int1);
109		key.set_valid(index, true);
110
111		let mut bytes = value.into().to_be_bytes();
112
113		match field.direction {
114			SortDirection::Asc => {
115				bytes[0] ^= 0x80;
116			}
117			SortDirection::Desc => {
118				bytes[0] ^= 0x80;
119				for b in bytes.iter_mut() {
120					*b = !*b;
121				}
122			}
123		}
124
125		unsafe { ptr::write_unaligned(key.make_mut().as_mut_ptr().add(field.offset), bytes[0]) }
126	}
127
128	pub fn set_i16(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<i16>) {
129		let field = &self.fields[index];
130		debug_assert_eq!(field.value, Type::Int2);
131		key.set_valid(index, true);
132
133		let mut bytes = value.into().to_be_bytes();
134
135		match field.direction {
136			SortDirection::Asc => {
137				bytes[0] ^= 0x80;
138			}
139			SortDirection::Desc => {
140				bytes[0] ^= 0x80;
141				for b in bytes.iter_mut() {
142					*b = !*b;
143				}
144			}
145		}
146
147		unsafe {
148			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 2);
149		}
150	}
151
152	pub fn set_i32(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<i32>) {
153		let field = &self.fields[index];
154		debug_assert_eq!(field.value, Type::Int4);
155		key.set_valid(index, true);
156
157		let mut bytes = value.into().to_be_bytes();
158
159		match field.direction {
160			SortDirection::Asc => {
161				bytes[0] ^= 0x80;
162			}
163			SortDirection::Desc => {
164				bytes[0] ^= 0x80;
165				for b in bytes.iter_mut() {
166					*b = !*b;
167				}
168			}
169		}
170
171		unsafe {
172			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 4);
173		}
174	}
175
176	pub fn set_i64(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<i64>) {
177		let field = &self.fields[index];
178		debug_assert_eq!(field.value, Type::Int8);
179		key.set_valid(index, true);
180
181		let mut bytes = value.into().to_be_bytes();
182
183		match field.direction {
184			SortDirection::Asc => {
185				bytes[0] ^= 0x80;
186			}
187			SortDirection::Desc => {
188				bytes[0] ^= 0x80;
189				for b in bytes.iter_mut() {
190					*b = !*b;
191				}
192			}
193		}
194
195		unsafe {
196			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
197		}
198	}
199
200	pub fn set_i128(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<i128>) {
201		let field = &self.fields[index];
202		debug_assert_eq!(field.value, Type::Int16);
203		key.set_valid(index, true);
204
205		let mut bytes = value.into().to_be_bytes();
206
207		match field.direction {
208			SortDirection::Asc => {
209				bytes[0] ^= 0x80;
210			}
211			SortDirection::Desc => {
212				bytes[0] ^= 0x80;
213				for b in bytes.iter_mut() {
214					*b = !*b;
215				}
216			}
217		}
218
219		unsafe {
220			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 16);
221		}
222	}
223
224	pub fn set_u8(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u8>) {
225		let field = &self.fields[index];
226		debug_assert_eq!(field.value, Type::Uint1);
227		key.set_valid(index, true);
228
229		let byte = match field.direction {
230			SortDirection::Asc => value.into(),
231			SortDirection::Desc => !value.into(),
232		};
233
234		unsafe { ptr::write_unaligned(key.make_mut().as_mut_ptr().add(field.offset), byte) }
235	}
236
237	pub fn set_u16(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u16>) {
238		let field = &self.fields[index];
239		debug_assert_eq!(field.value, Type::Uint2);
240		key.set_valid(index, true);
241
242		let bytes = match field.direction {
243			SortDirection::Asc => value.into().to_be_bytes(),
244			SortDirection::Desc => (!value.into()).to_be_bytes(),
245		};
246
247		unsafe {
248			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 2);
249		}
250	}
251
252	pub fn set_u32(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u32>) {
253		let field = &self.fields[index];
254		debug_assert_eq!(field.value, Type::Uint4);
255		key.set_valid(index, true);
256
257		let bytes = match field.direction {
258			SortDirection::Asc => value.into().to_be_bytes(),
259			SortDirection::Desc => (!value.into()).to_be_bytes(),
260		};
261
262		unsafe {
263			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 4);
264		}
265	}
266
267	pub fn set_u64(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u64>) {
268		let field = &self.fields[index];
269		debug_assert_eq!(field.value, Type::Uint8);
270		key.set_valid(index, true);
271
272		let bytes = match field.direction {
273			SortDirection::Asc => value.into().to_be_bytes(),
274			SortDirection::Desc => (!value.into()).to_be_bytes(),
275		};
276
277		unsafe {
278			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
279		}
280	}
281
282	pub fn set_u128(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u128>) {
283		let field = &self.fields[index];
284		debug_assert_eq!(field.value, Type::Uint16);
285		key.set_valid(index, true);
286
287		let bytes = match field.direction {
288			SortDirection::Asc => value.into().to_be_bytes(),
289			SortDirection::Desc => (!value.into()).to_be_bytes(),
290		};
291
292		unsafe {
293			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 16);
294		}
295	}
296
297	pub fn set_row_number(&self, key: &mut EncodedIndexKey, index: usize, value: impl Into<u64>) {
298		let field = &self.fields[index];
299		debug_assert_eq!(field.value, Type::Uint8);
300		key.set_valid(index, true);
301
302		let bytes = match field.direction {
303			SortDirection::Asc => value.into().to_be_bytes(),
304			SortDirection::Desc => (!value.into()).to_be_bytes(),
305		};
306
307		unsafe {
308			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
309		}
310	}
311
312	pub fn set_date(&self, key: &mut EncodedIndexKey, index: usize, value: Date) {
313		let field = &self.fields[index];
314		debug_assert_eq!(field.value, Type::Date);
315		key.set_valid(index, true);
316
317		let days = value.to_days_since_epoch();
318		let mut bytes = days.to_be_bytes();
319
320		match field.direction {
321			SortDirection::Asc => {
322				bytes[0] ^= 0x80;
323			}
324			SortDirection::Desc => {
325				bytes[0] ^= 0x80;
326				for b in bytes.iter_mut() {
327					*b = !*b;
328				}
329			}
330		}
331
332		unsafe {
333			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 4);
334		}
335	}
336
337	pub fn set_datetime(&self, key: &mut EncodedIndexKey, index: usize, value: DateTime) {
338		let field = &self.fields[index];
339		debug_assert_eq!(field.value, Type::DateTime);
340		key.set_valid(index, true);
341
342		let (seconds, nanos) = value.to_parts();
343		let mut sec_bytes = seconds.to_be_bytes();
344		let mut nano_bytes = nanos.to_be_bytes();
345
346		match field.direction {
347			SortDirection::Asc => {
348				sec_bytes[0] ^= 0x80;
349			}
350			SortDirection::Desc => {
351				sec_bytes[0] ^= 0x80;
352				for b in sec_bytes.iter_mut() {
353					*b = !*b;
354				}
355				for b in nano_bytes.iter_mut() {
356					*b = !*b;
357				}
358			}
359		}
360
361		unsafe {
362			ptr::copy_nonoverlapping(sec_bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
363			ptr::copy_nonoverlapping(
364				nano_bytes.as_ptr(),
365				key.make_mut().as_mut_ptr().add(field.offset + 8),
366				4,
367			);
368		}
369	}
370
371	pub fn set_time(&self, key: &mut EncodedIndexKey, index: usize, value: Time) {
372		let field = &self.fields[index];
373		debug_assert_eq!(field.value, Type::Time);
374		key.set_valid(index, true);
375
376		let nanos = value.to_nanos_since_midnight();
377		let bytes = match field.direction {
378			SortDirection::Asc => nanos.to_be_bytes(),
379			SortDirection::Desc => (!nanos).to_be_bytes(),
380		};
381
382		unsafe {
383			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 8);
384		}
385	}
386
387	pub fn set_duration(&self, key: &mut EncodedIndexKey, index: usize, value: Duration) {
388		let field = &self.fields[index];
389		debug_assert_eq!(field.value, Type::Duration);
390		key.set_valid(index, true);
391
392		let mut months_bytes = value.get_months().to_be_bytes();
393		let mut days_bytes = value.get_days().to_be_bytes();
394		let mut nanos_bytes = value.get_nanos().to_be_bytes();
395
396		match field.direction {
397			SortDirection::Asc => {
398				months_bytes[0] ^= 0x80;
399				days_bytes[0] ^= 0x80;
400				nanos_bytes[0] ^= 0x80;
401			}
402			SortDirection::Desc => {
403				months_bytes[0] ^= 0x80;
404				days_bytes[0] ^= 0x80;
405				nanos_bytes[0] ^= 0x80;
406				for b in months_bytes.iter_mut() {
407					*b = !*b;
408				}
409				for b in days_bytes.iter_mut() {
410					*b = !*b;
411				}
412				for b in nanos_bytes.iter_mut() {
413					*b = !*b;
414				}
415			}
416		}
417
418		unsafe {
419			ptr::copy_nonoverlapping(
420				months_bytes.as_ptr(),
421				key.make_mut().as_mut_ptr().add(field.offset),
422				4,
423			);
424			ptr::copy_nonoverlapping(
425				days_bytes.as_ptr(),
426				key.make_mut().as_mut_ptr().add(field.offset + 4),
427				4,
428			);
429			ptr::copy_nonoverlapping(
430				nanos_bytes.as_ptr(),
431				key.make_mut().as_mut_ptr().add(field.offset + 8),
432				8,
433			);
434		}
435	}
436
437	pub fn set_uuid4(&self, key: &mut EncodedIndexKey, index: usize, value: Uuid4) {
438		let field = &self.fields[index];
439		debug_assert_eq!(field.value, Type::Uuid4);
440		key.set_valid(index, true);
441
442		let uuid: Uuid = value.into();
443		let uuid_bytes = uuid.as_bytes();
444		let mut bytes = [0u8; 16];
445		bytes.copy_from_slice(uuid_bytes);
446
447		if field.direction == SortDirection::Desc {
448			for b in bytes.iter_mut() {
449				*b = !*b;
450			}
451		}
452
453		unsafe {
454			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 16);
455		}
456	}
457
458	pub fn set_uuid7(&self, key: &mut EncodedIndexKey, index: usize, value: Uuid7) {
459		let field = &self.fields[index];
460		debug_assert_eq!(field.value, Type::Uuid7);
461		key.set_valid(index, true);
462
463		let uuid: Uuid = value.into();
464		let uuid_bytes = uuid.as_bytes();
465		let mut bytes = [0u8; 16];
466		bytes.copy_from_slice(uuid_bytes);
467
468		if field.direction == SortDirection::Desc {
469			for b in bytes.iter_mut() {
470				*b = !*b;
471			}
472		}
473
474		unsafe {
475			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 16);
476		}
477	}
478
479	pub fn set_identity_id(&self, key: &mut EncodedIndexKey, index: usize, value: IdentityId) {
480		let field = &self.fields[index];
481		debug_assert_eq!(field.value, Type::IdentityId);
482		key.set_valid(index, true);
483
484		// Direct conversion from inner Uuid7 to Uuid
485		let uuid: Uuid = value.0.into();
486		let uuid_bytes = uuid.as_bytes();
487		let mut bytes = [0u8; 16];
488		bytes.copy_from_slice(uuid_bytes);
489
490		if field.direction == SortDirection::Desc {
491			for b in bytes.iter_mut() {
492				*b = !*b;
493			}
494		}
495
496		unsafe {
497			ptr::copy_nonoverlapping(bytes.as_ptr(), key.make_mut().as_mut_ptr().add(field.offset), 16);
498		}
499	}
500
501	pub fn set_none(&self, key: &mut EncodedIndexKey, index: usize) {
502		let field = &self.fields[index];
503		key.set_valid(index, false);
504
505		let buf = key.make_mut();
506		let start = field.offset;
507		let end = start + field.size;
508		buf[start..end].fill(0);
509	}
510}
511
512#[cfg(test)]
513pub mod tests {
514	use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
515
516	mod bool {
517		use reifydb_type::value::r#type::Type;
518
519		use super::*;
520
521		#[test]
522		fn test_asc() {
523			let layout = EncodedIndexLayout::new(&[Type::Boolean], &[SortDirection::Asc]).unwrap();
524			let mut key_false = layout.allocate_key();
525			let mut key_true = layout.allocate_key();
526
527			layout.set_bool(&mut key_false, 0, false);
528			layout.set_bool(&mut key_true, 0, true);
529
530			// Check bitvec shows field is set
531			assert_eq!(key_false[0] & 0x01, 0x01);
532			assert_eq!(key_true[0] & 0x01, 0x01);
533
534			// Check values at field offset (after bitvec)
535			let offset = layout.fields[0].offset;
536			assert_eq!(key_false[offset], 0);
537			assert_eq!(key_true[offset], 1);
538
539			// Verify ordering
540			assert!(key_false.as_slice() < key_true.as_slice());
541		}
542
543		#[test]
544		fn test_desc() {
545			let layout = EncodedIndexLayout::new(&[Type::Boolean], &[SortDirection::Desc]).unwrap();
546			let mut key_false = layout.allocate_key();
547			let mut key_true = layout.allocate_key();
548
549			layout.set_bool(&mut key_false, 0, false);
550			layout.set_bool(&mut key_true, 0, true);
551
552			// Check values at field offset (inverted for DESC)
553			let offset = layout.fields[0].offset;
554			assert_eq!(key_false[offset], 1); // false becomes 1 in DESC
555			assert_eq!(key_true[offset], 0); // true becomes 0 in DESC
556
557			// Verify ordering (reversed)
558			assert!(key_false.as_slice() > key_true.as_slice());
559		}
560	}
561
562	mod i8 {
563		use reifydb_type::value::r#type::Type;
564
565		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
566
567		#[test]
568		fn test_asc() {
569			let layout = EncodedIndexLayout::new(&[Type::Int1], &[SortDirection::Asc]).unwrap();
570			let mut key_neg = layout.allocate_key();
571			let mut key_zero = layout.allocate_key();
572			let mut key_pos = layout.allocate_key();
573
574			layout.set_i8(&mut key_neg, 0, -128i8);
575			layout.set_i8(&mut key_zero, 0, 0i8);
576			layout.set_i8(&mut key_pos, 0, 127i8);
577
578			let offset = layout.fields[0].offset;
579			// -128 with sign bit flipped: 0x80 -> 0x00
580			assert_eq!(key_neg[offset], 0x00);
581			// 0 with sign bit flipped: 0x00 -> 0x80
582			assert_eq!(key_zero[offset], 0x80);
583			// 127 with sign bit flipped: 0x7F -> 0xFF
584			assert_eq!(key_pos[offset], 0xFF);
585
586			// Verify ordering
587			assert!(key_neg.as_slice() < key_zero.as_slice());
588			assert!(key_zero.as_slice() < key_pos.as_slice());
589		}
590
591		#[test]
592		fn test_desc() {
593			let layout = EncodedIndexLayout::new(&[Type::Int1], &[SortDirection::Desc]).unwrap();
594			let mut key_neg = layout.allocate_key();
595			let mut key_zero = layout.allocate_key();
596			let mut key_pos = layout.allocate_key();
597
598			layout.set_i8(&mut key_neg, 0, -128i8);
599			layout.set_i8(&mut key_zero, 0, 0i8);
600			layout.set_i8(&mut key_pos, 0, 127i8);
601
602			let offset = layout.fields[0].offset;
603			// -128: 0x80 -> flip sign: 0x00 -> invert: 0xFF
604			assert_eq!(key_neg[offset], 0xFF);
605			// 0: 0x00 -> flip sign: 0x80 -> invert: 0x7F
606			assert_eq!(key_zero[offset], 0x7F);
607			// 127: 0x7F -> flip sign: 0xFF -> invert: 0x00
608			assert_eq!(key_pos[offset], 0x00);
609
610			// Verify ordering (reversed)
611			assert!(key_neg.as_slice() > key_zero.as_slice());
612			assert!(key_zero.as_slice() > key_pos.as_slice());
613		}
614	}
615
616	mod i32 {
617		use reifydb_type::value::r#type::Type;
618
619		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
620
621		#[test]
622		fn test_asc() {
623			let layout = EncodedIndexLayout::new(&[Type::Int4], &[SortDirection::Asc]).unwrap();
624			let mut key_neg = layout.allocate_key();
625			let mut key_zero = layout.allocate_key();
626			let mut key_pos = layout.allocate_key();
627
628			layout.set_i32(&mut key_neg, 0, i32::MIN);
629			layout.set_i32(&mut key_zero, 0, 0i32);
630			layout.set_i32(&mut key_pos, 0, i32::MAX);
631
632			let offset = layout.fields[0].offset;
633			// i32::MIN in big-endian with sign bit flipped
634			assert_eq!(&key_neg[offset..offset + 4], &[0x00, 0x00, 0x00, 0x00]);
635			// 0 with sign bit flipped
636			assert_eq!(&key_zero[offset..offset + 4], &[0x80, 0x00, 0x00, 0x00]);
637			// i32::MAX with sign bit flipped
638			assert_eq!(&key_pos[offset..offset + 4], &[0xFF, 0xFF, 0xFF, 0xFF]);
639
640			// Verify ordering
641			assert!(key_neg.as_slice() < key_zero.as_slice());
642			assert!(key_zero.as_slice() < key_pos.as_slice());
643		}
644
645		#[test]
646		fn test_desc() {
647			let layout = EncodedIndexLayout::new(&[Type::Int4], &[SortDirection::Desc]).unwrap();
648			let mut key_neg = layout.allocate_key();
649			let mut key_zero = layout.allocate_key();
650			let mut key_pos = layout.allocate_key();
651
652			layout.set_i32(&mut key_neg, 0, i32::MIN);
653			layout.set_i32(&mut key_zero, 0, 0i32);
654			layout.set_i32(&mut key_pos, 0, i32::MAX);
655
656			let offset = layout.fields[0].offset;
657			// i32::MIN: flip sign then invert all
658			assert_eq!(&key_neg[offset..offset + 4], &[0xFF, 0xFF, 0xFF, 0xFF]);
659			// 0: flip sign then invert all
660			assert_eq!(&key_zero[offset..offset + 4], &[0x7F, 0xFF, 0xFF, 0xFF]);
661			// i32::MAX: flip sign then invert all
662			assert_eq!(&key_pos[offset..offset + 4], &[0x00, 0x00, 0x00, 0x00]);
663
664			// Verify ordering (reversed)
665			assert!(key_neg.as_slice() > key_zero.as_slice());
666			assert!(key_zero.as_slice() > key_pos.as_slice());
667		}
668	}
669
670	mod i64 {
671		use reifydb_type::value::r#type::Type;
672
673		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
674
675		#[test]
676		fn test_asc() {
677			let layout = EncodedIndexLayout::new(&[Type::Int8], &[SortDirection::Asc]).unwrap();
678			let mut key = layout.allocate_key();
679
680			layout.set_i64(&mut key, 0, -1i64);
681
682			let offset = layout.fields[0].offset;
683			// -1 in two's complement is all 1s, with sign bit
684			// flipped becomes 0x7F...
685			assert_eq!(&key[offset..offset + 8], &[0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]);
686		}
687
688		#[test]
689		fn test_desc() {
690			let layout = EncodedIndexLayout::new(&[Type::Int8], &[SortDirection::Desc]).unwrap();
691			let mut key = layout.allocate_key();
692
693			layout.set_i64(&mut key, 0, -1i64);
694
695			let offset = layout.fields[0].offset;
696			// -1: flip sign then invert all
697			assert_eq!(&key[offset..offset + 8], &[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
698		}
699	}
700
701	mod u8 {
702		use reifydb_type::value::r#type::Type;
703
704		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
705
706		#[test]
707		fn test_asc() {
708			let layout = EncodedIndexLayout::new(&[Type::Uint1], &[SortDirection::Asc]).unwrap();
709			let mut key_min = layout.allocate_key();
710			let mut key_mid = layout.allocate_key();
711			let mut key_max = layout.allocate_key();
712
713			layout.set_u8(&mut key_min, 0, 0u8);
714			layout.set_u8(&mut key_mid, 0, 128u8);
715			layout.set_u8(&mut key_max, 0, 255u8);
716
717			let offset = layout.fields[0].offset;
718			assert_eq!(key_min[offset], 0x00);
719			assert_eq!(key_mid[offset], 0x80);
720			assert_eq!(key_max[offset], 0xFF);
721
722			// Verify ordering
723			assert!(key_min.as_slice() < key_mid.as_slice());
724			assert!(key_mid.as_slice() < key_max.as_slice());
725		}
726
727		#[test]
728		fn test_desc() {
729			let layout = EncodedIndexLayout::new(&[Type::Uint1], &[SortDirection::Desc]).unwrap();
730			let mut key_min = layout.allocate_key();
731			let mut key_mid = layout.allocate_key();
732			let mut key_max = layout.allocate_key();
733
734			layout.set_u8(&mut key_min, 0, 0u8);
735			layout.set_u8(&mut key_mid, 0, 128u8);
736			layout.set_u8(&mut key_max, 0, 255u8);
737
738			let offset = layout.fields[0].offset;
739			// Inverted for DESC
740			assert_eq!(key_min[offset], 0xFF);
741			assert_eq!(key_mid[offset], 0x7F);
742			assert_eq!(key_max[offset], 0x00);
743
744			// Verify ordering (reversed)
745			assert!(key_min.as_slice() > key_mid.as_slice());
746			assert!(key_mid.as_slice() > key_max.as_slice());
747		}
748	}
749
750	mod u32 {
751		use reifydb_type::value::r#type::Type;
752
753		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
754
755		#[test]
756		fn test_asc() {
757			let layout = EncodedIndexLayout::new(&[Type::Uint4], &[SortDirection::Asc]).unwrap();
758			let mut key = layout.allocate_key();
759
760			layout.set_u32(&mut key, 0, 0x12345678u32);
761
762			let offset = layout.fields[0].offset;
763			// Big-endian representation
764			assert_eq!(&key[offset..offset + 4], &[0x12, 0x34, 0x56, 0x78]);
765		}
766
767		#[test]
768		fn test_desc() {
769			let layout = EncodedIndexLayout::new(&[Type::Uint4], &[SortDirection::Desc]).unwrap();
770			let mut key = layout.allocate_key();
771
772			layout.set_u32(&mut key, 0, 0x12345678u32);
773
774			let offset = layout.fields[0].offset;
775			// Inverted for DESC
776			assert_eq!(&key[offset..offset + 4], &[0xED, 0xCB, 0xA9, 0x87]);
777		}
778	}
779
780	mod u64 {
781		use reifydb_type::value::r#type::Type;
782
783		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
784
785		#[test]
786		fn test_asc() {
787			let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
788			let mut key = layout.allocate_key();
789
790			layout.set_u64(&mut key, 0, u64::MAX);
791
792			let offset = layout.fields[0].offset;
793			assert_eq!(&key[offset..offset + 8], &[0xFF; 8]);
794		}
795
796		#[test]
797		fn test_desc() {
798			let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Desc]).unwrap();
799			let mut key = layout.allocate_key();
800
801			layout.set_u64(&mut key, 0, u64::MAX);
802
803			let offset = layout.fields[0].offset;
804			assert_eq!(&key[offset..offset + 8], &[0x00; 8]);
805		}
806	}
807
808	mod f32 {
809		use reifydb_type::value::r#type::Type;
810
811		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
812
813		#[test]
814		fn test_asc() {
815			let layout = EncodedIndexLayout::new(&[Type::Float4], &[SortDirection::Asc]).unwrap();
816			let mut key_neg = layout.allocate_key();
817			let mut key_zero = layout.allocate_key();
818			let mut key_pos = layout.allocate_key();
819
820			layout.set_f32(&mut key_neg, 0, -1.0f32);
821			layout.set_f32(&mut key_zero, 0, 0.0f32);
822			layout.set_f32(&mut key_pos, 0, 1.0f32);
823
824			let offset = layout.fields[0].offset;
825
826			// -1.0f32: 0xBF800000 -> invert all: 0x407FFFFF
827			assert_eq!(&key_neg[offset..offset + 4], &[0x40, 0x7F, 0xFF, 0xFF]);
828			// 0.0f32: 0x00000000 -> flip sign: 0x80000000
829			assert_eq!(&key_zero[offset..offset + 4], &[0x80, 0x00, 0x00, 0x00]);
830			// 1.0f32: 0x3F800000 -> flip sign: 0xBF800000
831			assert_eq!(&key_pos[offset..offset + 4], &[0xBF, 0x80, 0x00, 0x00]);
832
833			// Verify ordering
834			assert!(key_neg.as_slice() < key_zero.as_slice());
835			assert!(key_zero.as_slice() < key_pos.as_slice());
836		}
837
838		#[test]
839		fn test_desc() {
840			let layout = EncodedIndexLayout::new(&[Type::Float4], &[SortDirection::Desc]).unwrap();
841			let mut key_neg = layout.allocate_key();
842			let mut key_pos = layout.allocate_key();
843
844			layout.set_f32(&mut key_neg, 0, -1.0f32);
845			layout.set_f32(&mut key_pos, 0, 1.0f32);
846
847			let offset = layout.fields[0].offset;
848
849			// -1.0f32: ASC encoding then invert for DESC
850			assert_eq!(&key_neg[offset..offset + 4], &[0xBF, 0x80, 0x00, 0x00]);
851			// 1.0f32: ASC encoding then invert for DESC
852			assert_eq!(&key_pos[offset..offset + 4], &[0x40, 0x7F, 0xFF, 0xFF]);
853
854			// Verify ordering (reversed)
855			assert!(key_neg.as_slice() > key_pos.as_slice());
856		}
857	}
858
859	mod f64 {
860		use std::f64::consts::PI;
861
862		use reifydb_type::value::r#type::Type;
863
864		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
865
866		#[test]
867		fn test_asc() {
868			let layout = EncodedIndexLayout::new(&[Type::Float8], &[SortDirection::Asc]).unwrap();
869			let mut key = layout.allocate_key();
870
871			layout.set_f64(&mut key, 0, PI);
872
873			let offset = layout.fields[0].offset;
874			// PI in IEEE 754: 0x400921FB54442D18 -> flip sign bit
875			assert_eq!(&key[offset..offset + 8], &[0xC0, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18]);
876		}
877
878		#[test]
879		fn test_desc() {
880			let layout = EncodedIndexLayout::new(&[Type::Float8], &[SortDirection::Desc]).unwrap();
881			let mut key = layout.allocate_key();
882
883			layout.set_f64(&mut key, 0, PI);
884
885			let offset = layout.fields[0].offset;
886			// PI: ASC encoding then invert for DESC
887			assert_eq!(&key[offset..offset + 8], &[0x3F, 0xF6, 0xDE, 0x04, 0xAB, 0xBB, 0xD2, 0xE7]);
888		}
889	}
890
891	mod row_number {
892		use reifydb_type::value::r#type::Type;
893
894		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
895
896		#[test]
897		fn test_asc() {
898			let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Asc]).unwrap();
899			let mut key = layout.allocate_key();
900
901			layout.set_row_number(&mut key, 0, 0x123456789ABCDEFu64);
902
903			let offset = layout.fields[0].offset;
904			assert_eq!(&key[offset..offset + 8], &[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF]);
905		}
906
907		#[test]
908		fn test_desc() {
909			let layout = EncodedIndexLayout::new(&[Type::Uint8], &[SortDirection::Desc]).unwrap();
910			let mut key = layout.allocate_key();
911
912			layout.set_row_number(&mut key, 0, 0x123456789ABCDEFu64);
913
914			let offset = layout.fields[0].offset;
915			// Inverted for DESC
916			assert_eq!(&key[offset..offset + 8], &[0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10]);
917		}
918	}
919
920	mod date {
921		use reifydb_type::value::{date::Date, r#type::Type};
922
923		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
924
925		#[test]
926		fn test_asc() {
927			let layout = EncodedIndexLayout::new(&[Type::Date], &[SortDirection::Asc]).unwrap();
928			let mut key = layout.allocate_key();
929
930			let date = Date::new(2025, 1, 1).unwrap();
931			layout.set_date(&mut key, 0, date);
932
933			let offset = layout.fields[0].offset;
934			// Date is stored as i32 days since epoch with sign bit
935			// flipped
936			let bytes = &key[offset..offset + 4];
937
938			// Verify it's properly encoded
939			let mut expected = date.to_days_since_epoch().to_be_bytes();
940			expected[0] ^= 0x80;
941			assert_eq!(bytes, expected);
942		}
943
944		#[test]
945		fn test_desc() {
946			let layout = EncodedIndexLayout::new(&[Type::Date], &[SortDirection::Desc]).unwrap();
947			let mut key = layout.allocate_key();
948
949			let date = Date::new(2025, 1, 1).unwrap();
950			layout.set_date(&mut key, 0, date);
951
952			let offset = layout.fields[0].offset;
953			let bytes = &key[offset..offset + 4];
954
955			// Date with sign bit flipped then all inverted for DESC
956			let mut expected = date.to_days_since_epoch().to_be_bytes();
957			expected[0] ^= 0x80;
958			for b in expected.iter_mut() {
959				*b = !*b;
960			}
961			assert_eq!(bytes, expected);
962		}
963	}
964
965	mod composite {
966		use reifydb_type::value::r#type::Type;
967
968		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
969
970		#[test]
971		fn test_mixed_directions() {
972			let layout = EncodedIndexLayout::new(
973				&[Type::Int4, Type::Uint8],
974				&[SortDirection::Desc, SortDirection::Asc],
975			)
976			.unwrap();
977
978			let mut key = layout.allocate_key();
979			layout.set_i32(&mut key, 0, 100);
980			layout.set_u64(&mut key, 1, 200u64);
981
982			// Check first field (i32 DESC)
983			let offset1 = layout.fields[0].offset;
984			let mut expected_i32 = 100i32.to_be_bytes();
985			expected_i32[0] ^= 0x80;
986			for b in expected_i32.iter_mut() {
987				*b = !*b;
988			}
989			assert_eq!(&key[offset1..offset1 + 4], expected_i32);
990
991			// Check second field (u64 ASC)
992			let offset2 = layout.fields[1].offset;
993			let expected_u64 = 200u64.to_be_bytes();
994			assert_eq!(&key[offset2..offset2 + 8], expected_u64);
995		}
996	}
997
998	mod uuid4 {
999		use reifydb_type::value::{r#type::Type, uuid::Uuid4};
1000
1001		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
1002
1003		#[test]
1004		fn test_asc() {
1005			let layout = EncodedIndexLayout::new(&[Type::Uuid4], &[SortDirection::Asc]).unwrap();
1006			let mut key1 = layout.allocate_key();
1007			let mut key2 = layout.allocate_key();
1008
1009			let uuid1 = Uuid4::generate();
1010			let uuid2 = Uuid4::generate();
1011
1012			layout.set_uuid4(&mut key1, 0, uuid1.clone());
1013			layout.set_uuid4(&mut key2, 0, uuid2.clone());
1014
1015			// Check bitvec shows field is set
1016			assert!(key1.is_defined(0));
1017			assert!(key2.is_defined(0));
1018
1019			// Check values are stored correctly (16 bytes)
1020			let offset = layout.fields[0].offset;
1021			let uuid1_bytes: Vec<u8> = uuid1.as_bytes().to_vec();
1022			let uuid2_bytes: Vec<u8> = uuid2.as_bytes().to_vec();
1023
1024			assert_eq!(&key1[offset..offset + 16], &uuid1_bytes[..]);
1025			assert_eq!(&key2[offset..offset + 16], &uuid2_bytes[..]);
1026		}
1027
1028		#[test]
1029		fn test_desc() {
1030			let layout = EncodedIndexLayout::new(&[Type::Uuid4], &[SortDirection::Desc]).unwrap();
1031			let mut key = layout.allocate_key();
1032
1033			let uuid = Uuid4::generate();
1034			layout.set_uuid4(&mut key, 0, uuid.clone());
1035
1036			// Check value is inverted for DESC
1037			let offset = layout.fields[0].offset;
1038			let mut expected_bytes = uuid.as_bytes().to_vec();
1039			for b in expected_bytes.iter_mut() {
1040				*b = !*b;
1041			}
1042
1043			assert_eq!(&key[offset..offset + 16], &expected_bytes[..]);
1044		}
1045	}
1046
1047	mod uuid7 {
1048		use std::{thread::sleep, time::Duration};
1049
1050		use reifydb_type::value::{r#type::Type, uuid::Uuid7};
1051
1052		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
1053
1054		#[test]
1055		fn test_asc() {
1056			let layout = EncodedIndexLayout::new(&[Type::Uuid7], &[SortDirection::Asc]).unwrap();
1057			let mut key1 = layout.allocate_key();
1058			let mut key2 = layout.allocate_key();
1059
1060			let uuid1 = Uuid7::generate();
1061			// Sleep a bit to ensure different timestamps
1062			sleep(Duration::from_millis(10));
1063			let uuid2 = Uuid7::generate();
1064
1065			layout.set_uuid7(&mut key1, 0, uuid1.clone());
1066			layout.set_uuid7(&mut key2, 0, uuid2.clone());
1067
1068			// Check bitvec shows field is set
1069			assert!(key1.is_defined(0));
1070			assert!(key2.is_defined(0));
1071
1072			// Check values are stored correctly (16 bytes)
1073			let offset = layout.fields[0].offset;
1074			let uuid1_bytes: Vec<u8> = uuid1.as_bytes().to_vec();
1075			let uuid2_bytes: Vec<u8> = uuid2.as_bytes().to_vec();
1076
1077			assert_eq!(&key1[offset..offset + 16], &uuid1_bytes[..]);
1078			assert_eq!(&key2[offset..offset + 16], &uuid2_bytes[..]);
1079
1080			// UUID7 has timestamp prefix, so later should be
1081			// greater
1082			assert!(key1.as_slice() < key2.as_slice());
1083		}
1084
1085		#[test]
1086		fn test_desc() {
1087			let layout = EncodedIndexLayout::new(&[Type::Uuid7], &[SortDirection::Desc]).unwrap();
1088			let mut key1 = layout.allocate_key();
1089			let mut key2 = layout.allocate_key();
1090
1091			let uuid1 = Uuid7::generate();
1092			// Sleep a bit to ensure different timestamps
1093			sleep(Duration::from_millis(10));
1094			let uuid2 = Uuid7::generate();
1095
1096			layout.set_uuid7(&mut key1, 0, uuid1.clone());
1097			layout.set_uuid7(&mut key2, 0, uuid2.clone());
1098
1099			// Check values are inverted for DESC
1100			let offset = layout.fields[0].offset;
1101			let mut expected_bytes1 = uuid1.as_bytes().to_vec();
1102			let mut expected_bytes2 = uuid2.as_bytes().to_vec();
1103			for b in expected_bytes1.iter_mut() {
1104				*b = !*b;
1105			}
1106			for b in expected_bytes2.iter_mut() {
1107				*b = !*b;
1108			}
1109
1110			assert_eq!(&key1[offset..offset + 16], &expected_bytes1[..]);
1111			assert_eq!(&key2[offset..offset + 16], &expected_bytes2[..]);
1112
1113			// Verify ordering (reversed due to DESC)
1114			assert!(key1.as_slice() > key2.as_slice());
1115		}
1116	}
1117
1118	mod identity_id {
1119		use std::{thread::sleep, time::Duration};
1120
1121		use reifydb_type::value::{identity::IdentityId, r#type::Type, uuid::Uuid7};
1122
1123		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
1124
1125		#[test]
1126		fn test_asc() {
1127			let layout = EncodedIndexLayout::new(&[Type::IdentityId], &[SortDirection::Asc]).unwrap();
1128			let mut key1 = layout.allocate_key();
1129			let mut key2 = layout.allocate_key();
1130
1131			let id1 = IdentityId::generate();
1132			// Sleep a bit to ensure different timestamps
1133			// (IdentityId wraps Uuid7)
1134			sleep(Duration::from_millis(10));
1135			let id2 = IdentityId::generate();
1136
1137			layout.set_identity_id(&mut key1, 0, id1.clone());
1138			layout.set_identity_id(&mut key2, 0, id2.clone());
1139
1140			// Check bitvec shows field is set
1141			assert!(key1.is_defined(0));
1142			assert!(key2.is_defined(0));
1143
1144			// Check values are stored correctly (16 bytes)
1145			let offset = layout.fields[0].offset;
1146			let uuid7_1: Uuid7 = id1.into();
1147			let uuid7_2: Uuid7 = id2.into();
1148			let id1_bytes: Vec<u8> = uuid7_1.as_bytes().to_vec();
1149			let id2_bytes: Vec<u8> = uuid7_2.as_bytes().to_vec();
1150
1151			assert_eq!(&key1[offset..offset + 16], &id1_bytes[..]);
1152			assert_eq!(&key2[offset..offset + 16], &id2_bytes[..]);
1153
1154			// IdentityId wraps Uuid7 which has timestamp prefix, so
1155			// later should be greater
1156			assert!(key1.as_slice() < key2.as_slice());
1157		}
1158
1159		#[test]
1160		fn test_desc() {
1161			let layout = EncodedIndexLayout::new(&[Type::IdentityId], &[SortDirection::Desc]).unwrap();
1162			let mut key1 = layout.allocate_key();
1163			let mut key2 = layout.allocate_key();
1164
1165			let id1 = IdentityId::generate();
1166			// Sleep a bit to ensure different timestamps
1167			sleep(Duration::from_millis(10));
1168			let id2 = IdentityId::generate();
1169
1170			layout.set_identity_id(&mut key1, 0, id1.clone());
1171			layout.set_identity_id(&mut key2, 0, id2.clone());
1172
1173			// Check values are inverted for DESC
1174			let offset = layout.fields[0].offset;
1175			let uuid7_1: Uuid7 = id1.into();
1176			let uuid7_2: Uuid7 = id2.into();
1177			let mut expected_bytes1 = uuid7_1.as_bytes().to_vec();
1178			let mut expected_bytes2 = uuid7_2.as_bytes().to_vec();
1179			for b in expected_bytes1.iter_mut() {
1180				*b = !*b;
1181			}
1182			for b in expected_bytes2.iter_mut() {
1183				*b = !*b;
1184			}
1185
1186			assert_eq!(&key1[offset..offset + 16], &expected_bytes1[..]);
1187			assert_eq!(&key2[offset..offset + 16], &expected_bytes2[..]);
1188
1189			// Verify ordering (reversed due to DESC)
1190			assert!(key1.as_slice() > key2.as_slice());
1191		}
1192	}
1193
1194	mod undefined {
1195		use reifydb_type::value::r#type::Type;
1196
1197		use crate::{sort::SortDirection, value::index::layout::EncodedIndexLayout};
1198
1199		#[test]
1200		fn test_undefined() {
1201			let layout = EncodedIndexLayout::new(&[Type::Int4], &[SortDirection::Asc]).unwrap();
1202			let mut key = layout.allocate_key();
1203
1204			// Set a value first
1205			layout.set_i32(&mut key, 0, 42);
1206			assert!(key.is_defined(0));
1207
1208			// Now set it to undefined
1209			layout.set_none(&mut key, 0);
1210			assert!(!key.is_defined(0));
1211
1212			// Check that the data is zeroed
1213			let offset = layout.fields[0].offset;
1214			assert_eq!(&key[offset..offset + 4], &[0, 0, 0, 0]);
1215		}
1216	}
1217}