42
42
// ! assert!(first_byte == 0x41);
43
43
// ! ```
44
44
45
- use crate :: array :: {ArrayTrait , SpanTrait };
45
+ use crate :: array :: {ArrayTrait , Span , SpanTrait };
46
46
#[allow(unused_imports)]
47
47
use crate :: bytes_31 :: {
48
48
BYTES_IN_BYTES31 , Bytes31Trait , POW_2_128 , POW_2_8 , U128IntoBytes31 , U8IntoBytes31 ,
@@ -52,6 +52,8 @@ use crate::clone::Clone;
52
52
use crate :: cmp :: min;
53
53
#[allow(unused_imports)]
54
54
use crate :: integer :: {U32TryIntoNonZero , u128_safe_divmod};
55
+ #[feature(" bounded-int-utils" )]
56
+ use crate :: internal :: bounded_int :: {BoundedInt , downcast, upcast};
55
57
#[allow(unused_imports)]
56
58
use crate :: serde :: Serde ;
57
59
use crate :: traits :: {Into , TryInto };
@@ -586,3 +588,84 @@ impl ByteArrayFromIterator of crate::iter::FromIterator<ByteArray, u8> {
586
588
ba
587
589
}
588
590
}
591
+
592
+ /// A view into a contiguous collection of a string type.
593
+ /// Currently implemented only for `ByteArray`, but will soon be implemented for other string types.
594
+ /// `Span` implements the `Copy` and the `Drop` traits.
595
+ #[derive(Copy , Drop )]
596
+ pub struct ByteSpan {
597
+ /// A span representing the array of all `bytes31` words in the byte-span, excluding the last
598
+ /// bytes_31 word that is stored in [Self::last_word].
599
+ /// Invariant: every byte stored in `data` is part of the span except for the bytes appearing
600
+ /// before `first_char_start_offset` in the first word.
601
+ data : Span <bytes31 >,
602
+ /// The offset of the first character in the first entry of [Self::data], for use in span
603
+ /// slices.
604
+ first_char_start_offset : BoundedInt <0 , 30 >,
605
+ /// Contains the final bytes of the span when the end is either not in memory or isn't aligned
606
+ /// to a word boundary.
607
+ /// It is represented as a `felt252` to improve performance of building the byte array, but
608
+ /// represents a `bytes31`.
609
+ /// The first byte is the most significant byte among the `pending_word_len` bytes in the word.
610
+ remainder_word : felt252 ,
611
+ /// The number of bytes in [Self::remainder_word].
612
+ remainder_len : BoundedInt <0 , 31 >,
613
+ }
614
+
615
+ #[generate_trait]
616
+ pub impl ByteArraySpanImpl of ByteSpanTrait {
617
+ /// Returns the length of the `ByteSpan`.
618
+ ///
619
+ /// # Examples
620
+ ///
621
+ /// ```
622
+ /// let ba: ByteArray = "byte array";
623
+ /// let span = ba.span();
624
+ /// let len = span.len();
625
+ /// assert!(len == 10);
626
+ /// ```
627
+ #[must_use]
628
+ fn len (self : @ ByteSpan ) -> usize {
629
+ let data_bytes = self . data. len () * BYTES_IN_BYTES31 ;
630
+ data_bytes - upcast (self . first_char_start_offset) + upcast (self . remainder_len)
631
+ }
632
+
633
+ /// Returns `true` if the `ByteSpan` has a length of 0.
634
+ ///
635
+ /// # Examples
636
+ ///
637
+ /// ```
638
+ /// let ba: ByteArray = "";
639
+ /// let span = ba.span();
640
+ /// assert!(span.is_empty());
641
+ ///
642
+ /// let ba2: ByteArray = "not empty";
643
+ /// let span2 = ba2.span();
644
+ /// assert!(!span2.is_empty());
645
+ /// ```
646
+ fn is_empty (self : @ ByteSpan ) -> bool {
647
+ self . len () == 0
648
+ }
649
+ }
650
+
651
+ pub trait ToByteSpanTrait <C > {
652
+ #[must_use]
653
+ fn span (self : @ C ) -> ByteSpan ;
654
+ }
655
+
656
+ impl ByteArrayToByteSpan of ToByteSpanTrait <ByteArray > {
657
+ fn span (self : @ ByteArray ) -> ByteSpan {
658
+ ByteSpan {
659
+ data : self . data. span (),
660
+ first_char_start_offset : 0 ,
661
+ remainder_word : * self . pending_word,
662
+ remainder_len : downcast (self . pending_word_len). expect (' In [0,30] by assumption' ),
663
+ }
664
+ }
665
+ }
666
+
667
+ impl ByteSpanToByteSpan of ToByteSpanTrait <ByteSpan > {
668
+ fn span (self : @ ByteSpan ) -> ByteSpan {
669
+ * self
670
+ }
671
+ }
0 commit comments