1use noxu_db::DatabaseEntry;
10
11use crate::entry_binding::EntryBinding;
12use crate::error::Result;
13use crate::tuple::tuple_binding::TupleBinding;
14use crate::tuple::tuple_input::TupleInput;
15use crate::tuple::tuple_output::TupleOutput;
16
17macro_rules! impl_primitive_binding {
22 (
23 $(#[$meta:meta])*
24 $name:ident, $ty:ty,
25 write: $write_method:ident,
26 read: $read_method:ident
27 ) => {
28 $(#[$meta])*
29 #[derive(Debug, Clone, Copy, Default)]
30 pub struct $name;
31
32 impl $name {
33 pub fn new() -> Self {
35 Self
36 }
37 }
38
39 impl EntryBinding<$ty> for $name {
40 fn entry_to_object(&self, entry: &DatabaseEntry) -> Result<$ty> {
41 let mut input = Self::entry_to_input(entry);
42 self.tuple_to_object(&mut input)
43 }
44
45 fn object_to_entry(&self, object: &$ty, entry: &mut DatabaseEntry) -> Result<()> {
46 let mut output = TupleOutput::new();
47 self.object_to_tuple(object, &mut output)?;
48 entry.set_data_vec(output.into_vec());
49 Ok(())
50 }
51 }
52
53 impl TupleBinding<$ty> for $name {
54 fn tuple_to_object(&self, input: &mut TupleInput) -> Result<$ty> {
55 input.$read_method()
56 }
57
58 fn object_to_tuple(&self, object: &$ty, output: &mut TupleOutput) -> Result<()> {
59 output.$write_method(*object);
60 Ok(())
61 }
62 }
63 };
64}
65
66impl_primitive_binding!(
67 BoolBinding, bool,
73 write: write_bool,
74 read: read_bool
75);
76
77impl_primitive_binding!(
78 ByteBinding, u8,
84 write: write_u8,
85 read: read_u8
86);
87
88impl_primitive_binding!(
89 ShortBinding, i16,
95 write: write_i16,
96 read: read_i16
97);
98
99impl_primitive_binding!(
100 IntBinding, i32,
106 write: write_i32,
107 read: read_i32
108);
109
110impl_primitive_binding!(
111 LongBinding, i64,
117 write: write_i64,
118 read: read_i64
119);
120
121impl_primitive_binding!(
122 FloatBinding, f32,
130 write: write_float,
131 read: read_float
132);
133
134impl_primitive_binding!(
135 DoubleBinding, f64,
143 write: write_double,
144 read: read_double
145);
146
147impl_primitive_binding!(
148 SortedFloatBinding, f32,
155 write: write_sorted_float,
156 read: read_sorted_float
157);
158
159impl_primitive_binding!(
160 SortedDoubleBinding, f64,
167 write: write_sorted_double,
168 read: read_sorted_double
169);
170
171impl_primitive_binding!(
172 PackedIntBinding, i32,
179 write: write_packed_int,
180 read: read_packed_int
181);
182
183impl_primitive_binding!(
184 PackedLongBinding, i64,
191 write: write_packed_long,
192 read: read_packed_long
193);
194
195impl_primitive_binding!(
196 SortedPackedIntBinding, i32,
206 write: write_sorted_packed_int,
207 read: read_sorted_packed_int
208);
209
210impl_primitive_binding!(
211 SortedPackedLongBinding, i64,
221 write: write_sorted_packed_long,
222 read: read_sorted_packed_long
223);
224
225impl_primitive_binding!(
226 CharBinding, u16,
238 write: write_char,
239 read: read_char
240);
241
242#[derive(Debug, Clone, Copy, Default)]
252pub struct StringBinding;
253
254impl StringBinding {
255 pub fn new() -> Self {
257 Self
258 }
259}
260
261impl EntryBinding<String> for StringBinding {
262 fn entry_to_object(&self, entry: &DatabaseEntry) -> Result<String> {
263 let mut input = Self::entry_to_input(entry);
264 self.tuple_to_object(&mut input)
265 }
266
267 fn object_to_entry(
268 &self,
269 object: &String,
270 entry: &mut DatabaseEntry,
271 ) -> Result<()> {
272 let mut output = TupleOutput::new();
273 self.object_to_tuple(object, &mut output)?;
274 entry.set_data_vec(output.into_vec());
275 Ok(())
276 }
277}
278
279impl TupleBinding<String> for StringBinding {
280 fn tuple_to_object(&self, input: &mut TupleInput) -> Result<String> {
281 input.read_string()
282 }
283
284 fn object_to_tuple(
285 &self,
286 object: &String,
287 output: &mut TupleOutput,
288 ) -> Result<()> {
289 output.write_string(object);
290 Ok(())
291 }
292}
293
294#[cfg(test)]
295mod tests {
296 use super::*;
297
298 #[test]
303 fn test_bool_binding_round_trip() {
304 let binding = BoolBinding::new();
305 for val in [true, false] {
306 let mut entry = DatabaseEntry::new();
307 binding.object_to_entry(&val, &mut entry).unwrap();
308 let result = binding.entry_to_object(&entry).unwrap();
309 assert_eq!(val, result);
310 }
311 }
312
313 #[test]
314 fn test_byte_binding_round_trip() {
315 let binding = ByteBinding::new();
316 for val in [0u8, 1, 127, 128, 255] {
317 let mut entry = DatabaseEntry::new();
318 binding.object_to_entry(&val, &mut entry).unwrap();
319 let result = binding.entry_to_object(&entry).unwrap();
320 assert_eq!(val, result);
321 }
322 }
323
324 #[test]
325 fn test_short_binding_round_trip() {
326 let binding = ShortBinding::new();
327 for val in [i16::MIN, -1, 0, 1, i16::MAX] {
328 let mut entry = DatabaseEntry::new();
329 binding.object_to_entry(&val, &mut entry).unwrap();
330 let result = binding.entry_to_object(&entry).unwrap();
331 assert_eq!(val, result);
332 }
333 }
334
335 #[test]
336 fn test_int_binding_round_trip() {
337 let binding = IntBinding::new();
338 for val in [i32::MIN, -1, 0, 1, i32::MAX] {
339 let mut entry = DatabaseEntry::new();
340 binding.object_to_entry(&val, &mut entry).unwrap();
341 let result = binding.entry_to_object(&entry).unwrap();
342 assert_eq!(val, result);
343 }
344 }
345
346 #[test]
347 fn test_long_binding_round_trip() {
348 let binding = LongBinding::new();
349 for val in [i64::MIN, -1, 0, 1, i64::MAX] {
350 let mut entry = DatabaseEntry::new();
351 binding.object_to_entry(&val, &mut entry).unwrap();
352 let result = binding.entry_to_object(&entry).unwrap();
353 assert_eq!(val, result);
354 }
355 }
356
357 #[test]
358 fn test_float_binding_round_trip() {
359 let binding = FloatBinding::new();
360 for val in [-1.5f32, 0.0, 1.5, f32::MAX, f32::MIN] {
361 let mut entry = DatabaseEntry::new();
362 binding.object_to_entry(&val, &mut entry).unwrap();
363 let result = binding.entry_to_object(&entry).unwrap();
364 assert_eq!(val, result);
365 }
366 }
367
368 #[test]
369 fn test_double_binding_round_trip() {
370 let binding = DoubleBinding::new();
371 for val in [-1.5f64, 0.0, 1.5, f64::MAX, f64::MIN] {
372 let mut entry = DatabaseEntry::new();
373 binding.object_to_entry(&val, &mut entry).unwrap();
374 let result = binding.entry_to_object(&entry).unwrap();
375 assert_eq!(val, result);
376 }
377 }
378
379 #[test]
380 fn test_sorted_float_binding_round_trip() {
381 let binding = SortedFloatBinding::new();
382 for val in [-1.5f32, -0.0, 0.0, 1.5, f32::MAX, f32::MIN] {
383 let mut entry = DatabaseEntry::new();
384 binding.object_to_entry(&val, &mut entry).unwrap();
385 let result = binding.entry_to_object(&entry).unwrap();
386 assert_eq!(val.to_bits(), result.to_bits(), "failed for {}", val);
388 }
389 }
390
391 #[test]
392 fn test_sorted_double_binding_round_trip() {
393 let binding = SortedDoubleBinding::new();
394 for val in [-1.5f64, -0.0, 0.0, 1.5, f64::MAX, f64::MIN] {
395 let mut entry = DatabaseEntry::new();
396 binding.object_to_entry(&val, &mut entry).unwrap();
397 let result = binding.entry_to_object(&entry).unwrap();
398 assert_eq!(val.to_bits(), result.to_bits(), "failed for {}", val);
399 }
400 }
401
402 #[test]
403 fn test_packed_int_binding_round_trip() {
404 let binding = PackedIntBinding::new();
405 for val in [i32::MIN, -120, -119, -1, 0, 1, 119, 120, i32::MAX] {
406 let mut entry = DatabaseEntry::new();
407 binding.object_to_entry(&val, &mut entry).unwrap();
408 let result = binding.entry_to_object(&entry).unwrap();
409 assert_eq!(val, result, "failed for {}", val);
410 }
411 }
412
413 #[test]
414 fn test_packed_long_binding_round_trip() {
415 let binding = PackedLongBinding::new();
416 for val in [i64::MIN, -120, -119, -1, 0, 1, 119, 120, i64::MAX] {
417 let mut entry = DatabaseEntry::new();
418 binding.object_to_entry(&val, &mut entry).unwrap();
419 let result = binding.entry_to_object(&entry).unwrap();
420 assert_eq!(val, result, "failed for {}", val);
421 }
422 }
423
424 #[test]
425 fn test_string_binding_round_trip() {
426 let binding = StringBinding::new();
427 for val in ["", "hello", "world", "unicode: \u{1F600}"] {
428 let s = val.to_string();
429 let mut entry = DatabaseEntry::new();
430 binding.object_to_entry(&s, &mut entry).unwrap();
431 let result = binding.entry_to_object(&entry).unwrap();
432 assert_eq!(s, result);
433 }
434 }
435
436 #[test]
437 fn test_string_binding_embedded_null() {
438 let binding = StringBinding::new();
439 let s = "hello\x00world".to_string();
441 let mut entry = DatabaseEntry::new();
442 binding.object_to_entry(&s, &mut entry).unwrap();
443 let result = binding.entry_to_object(&entry).unwrap();
444 assert_eq!(s, result);
445 }
446
447 #[test]
448 fn test_string_binding_multiple_embedded_nulls() {
449 let binding = StringBinding::new();
450 let s = "\x00\x00\x00".to_string();
451 let mut entry = DatabaseEntry::new();
452 binding.object_to_entry(&s, &mut entry).unwrap();
453 let result = binding.entry_to_object(&entry).unwrap();
454 assert_eq!(s, result);
455 }
456
457 #[test]
458 fn test_string_binding_null_at_start_and_end() {
459 let binding = StringBinding::new();
460 let s = "\x00hello\x00".to_string();
461 let mut entry = DatabaseEntry::new();
462 binding.object_to_entry(&s, &mut entry).unwrap();
463 let result = binding.entry_to_object(&entry).unwrap();
464 assert_eq!(s, result);
465 }
466
467 #[test]
468 fn test_string_binding_null_escape_encoded_correctly() {
469 let binding = StringBinding::new();
471 let s = "a\x00b".to_string();
472 let mut entry = DatabaseEntry::new();
473 binding.object_to_entry(&s, &mut entry).unwrap();
474 let raw = entry.data();
475 assert_eq!(raw, &[b'a', 0x00, 0x01, b'b', 0x00, 0x00]);
477 }
478
479 #[test]
480 fn test_string_binding_terminator_encoded_correctly() {
481 let binding = StringBinding::new();
483 let s = String::new();
484 let mut entry = DatabaseEntry::new();
485 binding.object_to_entry(&s, &mut entry).unwrap();
486 let raw = entry.data();
487 assert_eq!(raw, &[0x00, 0x00]);
488 }
489
490 #[test]
491 fn test_string_binding_two_strings_in_tuple() {
492 use crate::tuple::tuple_input::TupleInput;
494 use crate::tuple::tuple_output::TupleOutput;
495 let mut out = TupleOutput::new();
496 out.write_string("foo\x00bar");
497 out.write_string("baz");
498 let mut inp = TupleInput::new(&out.to_vec());
499 assert_eq!(inp.read_string().unwrap(), "foo\x00bar");
500 assert_eq!(inp.read_string().unwrap(), "baz");
501 }
502
503 fn encoded_bytes<T>(binding: &impl EntryBinding<T>, val: &T) -> Vec<u8> {
508 let mut entry = DatabaseEntry::new();
509 binding.object_to_entry(val, &mut entry).unwrap();
510 entry.data().to_vec()
511 }
512
513 #[test]
514 fn test_short_binding_sort_order() {
515 let binding = ShortBinding::new();
516 let values: Vec<i16> = vec![i16::MIN, -100, -1, 0, 1, 100, i16::MAX];
517 let encoded: Vec<Vec<u8>> =
518 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
519 for i in 0..encoded.len() - 1 {
520 assert!(
521 encoded[i] < encoded[i + 1],
522 "{} should sort before {}",
523 values[i],
524 values[i + 1]
525 );
526 }
527 }
528
529 #[test]
530 fn test_int_binding_sort_order() {
531 let binding = IntBinding::new();
532 let values: Vec<i32> = vec![i32::MIN, -100, -1, 0, 1, 100, i32::MAX];
533 let encoded: Vec<Vec<u8>> =
534 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
535 for i in 0..encoded.len() - 1 {
536 assert!(
537 encoded[i] < encoded[i + 1],
538 "{} should sort before {}",
539 values[i],
540 values[i + 1]
541 );
542 }
543 }
544
545 #[test]
546 fn test_long_binding_sort_order() {
547 let binding = LongBinding::new();
548 let values: Vec<i64> = vec![i64::MIN, -100, -1, 0, 1, 100, i64::MAX];
549 let encoded: Vec<Vec<u8>> =
550 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
551 for i in 0..encoded.len() - 1 {
552 assert!(
553 encoded[i] < encoded[i + 1],
554 "{} should sort before {}",
555 values[i],
556 values[i + 1]
557 );
558 }
559 }
560
561 #[test]
562 fn test_sorted_float_binding_sort_order() {
563 let binding = SortedFloatBinding::new();
564 let values: Vec<f32> = vec![
565 f32::NEG_INFINITY,
566 f32::MIN,
567 -100.0,
568 -1.0,
569 -f32::MIN_POSITIVE,
570 0.0,
571 f32::MIN_POSITIVE,
572 1.0,
573 100.0,
574 f32::MAX,
575 f32::INFINITY,
576 ];
577 let encoded: Vec<Vec<u8>> =
578 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
579 for i in 0..encoded.len() - 1 {
580 assert!(
581 encoded[i] < encoded[i + 1],
582 "{} (encoded {:?}) should sort before {} (encoded {:?})",
583 values[i],
584 encoded[i],
585 values[i + 1],
586 encoded[i + 1]
587 );
588 }
589 }
590
591 #[test]
592 fn test_sorted_double_binding_sort_order() {
593 let binding = SortedDoubleBinding::new();
594 let values: Vec<f64> = vec![
595 f64::NEG_INFINITY,
596 f64::MIN,
597 -100.0,
598 -1.0,
599 -f64::MIN_POSITIVE,
600 0.0,
601 f64::MIN_POSITIVE,
602 1.0,
603 100.0,
604 f64::MAX,
605 f64::INFINITY,
606 ];
607 let encoded: Vec<Vec<u8>> =
608 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
609 for i in 0..encoded.len() - 1 {
610 assert!(
611 encoded[i] < encoded[i + 1],
612 "{} should sort before {}",
613 values[i],
614 values[i + 1]
615 );
616 }
617 }
618
619 #[test]
620 fn test_string_binding_sort_order() {
621 let binding = StringBinding::new();
622 let values: Vec<String> = vec![
623 "".to_string(),
624 "a".to_string(),
625 "ab".to_string(),
626 "b".to_string(),
627 "z".to_string(),
628 ];
629 let encoded: Vec<Vec<u8>> =
630 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
631 for i in 0..encoded.len() - 1 {
632 assert!(
633 encoded[i] < encoded[i + 1],
634 "{:?} should sort before {:?}",
635 values[i],
636 values[i + 1]
637 );
638 }
639 }
640
641 #[test]
646 fn test_packed_int_boundary_values() {
647 let binding = PackedIntBinding::new();
648 for val in [-120, -119, 119, 120, 256, -257, 65536, -65537] {
650 let mut entry = DatabaseEntry::new();
651 binding.object_to_entry(&val, &mut entry).unwrap();
652 let result = binding.entry_to_object(&entry).unwrap();
653 assert_eq!(val, result, "boundary test failed for {}", val);
654 }
655 }
656
657 #[test]
658 fn test_packed_long_boundary_values() {
659 let binding = PackedLongBinding::new();
660 for val in [-120i64, -119, 119, 120, 256, -257, 1 << 32, -(1 << 32)] {
661 let mut entry = DatabaseEntry::new();
662 binding.object_to_entry(&val, &mut entry).unwrap();
663 let result = binding.entry_to_object(&entry).unwrap();
664 assert_eq!(val, result, "boundary test failed for {}", val);
665 }
666 }
667
668 #[test]
669 fn test_sorted_float_nan() {
670 let binding = SortedFloatBinding::new();
672 let val = f32::NAN;
673 let mut entry = DatabaseEntry::new();
674 binding.object_to_entry(&val, &mut entry).unwrap();
675 let result = binding.entry_to_object(&entry).unwrap();
676 assert!(result.is_nan());
677 }
678
679 #[test]
680 fn test_sorted_double_nan() {
681 let binding = SortedDoubleBinding::new();
682 let val = f64::NAN;
683 let mut entry = DatabaseEntry::new();
684 binding.object_to_entry(&val, &mut entry).unwrap();
685 let result = binding.entry_to_object(&entry).unwrap();
686 assert!(result.is_nan());
687 }
688
689 #[test]
690 fn test_sorted_float_negative_zero() {
691 let binding = SortedFloatBinding::new();
692 let val = -0.0f32;
693 let mut entry = DatabaseEntry::new();
694 binding.object_to_entry(&val, &mut entry).unwrap();
695 let result = binding.entry_to_object(&entry).unwrap();
696 assert_eq!(val.to_bits(), result.to_bits());
698 }
699
700 #[test]
701 fn test_sorted_double_negative_zero() {
702 let binding = SortedDoubleBinding::new();
703 let val = -0.0f64;
704 let mut entry = DatabaseEntry::new();
705 binding.object_to_entry(&val, &mut entry).unwrap();
706 let result = binding.entry_to_object(&entry).unwrap();
707 assert_eq!(val.to_bits(), result.to_bits());
708 }
709
710 #[test]
711 fn test_int_binding_encoded_size() {
712 let binding = IntBinding::new();
713 let mut entry = DatabaseEntry::new();
714 binding.object_to_entry(&42i32, &mut entry).unwrap();
715 assert_eq!(entry.data().len(), 4);
716 }
717
718 #[test]
719 fn test_long_binding_encoded_size() {
720 let binding = LongBinding::new();
721 let mut entry = DatabaseEntry::new();
722 binding.object_to_entry(&42i64, &mut entry).unwrap();
723 assert_eq!(entry.data().len(), 8);
724 }
725
726 #[test]
727 fn test_packed_int_compact_size() {
728 let binding = PackedIntBinding::new();
729 let mut entry = DatabaseEntry::new();
731 binding.object_to_entry(&0i32, &mut entry).unwrap();
732 assert_eq!(entry.data().len(), 1);
733
734 binding.object_to_entry(&119i32, &mut entry).unwrap();
735 assert_eq!(entry.data().len(), 1);
736
737 binding.object_to_entry(&(-119i32), &mut entry).unwrap();
738 assert_eq!(entry.data().len(), 1);
739
740 binding.object_to_entry(&120i32, &mut entry).unwrap();
742 assert!(entry.data().len() > 1);
743 }
744
745 #[test]
750 fn test_sorted_packed_int_binding_round_trip() {
751 let binding = SortedPackedIntBinding::new();
752 for val in [i32::MIN, -120, -119, -1, 0, 1, 119, 120, 121, i32::MAX] {
753 let mut entry = DatabaseEntry::new();
754 binding.object_to_entry(&val, &mut entry).unwrap();
755 let result = binding.entry_to_object(&entry).unwrap();
756 assert_eq!(val, result, "round-trip failed for {}", val);
757 }
758 }
759
760 #[test]
761 fn test_sorted_packed_int_binding_sort_order() {
762 let binding = SortedPackedIntBinding::new();
763 let values: Vec<i32> = vec![
764 i32::MIN,
765 -1_000_000,
766 -120,
767 -119,
768 -1,
769 0,
770 1,
771 119,
772 120,
773 121,
774 1_000_000,
775 i32::MAX,
776 ];
777 let encoded: Vec<Vec<u8>> =
778 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
779 for i in 0..encoded.len() - 1 {
780 assert!(
781 encoded[i] < encoded[i + 1],
782 "sort order violated: {} (encoded {:?}) should sort before {} (encoded {:?})",
783 values[i],
784 encoded[i],
785 values[i + 1],
786 encoded[i + 1]
787 );
788 }
789 }
790
791 #[test]
792 fn test_sorted_packed_int_single_byte_range() {
793 let binding = SortedPackedIntBinding::new();
795 for val in (-119..=120i32).step_by(1) {
796 let mut entry = DatabaseEntry::new();
797 binding.object_to_entry(&val, &mut entry).unwrap();
798 assert_eq!(
799 entry.data().len(),
800 1,
801 "value {} should encode in 1 byte",
802 val
803 );
804 }
805 }
806
807 #[test]
808 fn test_sorted_packed_int_multi_byte() {
809 let binding = SortedPackedIntBinding::new();
810 for val in [121i32, -120, i32::MAX, i32::MIN] {
811 let mut entry = DatabaseEntry::new();
812 binding.object_to_entry(&val, &mut entry).unwrap();
813 assert!(
814 entry.data().len() > 1,
815 "value {} should encode in more than 1 byte",
816 val
817 );
818 }
819 }
820
821 #[test]
826 fn test_sorted_packed_long_binding_round_trip() {
827 let binding = SortedPackedLongBinding::new();
828 for val in [
829 i64::MIN,
830 -1_000_000_000_000i64,
831 -120,
832 -119,
833 -1,
834 0,
835 1,
836 119,
837 120,
838 121,
839 1_000_000_000_000i64,
840 i64::MAX,
841 ] {
842 let mut entry = DatabaseEntry::new();
843 binding.object_to_entry(&val, &mut entry).unwrap();
844 let result = binding.entry_to_object(&entry).unwrap();
845 assert_eq!(val, result, "round-trip failed for {}", val);
846 }
847 }
848
849 #[test]
850 fn test_sorted_packed_long_binding_sort_order() {
851 let binding = SortedPackedLongBinding::new();
852 let values: Vec<i64> = vec![
853 i64::MIN,
854 -1_000_000_000_000,
855 -120,
856 -119,
857 -1,
858 0,
859 1,
860 119,
861 120,
862 121,
863 1_000_000_000_000,
864 i64::MAX,
865 ];
866 let encoded: Vec<Vec<u8>> =
867 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
868 for i in 0..encoded.len() - 1 {
869 assert!(
870 encoded[i] < encoded[i + 1],
871 "sort order violated: {} (encoded {:?}) should sort before {} (encoded {:?})",
872 values[i],
873 encoded[i],
874 values[i + 1],
875 encoded[i + 1]
876 );
877 }
878 }
879
880 #[test]
881 fn test_sorted_packed_long_single_byte_range() {
882 let binding = SortedPackedLongBinding::new();
884 for val in (-119..=120i64).step_by(1) {
885 let mut entry = DatabaseEntry::new();
886 binding.object_to_entry(&val, &mut entry).unwrap();
887 assert_eq!(
888 entry.data().len(),
889 1,
890 "value {} should encode in 1 byte",
891 val
892 );
893 }
894 }
895
896 #[test]
897 fn test_sorted_packed_long_multi_byte() {
898 let binding = SortedPackedLongBinding::new();
899 for val in [121i64, -120, i64::MAX, i64::MIN] {
900 let mut entry = DatabaseEntry::new();
901 binding.object_to_entry(&val, &mut entry).unwrap();
902 assert!(
903 entry.data().len() > 1,
904 "value {} should encode in more than 1 byte",
905 val
906 );
907 }
908 }
909
910 #[test]
915 fn test_char_binding_round_trip() {
916 let binding = CharBinding::new();
917 for val in
918 [0u16, 1, 'A' as u16, 'a' as u16, 0x00FF, 0x0100, 0xD800, 0xFFFF]
919 {
920 let mut entry = DatabaseEntry::new();
921 binding.object_to_entry(&val, &mut entry).unwrap();
922 let result = binding.entry_to_object(&entry).unwrap();
923 assert_eq!(val, result, "round-trip failed for U+{:04X}", val);
924 }
925 }
926
927 #[test]
928 fn test_char_binding_encoded_size() {
929 let binding = CharBinding::new();
930 let mut entry = DatabaseEntry::new();
931 binding.object_to_entry(&(b'A' as u16), &mut entry).unwrap();
932 assert_eq!(
933 entry.data().len(),
934 2,
935 "char should always encode to 2 bytes"
936 );
937 }
938
939 #[test]
940 fn test_char_binding_big_endian_encoding() {
941 let binding = CharBinding::new();
943 let val = b'A' as u16; let mut entry = DatabaseEntry::new();
945 binding.object_to_entry(&val, &mut entry).unwrap();
946 assert_eq!(
947 entry.data(),
948 &[0x00, 0x41],
949 "char 'A' (U+0041) should encode as [0x00, 0x41]"
950 );
951 }
952
953 #[test]
954 fn test_char_binding_high_codepoint_encoding() {
955 let binding = CharBinding::new();
957 let val: u16 = 0xFF41;
958 let mut entry = DatabaseEntry::new();
959 binding.object_to_entry(&val, &mut entry).unwrap();
960 assert_eq!(
961 entry.data(),
962 &[0xFF, 0x41],
963 "U+FF41 should encode as [0xFF, 0x41]"
964 );
965 }
966
967 #[test]
968 fn test_char_binding_sort_order() {
969 let binding = CharBinding::new();
971 let values: Vec<u16> = vec![
972 0x0000, 0x0041, 0x007F, 0x0080, 0x00FF, 0x0100, 0xD800, 0xFFFF,
973 ];
974 let encoded: Vec<Vec<u8>> =
975 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
976 for i in 0..encoded.len() - 1 {
977 assert!(
978 encoded[i] < encoded[i + 1],
979 "sort order violated: U+{:04X} should sort before U+{:04X}",
980 values[i],
981 values[i + 1]
982 );
983 }
984 }
985
986 #[test]
987 fn test_sorted_packed_int_sort_order_vs_fixed_int() {
988 let spb = SortedPackedIntBinding::new();
990 let ib = IntBinding::new();
991 let values: Vec<i32> = vec![-1000, -1, 0, 1, 1000];
992 let sp_encoded: Vec<Vec<u8>> =
994 values.iter().map(|v| encoded_bytes(&spb, v)).collect();
995 let i_encoded: Vec<Vec<u8>> =
996 values.iter().map(|v| encoded_bytes(&ib, v)).collect();
997 for i in 0..sp_encoded.len() - 1 {
998 assert!(
999 sp_encoded[i] < sp_encoded[i + 1],
1000 "SortedPackedIntBinding sort order violated for {} < {}",
1001 values[i],
1002 values[i + 1]
1003 );
1004 assert!(
1005 i_encoded[i] < i_encoded[i + 1],
1006 "IntBinding sort order violated for {} < {}",
1007 values[i],
1008 values[i + 1]
1009 );
1010 }
1011 }
1012
1013 #[test]
1014 fn test_i8_sort_order() {
1015 let values: Vec<i8> = vec![-128, -1, 0, 1, 127];
1016 let encoded: Vec<Vec<u8>> = values
1017 .iter()
1018 .map(|&v| {
1019 let mut out = TupleOutput::new();
1020 out.write_i8(v);
1021 out.to_vec()
1022 })
1023 .collect();
1024 for i in 0..encoded.len() - 1 {
1025 assert!(
1026 encoded[i] < encoded[i + 1],
1027 "i8 sort order: {} should be < {}",
1028 values[i],
1029 values[i + 1]
1030 );
1031 }
1032 }
1033
1034 #[test]
1040 fn test_bool_binding_encoded_size() {
1041 let binding = BoolBinding::new();
1042 for val in [true, false] {
1043 let mut entry = DatabaseEntry::new();
1044 binding.object_to_entry(&val, &mut entry).unwrap();
1045 assert_eq!(
1046 entry.data().len(),
1047 1,
1048 "bool {} should encode to 1 byte",
1049 val
1050 );
1051 }
1052 }
1053
1054 #[test]
1056 fn test_byte_binding_encoded_size() {
1057 let binding = ByteBinding::new();
1058 for val in [0u8, 1, 123, 255] {
1059 let mut entry = DatabaseEntry::new();
1060 binding.object_to_entry(&val, &mut entry).unwrap();
1061 assert_eq!(
1062 entry.data().len(),
1063 1,
1064 "u8 {} should encode to 1 byte",
1065 val
1066 );
1067 }
1068 }
1069
1070 #[test]
1072 fn test_short_binding_encoded_size() {
1073 let binding = ShortBinding::new();
1074 for val in [i16::MIN, -1i16, 0, 1, 123, i16::MAX] {
1075 let mut entry = DatabaseEntry::new();
1076 binding.object_to_entry(&val, &mut entry).unwrap();
1077 assert_eq!(
1078 entry.data().len(),
1079 2,
1080 "i16 {} should encode to 2 bytes",
1081 val
1082 );
1083 }
1084 }
1085
1086 #[test]
1088 fn test_float_binding_encoded_size() {
1089 let binding = FloatBinding::new();
1090 for val in [0.0f32, 1.0, -1.0, 123.123, f32::MAX, f32::MIN, f32::NAN] {
1091 let mut entry = DatabaseEntry::new();
1092 binding.object_to_entry(&val, &mut entry).unwrap();
1093 assert_eq!(
1094 entry.data().len(),
1095 4,
1096 "f32 {} should encode to 4 bytes",
1097 val
1098 );
1099 }
1100 }
1101
1102 #[test]
1104 fn test_double_binding_encoded_size() {
1105 let binding = DoubleBinding::new();
1106 for val in [0.0f64, 1.0, -1.0, 123.123, f64::MAX, f64::MIN, f64::NAN] {
1107 let mut entry = DatabaseEntry::new();
1108 binding.object_to_entry(&val, &mut entry).unwrap();
1109 assert_eq!(
1110 entry.data().len(),
1111 8,
1112 "f64 {} should encode to 8 bytes",
1113 val
1114 );
1115 }
1116 }
1117
1118 #[test]
1120 fn test_sorted_float_binding_encoded_size() {
1121 let binding = SortedFloatBinding::new();
1122 for val in
1123 [0.0f32, 1.0, -1.0, 123.123, f32::MAX, f32::NEG_INFINITY, f32::NAN]
1124 {
1125 let mut entry = DatabaseEntry::new();
1126 binding.object_to_entry(&val, &mut entry).unwrap();
1127 assert_eq!(
1128 entry.data().len(),
1129 4,
1130 "sorted_f32 {} should encode to 4 bytes",
1131 val
1132 );
1133 }
1134 }
1135
1136 #[test]
1138 fn test_sorted_double_binding_encoded_size() {
1139 let binding = SortedDoubleBinding::new();
1140 for val in
1141 [0.0f64, 1.0, -1.0, 123.123, f64::MAX, f64::NEG_INFINITY, f64::NAN]
1142 {
1143 let mut entry = DatabaseEntry::new();
1144 binding.object_to_entry(&val, &mut entry).unwrap();
1145 assert_eq!(
1146 entry.data().len(),
1147 8,
1148 "sorted_f64 {} should encode to 8 bytes",
1149 val
1150 );
1151 }
1152 }
1153
1154 #[test]
1156 fn test_char_binding_encoded_size_variants() {
1157 let binding = CharBinding::new();
1158 for val in [0u16, b'a' as u16, 0x7F, 0x00FF, 0x0100, 0xFFFF] {
1159 let mut entry = DatabaseEntry::new();
1160 binding.object_to_entry(&val, &mut entry).unwrap();
1161 assert_eq!(
1162 entry.data().len(),
1163 2,
1164 "char U+{:04X} should encode to 2 bytes",
1165 val
1166 );
1167 }
1168 }
1169
1170 #[test]
1172 fn test_string_binding_abc_size() {
1173 let binding = StringBinding::new();
1174 let mut entry = DatabaseEntry::new();
1175 binding.object_to_entry(&"abc".to_string(), &mut entry).unwrap();
1176 assert_eq!(entry.data().len(), 5);
1178 }
1179
1180 #[test]
1182 fn test_string_binding_empty_size() {
1183 let binding = StringBinding::new();
1184 let mut entry = DatabaseEntry::new();
1185 binding.object_to_entry(&String::new(), &mut entry).unwrap();
1186 assert_eq!(entry.data().len(), 2);
1188 }
1189
1190 #[test]
1193 fn test_nested_binding_coverage_int() {
1194 use crate::tuple::tuple_binding::TupleBinding;
1195 let binding = IntBinding::new();
1196 let mut out = TupleOutput::new();
1197 out.write_string("abc");
1198 binding.object_to_tuple(&123i32, &mut out).unwrap();
1199 out.write_string("xyz");
1200
1201 let mut inp = TupleInput::new(&out.to_vec());
1202 assert_eq!(inp.read_string().unwrap(), "abc");
1203 let val: i32 = binding.tuple_to_object(&mut inp).unwrap();
1204 assert_eq!(val, 123);
1205 assert_eq!(inp.read_string().unwrap(), "xyz");
1206 assert_eq!(inp.available(), 0);
1207 }
1208
1209 #[test]
1211 fn test_nested_binding_coverage_long() {
1212 use crate::tuple::tuple_binding::TupleBinding;
1213 let binding = LongBinding::new();
1214 let mut out = TupleOutput::new();
1215 out.write_string("abc");
1216 binding.object_to_tuple(&123i64, &mut out).unwrap();
1217 out.write_string("xyz");
1218
1219 let mut inp = TupleInput::new(&out.to_vec());
1220 assert_eq!(inp.read_string().unwrap(), "abc");
1221 let val: i64 = binding.tuple_to_object(&mut inp).unwrap();
1222 assert_eq!(val, 123);
1223 assert_eq!(inp.read_string().unwrap(), "xyz");
1224 assert_eq!(inp.available(), 0);
1225 }
1226
1227 #[test]
1229 fn test_nested_binding_coverage_bool() {
1230 use crate::tuple::tuple_binding::TupleBinding;
1231 let binding = BoolBinding::new();
1232 let mut out = TupleOutput::new();
1233 out.write_string("abc");
1234 binding.object_to_tuple(&true, &mut out).unwrap();
1235 out.write_string("xyz");
1236
1237 let mut inp = TupleInput::new(&out.to_vec());
1238 assert_eq!(inp.read_string().unwrap(), "abc");
1239 let val: bool = binding.tuple_to_object(&mut inp).unwrap();
1240 assert!(val);
1241 assert_eq!(inp.read_string().unwrap(), "xyz");
1242 assert_eq!(inp.available(), 0);
1243 }
1244
1245 #[test]
1247 fn test_nested_binding_coverage_sorted_float() {
1248 use crate::tuple::tuple_binding::TupleBinding;
1249 let binding = SortedFloatBinding::new();
1250 let val = 123.123f32;
1251 let mut out = TupleOutput::new();
1252 out.write_string("abc");
1253 binding.object_to_tuple(&val, &mut out).unwrap();
1254 out.write_string("xyz");
1255
1256 let mut inp = TupleInput::new(&out.to_vec());
1257 assert_eq!(inp.read_string().unwrap(), "abc");
1258 let got: f32 = binding.tuple_to_object(&mut inp).unwrap();
1259 assert_eq!(got.to_bits(), val.to_bits());
1260 assert_eq!(inp.read_string().unwrap(), "xyz");
1261 assert_eq!(inp.available(), 0);
1262 }
1263
1264 #[test]
1266 fn test_nested_binding_coverage_sorted_double() {
1267 use crate::tuple::tuple_binding::TupleBinding;
1268 let binding = SortedDoubleBinding::new();
1269 let val = 123.123f64;
1270 let mut out = TupleOutput::new();
1271 out.write_string("abc");
1272 binding.object_to_tuple(&val, &mut out).unwrap();
1273 out.write_string("xyz");
1274
1275 let mut inp = TupleInput::new(&out.to_vec());
1276 assert_eq!(inp.read_string().unwrap(), "abc");
1277 let got: f64 = binding.tuple_to_object(&mut inp).unwrap();
1278 assert_eq!(got.to_bits(), val.to_bits());
1279 assert_eq!(inp.read_string().unwrap(), "xyz");
1280 assert_eq!(inp.available(), 0);
1281 }
1282
1283 #[test]
1285 fn test_nested_binding_coverage_packed_int() {
1286 use crate::tuple::tuple_binding::TupleBinding;
1287 let binding = PackedIntBinding::new();
1288 let mut out = TupleOutput::new();
1289 out.write_string("abc");
1290 binding.object_to_tuple(&1234i32, &mut out).unwrap();
1291 out.write_string("xyz");
1292
1293 let mut inp = TupleInput::new(&out.to_vec());
1294 assert_eq!(inp.read_string().unwrap(), "abc");
1295 let val: i32 = binding.tuple_to_object(&mut inp).unwrap();
1296 assert_eq!(val, 1234);
1297 assert_eq!(inp.read_string().unwrap(), "xyz");
1298 assert_eq!(inp.available(), 0);
1299 }
1300
1301 #[test]
1303 fn test_nested_binding_coverage_packed_long() {
1304 use crate::tuple::tuple_binding::TupleBinding;
1305 let binding = PackedLongBinding::new();
1306 let mut out = TupleOutput::new();
1307 out.write_string("abc");
1308 binding.object_to_tuple(&1234i64, &mut out).unwrap();
1309 out.write_string("xyz");
1310
1311 let mut inp = TupleInput::new(&out.to_vec());
1312 assert_eq!(inp.read_string().unwrap(), "abc");
1313 let val: i64 = binding.tuple_to_object(&mut inp).unwrap();
1314 assert_eq!(val, 1234);
1315 assert_eq!(inp.read_string().unwrap(), "xyz");
1316 assert_eq!(inp.available(), 0);
1317 }
1318
1319 #[test]
1326 fn test_packed_int_binding_1234_size() {
1327 let binding = PackedIntBinding::new();
1328 let mut entry = DatabaseEntry::new();
1329 binding.object_to_entry(&1234i32, &mut entry).unwrap();
1330 assert_eq!(
1332 entry.data().len(),
1333 3,
1334 "1234 should encode to 3 bytes (header + 2 value bytes)"
1335 );
1336 let got = binding.entry_to_object(&entry).unwrap();
1338 assert_eq!(got, 1234i32);
1339 }
1340
1341 #[test]
1347 fn test_packed_long_binding_1234_size() {
1348 let binding = PackedLongBinding::new();
1349 let mut entry = DatabaseEntry::new();
1350 binding.object_to_entry(&1234i64, &mut entry).unwrap();
1351 assert_eq!(
1353 entry.data().len(),
1354 3,
1355 "1234L should encode to 3 bytes (header + 2 value bytes)"
1356 );
1357 let got = binding.entry_to_object(&entry).unwrap();
1358 assert_eq!(got, 1234i64);
1359 }
1360
1361 #[test]
1368 fn test_sorted_packed_int_binding_1234_size() {
1369 let binding = SortedPackedIntBinding::new();
1370 let mut entry = DatabaseEntry::new();
1371 binding.object_to_entry(&1234i32, &mut entry).unwrap();
1372 assert_eq!(
1374 entry.data().len(),
1375 3,
1376 "1234 should encode to 3 bytes in SortedPackedIntBinding"
1377 );
1378 let got = binding.entry_to_object(&entry).unwrap();
1379 assert_eq!(got, 1234i32);
1380 }
1381
1382 #[test]
1384 fn test_sorted_packed_long_binding_1234_size() {
1385 let binding = SortedPackedLongBinding::new();
1386 let mut entry = DatabaseEntry::new();
1387 binding.object_to_entry(&1234i64, &mut entry).unwrap();
1388 assert_eq!(
1390 entry.data().len(),
1391 3,
1392 "1234L should encode to 3 bytes in SortedPackedLongBinding"
1393 );
1394 let got = binding.entry_to_object(&entry).unwrap();
1395 assert_eq!(got, 1234i64);
1396 }
1397
1398 #[test]
1404 fn test_all_primitive_bindings_round_trip() {
1405 {
1407 let b = BoolBinding::new();
1408 let mut e = DatabaseEntry::new();
1409 b.object_to_entry(&true, &mut e).unwrap();
1410 assert!(b.entry_to_object(&e).unwrap());
1411 }
1412 {
1414 let b = ByteBinding::new();
1415 let mut e = DatabaseEntry::new();
1416 b.object_to_entry(&123u8, &mut e).unwrap();
1417 assert_eq!(b.entry_to_object(&e).unwrap(), 123u8);
1418 }
1419 {
1421 let b = ShortBinding::new();
1422 let mut e = DatabaseEntry::new();
1423 b.object_to_entry(&123i16, &mut e).unwrap();
1424 assert_eq!(b.entry_to_object(&e).unwrap(), 123i16);
1425 }
1426 {
1428 let b = IntBinding::new();
1429 let mut e = DatabaseEntry::new();
1430 b.object_to_entry(&123i32, &mut e).unwrap();
1431 assert_eq!(b.entry_to_object(&e).unwrap(), 123i32);
1432 }
1433 {
1435 let b = LongBinding::new();
1436 let mut e = DatabaseEntry::new();
1437 b.object_to_entry(&123i64, &mut e).unwrap();
1438 assert_eq!(b.entry_to_object(&e).unwrap(), 123i64);
1439 }
1440 {
1442 let b = FloatBinding::new();
1443 let mut e = DatabaseEntry::new();
1444 b.object_to_entry(&123.123f32, &mut e).unwrap();
1445 let got = b.entry_to_object(&e).unwrap();
1446 assert!((got - 123.123f32).abs() < 1e-3);
1447 }
1448 {
1450 let b = DoubleBinding::new();
1451 let mut e = DatabaseEntry::new();
1452 b.object_to_entry(&123.123f64, &mut e).unwrap();
1453 let got = b.entry_to_object(&e).unwrap();
1454 assert!((got - 123.123f64).abs() < 1e-9);
1455 }
1456 {
1458 let b = CharBinding::new();
1459 let mut e = DatabaseEntry::new();
1460 b.object_to_entry(&(b'a' as u16), &mut e).unwrap();
1461 assert_eq!(b.entry_to_object(&e).unwrap(), b'a' as u16);
1462 }
1463 {
1465 let b = StringBinding::new();
1466 let mut e = DatabaseEntry::new();
1467 b.object_to_entry(&"abc".to_string(), &mut e).unwrap();
1468 assert_eq!(b.entry_to_object(&e).unwrap(), "abc".to_string());
1469 }
1470 }
1471
1472 #[test]
1478 fn test_string_ordering_sorted_sequence() {
1479 let binding = StringBinding::new();
1480 let data = vec![
1483 "".to_string(),
1484 "\u{0001}".to_string(),
1485 "\u{0002}".to_string(),
1486 "A".to_string(),
1487 "a".to_string(),
1488 "ab".to_string(),
1489 "b".to_string(),
1490 "bb".to_string(),
1491 "bba".to_string(),
1492 "c".to_string(),
1493 ];
1494 let encoded: Vec<Vec<u8>> =
1495 data.iter().map(|v| encoded_bytes(&binding, v)).collect();
1496 for i in 0..encoded.len() - 1 {
1497 assert!(
1498 encoded[i] < encoded[i + 1],
1499 "string ordering violated: {:?} should sort before {:?}",
1500 data[i],
1501 data[i + 1]
1502 );
1503 }
1504 }
1505
1506 #[test]
1508 fn test_u8_binding_ordering() {
1509 let binding = ByteBinding::new();
1511 let values: Vec<u8> = vec![0, 1, 0x7F, 0xFF];
1512 let encoded: Vec<Vec<u8>> =
1513 values.iter().map(|v| encoded_bytes(&binding, v)).collect();
1514 for i in 0..encoded.len() - 1 {
1515 assert!(
1516 encoded[i] < encoded[i + 1],
1517 "u8 binding ordering violated: {} should sort before {}",
1518 values[i],
1519 values[i + 1]
1520 );
1521 }
1522 }
1523}