1
1
use crate :: byte_array :: {ByteSpanTrait , ToByteSpanTrait };
2
+ use crate :: num :: traits :: Bounded ;
2
3
use crate :: test :: test_utils :: {assert_eq, assert_ne};
3
4
4
5
#[test]
@@ -507,7 +508,6 @@ fn test_from_collect() {
507
508
assert_eq! (ba , " hello" );
508
509
}
509
510
510
- // TODO(giladchase): add dedicated is_empty test once we have `slice`.
511
511
#[test]
512
512
fn test_span_len () {
513
513
// Test simple happy flow --- value is included in the last word.
@@ -517,28 +517,60 @@ fn test_span_len() {
517
517
assert_eq! (span . len (), 1 );
518
518
assert! (! span . is_empty ());
519
519
520
+ let ba_31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" ;
521
+ let span = ba_31 . span ();
522
+ assert_eq! (span . len (), 31 , " wrong span len" );
523
+ assert! (! span . is_empty ());
524
+
520
525
// Test empty.
521
526
let empty_ba : ByteArray = "" ;
522
527
let empty_span = empty_ba . span ();
523
528
assert_eq! (empty_span . len (), 0 );
524
529
assert! (empty_span . is_empty ());
525
530
526
- // TODO(giladchase): Add start-offset using slice once supported.
527
531
// First word in the array, second in last word.
528
532
let two_byte31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg" ;
529
- let mut single_span = two_byte31 . span ();
530
- assert_eq! (single_span . len (), 33 , " len error with start offset" );
533
+ let mut single_span = two_byte31 . span (). slice ( 1 , 32 ) . unwrap () ;
534
+ assert_eq! (single_span . len (), 32 , " len error with start offset" );
531
535
assert! (! single_span . is_empty ());
532
536
533
- // TODO(giladchase): Add start-offset using slice once supported.
534
537
// First word in the array, second in the array, third in last word.
535
538
let three_bytes31 : ByteArray =
536
539
" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ; // 64 chars.
537
- let mut three_span = three_bytes31 . span ();
538
- assert_eq! (three_span . len (), 64 , " len error with size-3 bytearray" );
540
+ let mut three_span = three_bytes31 . span (). slice ( 1 , 63 ) . unwrap () ;
541
+ assert_eq! (three_span . len (), 63 , " len error with size-3 bytearray" );
539
542
assert! (! three_span . is_empty ());
540
543
}
541
544
545
+ #[test]
546
+ fn test_span_slice_is_empty () {
547
+ let ba : ByteArray = " hello" ;
548
+ let span = ba . span ();
549
+
550
+ let empty = span . slice (2 , 0 ). unwrap ();
551
+ assert_eq! (empty . len (), 0 );
552
+ assert! (empty . is_empty ());
553
+
554
+ let empty_string : ByteArray = "" ;
555
+ assert_eq! (empty_string , empty . to_byte_array ());
556
+
557
+ let ba_31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" ;
558
+ let span = ba_31 . span ();
559
+ assert! (span . slice (30 , 0 ). unwrap (). is_empty ());
560
+ assert! (span . slice (31 , 0 ). unwrap (). is_empty ());
561
+ assert! (! span . slice (30 , 1 ). unwrap (). is_empty ());
562
+ assert! (! span . slice (15 , 16 ). unwrap (). is_empty ());
563
+ assert! (! span . slice (16 , 15 ). unwrap (). is_empty ());
564
+
565
+ let ba_30 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcd" ;
566
+ let span = ba_30 . span ();
567
+ assert! (span . slice (29 , 0 ). unwrap (). is_empty ());
568
+ assert! (span . slice (30 , 0 ). unwrap (). is_empty ());
569
+ assert! (! span . slice (29 , 1 ). unwrap (). is_empty ());
570
+ assert! (! span . slice (14 , 15 ). unwrap (). is_empty ());
571
+ assert! (! span . slice (15 , 14 ). unwrap (). is_empty ());
572
+ }
573
+
542
574
#[test]
543
575
fn test_span_copy () {
544
576
let ba : ByteArray = " 12" ;
@@ -559,6 +591,100 @@ fn test_span_copy() {
559
591
assert_eq! (ba , span . to_byte_array ());
560
592
}
561
593
594
+ #[test]
595
+ fn test_span_slice_empty () {
596
+ let ba : ByteArray = " hello" ;
597
+ let span = ba . span ();
598
+
599
+ let empty = span . slice (2 , 0 ). unwrap ();
600
+ assert_eq! (empty . len (), 0 );
601
+ assert! (empty . is_empty ());
602
+
603
+ let empty_string : ByteArray = "" ;
604
+ assert_eq! (empty_string , empty . to_byte_array ());
605
+ }
606
+
607
+ // TODO(giladchase): replace assert+is_none with assert_eq when we have PartialEq.
608
+ #[test]
609
+ fn test_span_slice_out_of_bounds () {
610
+ let ba : ByteArray = " hello" ;
611
+ let span = ba . span ();
612
+
613
+ assert! (span . slice (3 , 5 ). is_none (), " end out of bounds" );
614
+ assert! (span . slice (6 , 1 ). is_none (), " start out of bounds" );
615
+
616
+ assert! (
617
+ span . slice (1 , 3 ). unwrap (). slice (Bounded :: <usize >:: MAX , 1 ). is_none (),
618
+ " start offset overflow" ,
619
+ );
620
+ assert! (span . slice (Bounded :: <usize >:: MAX , 1 ). is_none ());
621
+ assert! (span . slice (1 , Bounded :: <usize >:: MAX ). is_none ());
622
+
623
+ let empty_string : ByteArray = "" ;
624
+ assert! (empty_string . span (). slice (0 , 2 ). is_none (), " empty slice is sliceable" );
625
+ }
626
+
627
+ #[test]
628
+ fn test_span_slice_under_31_bytes () {
629
+ // Word entirely in remainder word.
630
+ let ba : ByteArray = " abcde" ;
631
+ let span = ba . span ();
632
+
633
+ let mut slice : ByteArray = span . slice (0 , 3 ). unwrap (). to_byte_array ();
634
+ assert_eq! (slice , " abc" , " first 3 bytes" );
635
+
636
+ slice = span . slice (2 , 2 ). unwrap (). to_byte_array ();
637
+ assert_eq! (slice , " cd" , " middle 2 bytes" );
638
+
639
+ slice = span . slice (4 , 1 ). unwrap (). to_byte_array ();
640
+ assert_eq! (slice , " e" , " last byte" );
641
+ }
642
+ #[test]
643
+ fn test_span_slice_exactly_31_bytes () {
644
+ // 1 full data word, empty last_word.
645
+ let ba_31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" ; // 31 bytes
646
+ let span31 = ba_31 . span ();
647
+ assert_eq! (span31 . len (), 31 );
648
+
649
+ let ba : ByteArray = span31 . slice (0 , 31 ). unwrap (). to_byte_array ();
650
+ assert_eq! (ba , ba_31 );
651
+
652
+ // Debug: Let's check what byte is at position 10
653
+ assert_eq! (ba_31 . at (10 ), Some (' K' ));
654
+ assert_eq! (ba_31 . at (11 ), Some (' L' ));
655
+
656
+ // Partial slice
657
+ let ba : ByteArray = span31 . slice (10 , 10 ). unwrap (). to_byte_array ();
658
+ assert_eq! (ba , " KLMNOPQRST" , " middle 10 bytes" );
659
+ }
660
+
661
+ #[test]
662
+ fn test_span_slice_positions () {
663
+ // Two full bytes31 + remainder with 2 bytes.
664
+ let ba : ByteArray =
665
+ " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ; // 64 bytes
666
+ let span = ba . span ();
667
+
668
+ // Slice from middle of first word to middle of second word.
669
+ let short_slice_across_data_words = span . slice (10 , 30 ). unwrap ();
670
+ let mut ba_from_span : ByteArray = short_slice_across_data_words . to_byte_array ();
671
+ assert_eq! (ba_from_span , " KLMNOPQRSTUVWXYZabcdefghijklmn" , " multi-word short slice failed" );
672
+
673
+ // Slice spanning 3 words (two data and remainder).
674
+ let long_slice_across_data_words = span . slice (5 , 59 ). unwrap ();
675
+ ba_from_span = long_slice_across_data_words . to_byte_array ();
676
+ assert_eq! (
677
+ ba_from_span ,
678
+ " FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ,
679
+ " multi-word long slice failed" ,
680
+ );
681
+
682
+ // Slice from second word into remainder.
683
+ let short_slice_into_remainder_word = span . slice (29 , 20 ). unwrap ();
684
+ ba_from_span = short_slice_into_remainder_word . to_byte_array ();
685
+ assert_eq! (ba_from_span , " defghijklmnopqrstuvw" , " short slice into remainder word failed" );
686
+ }
687
+
562
688
#[test]
563
689
fn test_span_to_bytearray () {
564
690
let empty_ba : ByteArray = "" ;
@@ -576,5 +702,28 @@ fn test_span_to_bytearray() {
576
702
let even_larger_ba : ByteArray =
577
703
" abcdeFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ; // 64 bytes
578
704
assert_eq! (even_larger_ba . span (). to_byte_array (), even_larger_ba );
579
- // TODO(giladchase): test with slice.
705
+
706
+ // Test sliced span with offset.
707
+ let sliced : ByteArray = large_ba . span (). slice (10 , 25 ). unwrap (). to_byte_array ();
708
+ assert_eq! (sliced , " :;<=>?@ABCDEFGHIJKLMNOPQR" );
709
+ }
710
+
711
+ #[test]
712
+ fn test_span_multiple_start_offset_slicing () {
713
+ // Test to demonstrate the optimization of lazy start-offset trimming.
714
+ // Multiple slicing operations on remainder word should be more efficient.
715
+ let ba : ByteArray = " abcdef" ; // 10 bytes in remainder
716
+ let span = ba . span ();
717
+
718
+ let slice1 = span . slice (1 , 5 ). unwrap ();
719
+ let slice2 = slice1 . slice (1 , 4 ). unwrap ();
720
+ let slice3 = slice2 . slice (1 , 3 ). unwrap ();
721
+
722
+ // Convert to ByteArray to verify correctness
723
+ let result1 : ByteArray = slice1 . to_byte_array ();
724
+ assert_eq! (result1 , " bcdef" , " first slice" );
725
+ let result2 : ByteArray = slice2 . to_byte_array ();
726
+ assert_eq! (result2 , " cdef" , " second slice" );
727
+ let result3 : ByteArray = slice3 . to_byte_array ();
728
+ assert_eq! (result3 , " def" , " third slice" );
580
729
}
0 commit comments