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,54 @@ 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
+ fn len (self : @ ByteSpan ) -> usize {
618
+ let data_bytes = self . data. len () * BYTES_IN_BYTES31 ;
619
+ data_bytes - upcast (self . first_char_start_offset) + upcast (self . remainder_len)
620
+ }
621
+
622
+ fn is_empty (self : @ ByteSpan ) -> bool {
623
+ self . len () == 0
624
+ }
625
+ }
626
+
627
+ pub trait ToByteSpanTrait <C > {
628
+ #[must_use]
629
+ fn span (self : @ C ) -> ByteSpan ;
630
+ }
631
+
632
+ impl ByteArrayToByteSpan of ToByteSpanTrait <ByteArray > {
633
+ fn span (self : @ ByteArray ) -> ByteSpan {
634
+ ByteSpan {
635
+ data : self . data. span (),
636
+ first_char_start_offset : downcast (0 ). unwrap (),
637
+ remainder_word : * self . pending_word,
638
+ remainder_len : downcast (self . pending_word_len). expect (' In [0,30] by assumption' ),
639
+ }
640
+ }
641
+ }
0 commit comments