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 );
@@ -516,25 +520,28 @@ fn test_span_len() {
516
520
assert_eq! (span . len (), 1 );
517
521
assert! (! span . is_empty ());
518
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
+
519
528
// Test empty.
520
529
let empty_ba : ByteArray = "" ;
521
530
let empty_span = empty_ba . span ();
522
531
assert_eq! (empty_span . len (), 0 );
523
532
assert! (empty_span . is_empty ());
524
533
525
- // TODO(giladchase): Add start-offset using slice once supported.
526
534
// First word in the array, second in last word.
527
535
let two_byte31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefg" ;
528
- let mut single_span = two_byte31 . span ();
529
- 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" );
530
538
assert! (! single_span . is_empty ());
531
539
532
- // TODO(giladchase): Add start-offset using slice once supported.
533
540
// First word in the array, second in the array, third in last word.
534
541
let three_bytes31 : ByteArray =
535
542
" ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ; // 64 chars.
536
- let mut three_span = three_bytes31 . span ();
537
- 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" );
538
545
assert! (! three_span . is_empty ());
539
546
}
540
547
@@ -558,6 +565,100 @@ fn test_span_copy() {
558
565
assert_eq! (ba , span . into ());
559
566
}
560
567
568
+ #[test]
569
+ fn test_span_slice_empty () {
570
+ let ba : ByteArray = " hello" ;
571
+ let span = ba . span ();
572
+
573
+ let empty = span . slice (2 , 0 ). unwrap ();
574
+ assert_eq! (empty . len (), 0 );
575
+ assert! (empty . is_empty ());
576
+
577
+ let empty_string : ByteArray = "" ;
578
+ assert_eq! (empty_string , empty . into ());
579
+ }
580
+
581
+ // TODO(giladchase): replace assert+is_none with assert_eq when we have PartialEq.
582
+ #[test]
583
+ fn test_span_slice_out_of_bounds () {
584
+ let ba : ByteArray = " hello" ;
585
+ let span = ba . span ();
586
+
587
+ assert! (span . slice (3 , 5 ). is_none (), " end out of bounds" );
588
+ assert! (span . slice (6 , 1 ). is_none (), " start out of bounds" );
589
+
590
+ assert! (
591
+ span . slice (1 , 3 ). unwrap (). slice (Bounded :: <usize >:: MAX , 1 ). is_none (),
592
+ " start offset overflow" ,
593
+ );
594
+ assert! (span . slice (Bounded :: <usize >:: MAX , 1 ). is_none ());
595
+ assert! (span . slice (1 , Bounded :: <usize >:: MAX ). is_none ());
596
+
597
+ let empty_string : ByteArray = "" ;
598
+ assert! (empty_string . span (). slice (0 , 2 ). is_none (), " empty slice is sliceable" );
599
+ }
600
+
601
+ #[test]
602
+ fn test_span_slice_under_31_bytes () {
603
+ // Word entirely in remainder word.
604
+ let ba : ByteArray = " abcde" ;
605
+ let span = ba . span ();
606
+
607
+ let mut slice : ByteArray = span . slice (0 , 3 ). unwrap (). into ();
608
+ assert_eq! (slice , " abc" , " first 3 bytes" );
609
+
610
+ slice = span . slice (2 , 2 ). unwrap (). into ();
611
+ assert_eq! (slice , " cd" , " middle 2 bytes" );
612
+
613
+ slice = span . slice (4 , 1 ). unwrap (). into ();
614
+ assert_eq! (slice , " e" , " last byte" );
615
+ }
616
+ #[test]
617
+ fn test_span_slice_exactly_31_bytes () {
618
+ // 1 full data word, empty last_word.
619
+ let ba_31 : ByteArray = " ABCDEFGHIJKLMNOPQRSTUVWXYZabcde" ; // 31 bytes
620
+ let span31 = ba_31 . span ();
621
+ assert_eq! (span31 . len (), 31 );
622
+
623
+ let ba : ByteArray = span31 . slice (0 , 31 ). unwrap (). into ();
624
+ assert_eq! (ba , ba_31 );
625
+
626
+ // Debug: Let's check what byte is at position 10
627
+ assert_eq! (ba_31 . at (10 ), Some (' K' ));
628
+ assert_eq! (ba_31 . at (11 ), Some (' L' ));
629
+
630
+ // Partial slice
631
+ let ba : ByteArray = span31 . slice (10 , 10 ). unwrap (). into ();
632
+ assert_eq! (ba , " KLMNOPQRST" , " middle 10 bytes" );
633
+ }
634
+
635
+ #[test]
636
+ fn test_span_slice_positions () {
637
+ // Two full bytes31 + remainder with 2 bytes.
638
+ let ba : ByteArray =
639
+ " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789#$" ; // 64 bytes
640
+ let span = ba . span ();
641
+
642
+ // Slice from middle of first word to middle of second word.
643
+ let short_slice_across_data_words = span . slice (10 , 30 ). unwrap ();
644
+ let mut ba_from_span : ByteArray = short_slice_across_data_words . into ();
645
+ assert_eq! (ba_from_span , " KLMNOPQRSTUVWXYZabcdefghijklmn" , " multi-word short slice failed" );
646
+
647
+ // Slice spanning multiple words.
648
+ let long_slice_across_data_words = span . slice (5 , 50 ). unwrap ();
649
+ ba_from_span = long_slice_across_data_words . into ();
650
+ assert_eq! (
651
+ ba_from_span ,
652
+ " FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012" ,
653
+ " multi-word long slice failed" ,
654
+ );
655
+
656
+ // Slice from second word into remainder.
657
+ let short_slice_into_remainder_word = span . slice (29 , 20 ). unwrap ();
658
+ ba_from_span = short_slice_into_remainder_word . into ();
659
+ assert_eq! (ba_from_span , " defghijklmnopqrstuvw" , " short slice into remainder word failed" );
660
+ }
661
+
561
662
#[test]
562
663
fn test_span_into_bytearray () {
563
664
let empty_ba : ByteArray = "" ;
@@ -570,5 +671,29 @@ fn test_span_into_bytearray() {
570
671
// Data word and remainder.
571
672
let large_ba : ByteArray = " 0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVW" ; // 40 bytes
572
673
assert_eq! (large_ba . span (). into (), large_ba );
573
- // TODO(giladchase): test with slice.
674
+
675
+ // Test sliced span with offset.
676
+ let sliced : ByteArray = large_ba . span (). slice (10 , 25 ). unwrap (). into ();
677
+ assert_eq! (sliced , " :;<=>?@ABCDEFGHIJKLMNOPQR" );
678
+ }
679
+
680
+ #[test]
681
+ fn test_span_multiple_start_offset_slicing () {
682
+ // Test to demonstrate the optimization of lazy start-offset trimming.
683
+ // Multiple slicing operations on remainder word should be more efficient.
684
+ let ba : ByteArray = " abcdef" ; // 10 bytes in remainder
685
+ let span = ba . span ();
686
+
687
+ let slice1 = span . slice (1 , 5 ). unwrap ();
688
+ let slice2 = slice1 . slice (1 , 4 ). unwrap ();
689
+ let slice3 = slice2 . slice (1 , 3 ). unwrap ();
690
+
691
+ // Convert to ByteArray to verify correctness
692
+ let result1 : ByteArray = slice1 . into ();
693
+ assert_eq! (result1 , " bcdef" , " first slice" );
694
+ let result2 : ByteArray = slice2 . into ();
695
+ assert_eq! (result2 , " cdef" , " second slice" );
696
+ let result3 : ByteArray = slice3 . into ();
697
+ assert_eq! (result3 , " def" , " third slice" );
574
698
}
699
+
0 commit comments