sov_state/
utils.rs

1/// A [`Vec`] of bytes whose length is guaranteed to be aligned to 4 bytes.
2/// This makes certain operations cheaper in zk-context (namely, concatenation).
3// TODO: Currently the implementation defaults to `stc::vec::Vec` see:
4// https://github.com/Sovereign-Labs/sovereign-sdk/issues/47
5#[derive(
6    borsh::BorshDeserialize,
7    borsh::BorshSerialize,
8    Debug,
9    PartialEq,
10    Eq,
11    Clone,
12    serde::Serialize,
13    serde::Deserialize,
14)]
15pub struct AlignedVec {
16    inner: Vec<u8>,
17}
18
19impl AlignedVec {
20    /// The length of the chunks of the aligned vector.
21    pub const ALIGNMENT: usize = 4;
22
23    /// Creates a new [`AlignedVec`] whose length is aligned to
24    /// [`AlignedVec::ALIGNMENT`] bytes.
25    pub fn new(vector: Vec<u8>) -> Self {
26        Self { inner: vector }
27    }
28
29    /// Extends `self` with the contents of the other [`AlignedVec`].
30    pub fn extend(&mut self, other: &Self) {
31        // TODO check if the standard extend method does the right thing.
32        // debug_assert_eq!(
33        //     self.inner.len() % Self::ALIGNMENT,
34        //     0,
35        //     "`AlignedVec` is expected to have well-formed chunks"
36        // );
37        self.inner.extend(&other.inner);
38    }
39
40    /// Consumes `self` and returns the underlying [`Vec`] of bytes.
41    pub fn into_inner(self) -> Vec<u8> {
42        self.inner
43    }
44
45    /// Returns the length in bytes of the prefix.
46    pub fn len(&self) -> usize {
47        self.inner.len()
48    }
49
50    /// Returns `true` if the prefix is empty, `false` otherwise.
51    #[must_use]
52    pub fn is_empty(&self) -> bool {
53        self.len() == 0
54    }
55}
56
57impl AsRef<Vec<u8>> for AlignedVec {
58    fn as_ref(&self) -> &Vec<u8> {
59        &self.inner
60    }
61}
62
63#[cfg(feature = "arbitrary")]
64mod arbitrary_impls {
65    use arbitrary::{Arbitrary, Unstructured};
66    use proptest::arbitrary::any;
67    use proptest::strategy::{BoxedStrategy, Strategy};
68
69    use super::*;
70
71    impl<'a> Arbitrary<'a> for AlignedVec {
72        fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
73            u.arbitrary().map(|v: Vec<u8>| {
74                // we re-allocate so the capacity is also guaranteed to be aligned
75                Self::new(v[..(v.len() / Self::ALIGNMENT) * Self::ALIGNMENT].to_vec())
76            })
77        }
78    }
79
80    impl proptest::arbitrary::Arbitrary for AlignedVec {
81        type Parameters = ();
82        type Strategy = BoxedStrategy<Self>;
83
84        fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
85            any::<Vec<u8>>()
86                .prop_map(|v| {
87                    Self::new(v[..(v.len() / Self::ALIGNMENT) * Self::ALIGNMENT].to_vec())
88                })
89                .boxed()
90        }
91    }
92}