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