Skip to main content

reifydb_core/value/index/
set.rs

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