reifydb_core/value/index/
set.rs

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