Skip to main content

reifydb_core/value/index/
set.rs

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