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,18 +52,25 @@ 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 :: {self, BoundedInt , UnitInt , downcast};
55
57
#[allow(unused_imports)]
56
58
use crate :: serde :: Serde ;
57
59
use crate :: traits :: {Into , TryInto };
58
60
#[allow(unused_imports)]
59
61
use crate :: zeroable :: NonZeroIntoImpl ;
60
62
63
+ /// The number of bytes in [`ByteArray::pending_word`].
64
+ type WordBytes = BoundedInt <0 , { BYTES_IN_BYTES31_MINUS_ONE . into() }>;
65
+ type BYTES_IN_BYTES31_TYPED = UnitInt <{ BYTES_IN_BYTES31 . into() }>;
66
+
61
67
/// A magic constant for identifying serialization of `ByteArray` variables. An array of `felt252`
62
68
/// with this magic value as one of the `felt252` indicates that you should expect right after it a
63
69
/// serialized `ByteArray`. This is currently used mainly for prints and panics.
64
70
pub const BYTE_ARRAY_MAGIC : felt252 =
65
71
0x46a6158a16a947e5916b2a2ca68501a45e93d7110e81aa2d6438b1c57c879a3 ;
66
72
const BYTES_IN_U128 : usize = 16 ;
73
+ const BYTES_IN_BYTES31_UNIT_INT : BYTES_IN_BYTES31_TYPED = downcast (BYTES_IN_BYTES31 ). unwrap ();
67
74
const BYTES_IN_BYTES31_MINUS_ONE : usize = BYTES_IN_BYTES31 - 1 ;
68
75
const BYTES_IN_BYTES31_NONZERO : NonZero <usize > = BYTES_IN_BYTES31 . try_into (). unwrap ();
69
76
@@ -586,3 +593,115 @@ impl ByteArrayFromIterator of crate::iter::FromIterator<ByteArray, u8> {
586
593
ba
587
594
}
588
595
}
596
+
597
+ /// A view into a contiguous collection of a string type.
598
+ /// Currently implemented only for `ByteArray`, but will soon be implemented for other string types.
599
+ /// `Span` implements the `Copy` and the `Drop` traits.
600
+ #[derive(Copy , Drop )]
601
+ pub struct ByteSpan {
602
+ /// A span representing the array of all `bytes31` words in the byte-span, excluding the last
603
+ /// bytes_31 word that is stored in [Self::last_word].
604
+ /// Invariant: every byte stored in `data` is part of the span except for the bytes appearing
605
+ /// before `first_char_start_offset` in the first word.
606
+ data : Span <bytes31 >,
607
+ /// The offset of the first character in the first entry of [Self::data], for use in span
608
+ /// slices. When data is empty, this offset applies to remainder_word instead.
609
+ first_char_start_offset : WordBytes ,
610
+ /// Contains the final bytes of the span when the end is either not in memory or isn't aligned
611
+ /// to a word boundary.
612
+ /// It is represented as a `felt252` to improve performance of building the byte array, but
613
+ /// represents a `bytes31`.
614
+ /// The first byte is the most significant byte among the `pending_word_len` bytes in the word.
615
+ remainder_word : felt252 ,
616
+ /// The number of bytes in [Self::remainder_word].
617
+ remainder_len : WordBytes ,
618
+ }
619
+
620
+
621
+ #[generate_trait]
622
+ pub impl ByteSpanImpl of ByteSpanTrait {
623
+ /// Returns the length of the `ByteSpan`.
624
+ ///
625
+ /// # Examples
626
+ ///
627
+ /// ```
628
+ /// let ba: ByteArray = "byte array";
629
+ /// let span = ba.span();
630
+ /// let len = span.len();
631
+ /// assert!(len == 10);
632
+ /// ```
633
+ #[must_use]
634
+ fn len (self : ByteSpan ) -> usize {
635
+ let data_bytes = bounded_int :: mul (self . data. len (), BYTES_IN_BYTES31_UNIT_INT );
636
+ let span_bytes_unadjusted = bounded_int :: add (self . remainder_len, data_bytes );
637
+ let span_bytes = bounded_int :: sub (span_bytes_unadjusted , self . first_char_start_offset);
638
+
639
+ downcast (span_bytes ). unwrap ()
640
+ }
641
+
642
+ /// Returns `true` if the `ByteSpan` has a length of 0.
643
+ ///
644
+ /// # Examples
645
+ ///
646
+ /// ```
647
+ /// let ba: ByteArray = "";
648
+ /// let span = ba.span();
649
+ /// assert!(span.is_empty());
650
+ ///
651
+ /// let ba2: ByteArray = "not empty";
652
+ /// let span2 = ba2.span();
653
+ /// assert!(!span2.is_empty());
654
+ /// ```
655
+ fn is_empty (self : ByteSpan ) -> bool {
656
+ self . remainder_len == 0 && self . data. len () == 0
657
+ }
658
+ }
659
+
660
+ pub trait ToByteSpanTrait <C > {
661
+ #[must_use]
662
+ fn span (self : @ C ) -> ByteSpan ;
663
+ }
664
+
665
+ impl ByteArrayToByteSpan of ToByteSpanTrait <ByteArray > {
666
+ fn span (self : @ ByteArray ) -> ByteSpan {
667
+ ByteSpan {
668
+ data : self . data. span (),
669
+ first_char_start_offset : 0 ,
670
+ remainder_word : * self . pending_word,
671
+ remainder_len : downcast (self . pending_word_len). expect (' In [0,30] by assumption' ),
672
+ }
673
+ }
674
+ }
675
+
676
+ impl ByteSpanToByteSpan of ToByteSpanTrait <ByteSpan > {
677
+ fn span (self : @ ByteSpan ) -> ByteSpan {
678
+ * self
679
+ }
680
+ }
681
+
682
+ mod helpers {
683
+ use core :: num :: traits :: Bounded ;
684
+ use crate :: bytes_31 :: BYTES_IN_BYTES31 ;
685
+ #[feature(" bounded-int-utils" )]
686
+ use crate :: internal :: bounded_int :: {AddHelper , BoundedInt , MulHelper , SubHelper };
687
+ use super :: {BYTES_IN_BYTES31_MINUS_ONE , BYTES_IN_BYTES31_TYPED , WordBytes };
688
+
689
+ const U32_MAX_TIMES_B31 : felt252 = Bounded :: <u32 >:: MAX . into () * BYTES_IN_BYTES31 . into ();
690
+
691
+ pub impl U32ByB31 of MulHelper <u32 , BYTES_IN_BYTES31_TYPED > {
692
+ type Result = BoundedInt <0 , { U32_MAX_TIMES_B31 }>;
693
+ }
694
+
695
+ pub impl B30AddU32ByB31 of AddHelper <WordBytes , U32ByB31 :: Result > {
696
+ type Result = BoundedInt <0 , { BYTES_IN_BYTES31_MINUS_ONE . into() + U32_MAX_TIMES_B31 }>;
697
+ }
698
+
699
+ pub impl B30AddU32ByB31SubB30 of SubHelper <B30AddU32ByB31 :: Result , WordBytes > {
700
+ type Result =
701
+ BoundedInt <
702
+ { - BYTES_IN_BYTES31_MINUS_ONE . into() },
703
+ { BYTES_IN_BYTES31_MINUS_ONE . into() + U32_MAX_TIMES_B31 },
704
+ >;
705
+ }
706
+ }
707
+ use helpers :: {B30AddU32ByB31 , B30AddU32ByB31SubB30 , U32ByB31 };
0 commit comments