unc_sdk/collections/
vector.rs

1//! A vector implemented on a trie. Unlike standard vector does not support insertion and removal
2//! of an element results in the last element being placed in the empty position.
3use core::ops::Range;
4use std::iter::FusedIterator;
5use std::marker::PhantomData;
6
7use borsh::{to_vec, BorshDeserialize, BorshSerialize};
8use unc_sdk_macros::unc;
9
10use crate::collections::append_slice;
11use crate::{env, IntoStorageKey};
12
13const ERR_INCONSISTENT_STATE: &str = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?";
14const ERR_ELEMENT_DESERIALIZATION: &str = "Cannot deserialize element";
15const ERR_ELEMENT_SERIALIZATION: &str = "Cannot serialize element";
16const ERR_INDEX_OUT_OF_BOUNDS: &str = "Index out of bounds";
17
18fn expect_consistent_state<T>(val: Option<T>) -> T {
19    val.unwrap_or_else(|| env::panic_str(ERR_INCONSISTENT_STATE))
20}
21
22/// An iterable implementation of vector that stores its content on the trie.
23/// Uses the following map: index -> element.
24#[unc(inside_uncsdk)]
25pub struct Vector<T> {
26    len: u64,
27    prefix: Vec<u8>,
28    #[borsh(skip)]
29    el: PhantomData<T>,
30}
31
32impl<T> Vector<T> {
33    /// Returns the number of elements in the vector, also referred to as its size.
34    pub fn len(&self) -> u64 {
35        self.len
36    }
37
38    /// Returns `true` if the vector contains no elements.
39    pub fn is_empty(&self) -> bool {
40        self.len == 0
41    }
42
43    /// Create new vector with zero elements. Use `id` as a unique identifier on the trie.
44    ///
45    /// # Examples
46    ///
47    /// ```
48    /// use unc_sdk::collections::Vector;
49    /// let mut set: Vector<u32> = Vector::new(b"m");
50    /// ```
51    pub fn new<S>(prefix: S) -> Self
52    where
53        S: IntoStorageKey,
54    {
55        Self { len: 0, prefix: prefix.into_storage_key(), el: PhantomData }
56    }
57
58    /// Helper utility to be able to easily migrate to the new [`Vector`] implementation.
59    ///
60    /// This new [`Vector`]'s API matches the Rust [`Vec`] API more closely and has a caching
61    /// layer to avoid reading/writing redundant times to storage.
62    ///
63    /// [`Vector`]: crate::store::Vector
64    #[cfg(feature = "unstable")]
65    pub fn to_v2(&self) -> crate::store::Vector<T>
66    where
67        T: BorshSerialize,
68    {
69        crate::store::Vector {
70            // Length cannot feasibly exceed u32::MAX, but checked conversion anyway.
71            len: self.len.try_into().unwrap(),
72            values: crate::store::IndexMap::new(self.prefix.as_slice()),
73        }
74    }
75
76    fn index_to_lookup_key(&self, index: u64) -> Vec<u8> {
77        append_slice(&self.prefix, &index.to_le_bytes()[..])
78    }
79
80    /// Returns the serialized element by index or `None` if it is not present.
81    pub fn get_raw(&self, index: u64) -> Option<Vec<u8>> {
82        if index >= self.len {
83            return None;
84        }
85        let lookup_key = self.index_to_lookup_key(index);
86        Some(expect_consistent_state(env::storage_read(&lookup_key)))
87    }
88
89    /// Removes an element from the vector and returns it in serialized form.
90    /// The removed element is replaced by the last element of the vector.
91    /// Does not preserve ordering, but is `O(1)`.
92    ///
93    /// # Panics
94    ///
95    /// Panics if `index` is out of bounds.
96    pub fn swap_remove_raw(&mut self, index: u64) -> Vec<u8> {
97        if index >= self.len {
98            env::panic_str(ERR_INDEX_OUT_OF_BOUNDS)
99        } else if index + 1 == self.len {
100            expect_consistent_state(self.pop_raw())
101        } else {
102            let lookup_key = self.index_to_lookup_key(index);
103            let raw_last_value = self.pop_raw().expect("checked `index < len` above, so `len > 0`");
104            if env::storage_write(&lookup_key, &raw_last_value) {
105                expect_consistent_state(env::storage_get_evicted())
106            } else {
107                env::panic_str(ERR_INCONSISTENT_STATE)
108            }
109        }
110    }
111
112    /// Appends a serialized element to the back of the collection.
113    pub fn push_raw(&mut self, raw_element: &[u8]) {
114        let lookup_key = self.index_to_lookup_key(self.len);
115        self.len += 1;
116        env::storage_write(&lookup_key, raw_element);
117    }
118
119    /// Removes the last element from a vector and returns it without deserializing, or `None` if it is empty.
120    pub fn pop_raw(&mut self) -> Option<Vec<u8>> {
121        if self.is_empty() {
122            None
123        } else {
124            let last_index = self.len - 1;
125            let last_lookup_key = self.index_to_lookup_key(last_index);
126
127            self.len -= 1;
128            let raw_last_value = if env::storage_remove(&last_lookup_key) {
129                expect_consistent_state(env::storage_get_evicted())
130            } else {
131                env::panic_str(ERR_INCONSISTENT_STATE)
132            };
133            Some(raw_last_value)
134        }
135    }
136
137    /// Inserts a serialized element at `index`, returns a serialized evicted element.
138    ///
139    /// # Panics
140    ///
141    /// If `index` is out of bounds.
142    pub fn replace_raw(&mut self, index: u64, raw_element: &[u8]) -> Vec<u8> {
143        if index >= self.len {
144            env::panic_str(ERR_INDEX_OUT_OF_BOUNDS)
145        } else {
146            let lookup_key = self.index_to_lookup_key(index);
147            if env::storage_write(&lookup_key, raw_element) {
148                expect_consistent_state(env::storage_get_evicted())
149            } else {
150                env::panic_str(ERR_INCONSISTENT_STATE);
151            }
152        }
153    }
154
155    /// Iterate over raw serialized elements.
156    pub fn iter_raw(&self) -> RawIter<T> {
157        RawIter::new(self)
158    }
159
160    /// Extends vector from the given collection of serialized elements.
161    pub fn extend_raw<IT: IntoIterator<Item = Vec<u8>>>(&mut self, iter: IT) {
162        for el in iter {
163            self.push_raw(&el)
164        }
165    }
166}
167
168impl<T> Vector<T> {
169    /// Removes all elements from the collection.
170    pub fn clear(&mut self) {
171        for i in 0..self.len {
172            let lookup_key = self.index_to_lookup_key(i);
173            env::storage_remove(&lookup_key);
174        }
175        self.len = 0;
176    }
177}
178
179impl<T> Vector<T>
180where
181    T: BorshSerialize,
182{
183    fn serialize_element(element: &T) -> Vec<u8> {
184        to_vec(element).unwrap_or_else(|_| env::panic_str(ERR_ELEMENT_SERIALIZATION))
185    }
186
187    /// Appends an element to the back of the collection.
188    pub fn push(&mut self, element: &T) {
189        let raw_element = Self::serialize_element(element);
190        self.push_raw(&raw_element);
191    }
192
193    /// Extends vector from the given collection.
194    pub fn extend<IT: IntoIterator<Item = T>>(&mut self, iter: IT) {
195        for el in iter {
196            self.push(&el)
197        }
198    }
199}
200
201impl<T> Vector<T>
202where
203    T: BorshDeserialize,
204{
205    fn deserialize_element(raw_element: &[u8]) -> T {
206        T::try_from_slice(raw_element)
207            .unwrap_or_else(|_| env::panic_str(ERR_ELEMENT_DESERIALIZATION))
208    }
209
210    /// Returns the element by index or `None` if it is not present.
211    pub fn get(&self, index: u64) -> Option<T> {
212        self.get_raw(index).map(|x| Self::deserialize_element(&x))
213    }
214
215    /// Removes an element from the vector and returns it.
216    /// The removed element is replaced by the last element of the vector.
217    /// Does not preserve ordering, but is `O(1)`.
218    ///
219    /// # Panics
220    ///
221    /// Panics if `index` is out of bounds.
222    pub fn swap_remove(&mut self, index: u64) -> T {
223        let raw_evicted = self.swap_remove_raw(index);
224        Self::deserialize_element(&raw_evicted)
225    }
226
227    /// Removes the last element from a vector and returns it, or `None` if it is empty.
228    pub fn pop(&mut self) -> Option<T> {
229        self.pop_raw().map(|x| Self::deserialize_element(&x))
230    }
231
232    /// Iterate over deserialized elements.
233    pub fn iter(&self) -> Iter<T> {
234        Iter::new(self)
235    }
236
237    pub fn to_vec(&self) -> Vec<T> {
238        self.iter().collect()
239    }
240}
241
242impl<T> Vector<T>
243where
244    T: BorshSerialize + BorshDeserialize,
245{
246    /// Inserts a element at `index`, returns an evicted element.
247    ///
248    /// # Panics
249    ///
250    /// If `index` is out of bounds.
251    pub fn replace(&mut self, index: u64, element: &T) -> T {
252        let raw_element = Self::serialize_element(element);
253        Self::deserialize_element(&self.replace_raw(index, &raw_element))
254    }
255}
256
257#[cfg(feature = "expensive-debug")]
258impl<T: std::fmt::Debug + BorshDeserialize> std::fmt::Debug for Vector<T> {
259    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
260        self.to_vec().fmt(f)
261    }
262}
263
264#[cfg(not(feature = "expensive-debug"))]
265impl<T: std::fmt::Debug + BorshDeserialize> std::fmt::Debug for Vector<T> {
266    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
267        f.debug_struct("Vector").field("len", &self.len).field("prefix", &self.prefix).finish()
268    }
269}
270
271/// An iterator over raw serialized bytes of each element in the [`Vector`].
272pub struct RawIter<'a, T> {
273    vec: &'a Vector<T>,
274    range: Range<u64>,
275}
276
277impl<'a, T> RawIter<'a, T> {
278    fn new(vec: &'a Vector<T>) -> Self {
279        Self { vec, range: Range { start: 0, end: vec.len() } }
280    }
281
282    /// Returns number of elements left to iterate.
283    fn remaining(&self) -> usize {
284        (self.range.end - self.range.start) as usize
285    }
286}
287
288impl<'a, T> Iterator for RawIter<'a, T> {
289    type Item = Vec<u8>;
290
291    fn next(&mut self) -> Option<Self::Item> {
292        <Self as Iterator>::nth(self, 0)
293    }
294
295    fn size_hint(&self) -> (usize, Option<usize>) {
296        let remaining = self.remaining();
297        (remaining, Some(remaining))
298    }
299
300    fn count(self) -> usize {
301        self.remaining()
302    }
303
304    fn nth(&mut self, n: usize) -> Option<Self::Item> {
305        let idx = self.range.nth(n)?;
306        self.vec.get_raw(idx)
307    }
308}
309
310impl<'a, T> ExactSizeIterator for RawIter<'a, T> {}
311impl<'a, T> FusedIterator for RawIter<'a, T> {}
312
313impl<'a, T> DoubleEndedIterator for RawIter<'a, T> {
314    fn next_back(&mut self) -> Option<Self::Item> {
315        <Self as DoubleEndedIterator>::nth_back(self, 0)
316    }
317
318    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
319        let idx = self.range.nth_back(n)?;
320        self.vec.get_raw(idx)
321    }
322}
323
324/// An iterator over each element deserialized in the [`Vector`].
325pub struct Iter<'a, T> {
326    inner: RawIter<'a, T>,
327}
328
329impl<'a, T> Iter<'a, T> {
330    fn new(vec: &'a Vector<T>) -> Self {
331        Self { inner: RawIter::new(vec) }
332    }
333}
334
335impl<'a, T> Iterator for Iter<'a, T>
336where
337    T: BorshDeserialize,
338{
339    type Item = T;
340
341    fn next(&mut self) -> Option<Self::Item> {
342        <Self as Iterator>::nth(self, 0)
343    }
344
345    fn size_hint(&self) -> (usize, Option<usize>) {
346        let remaining = self.inner.remaining();
347        (remaining, Some(remaining))
348    }
349
350    fn count(self) -> usize {
351        self.inner.remaining()
352    }
353
354    fn nth(&mut self, n: usize) -> Option<Self::Item> {
355        self.inner.nth(n).map(|raw_element| Vector::deserialize_element(&raw_element))
356    }
357}
358
359impl<'a, T> ExactSizeIterator for Iter<'a, T> where T: BorshDeserialize {}
360impl<'a, T> FusedIterator for Iter<'a, T> where T: BorshDeserialize {}
361
362impl<'a, T> DoubleEndedIterator for Iter<'a, T>
363where
364    T: BorshDeserialize,
365{
366    fn next_back(&mut self) -> Option<Self::Item> {
367        <Self as DoubleEndedIterator>::nth_back(self, 0)
368    }
369
370    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
371        self.inner.nth_back(n).map(|raw_element| Vector::deserialize_element(&raw_element))
372    }
373}
374
375#[cfg(not(target_arch = "wasm32"))]
376#[cfg(test)]
377mod tests {
378    use borsh::BorshDeserialize;
379    use rand::{Rng, SeedableRng};
380
381    use crate::collections::Vector;
382
383    #[test]
384    fn test_push_pop() {
385        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0);
386        let mut vec = Vector::new(b"v".to_vec());
387        let mut baseline = vec![];
388        for _ in 0..500 {
389            let value = rng.gen::<u64>();
390            vec.push(&value);
391            baseline.push(value);
392        }
393        let actual = vec.to_vec();
394        assert_eq!(actual, baseline);
395        for _ in 0..1001 {
396            assert_eq!(baseline.pop(), vec.pop());
397        }
398    }
399
400    #[test]
401    pub fn test_replace() {
402        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(1);
403        let mut vec = Vector::new(b"v".to_vec());
404        let mut baseline = vec![];
405        for _ in 0..500 {
406            let value = rng.gen::<u64>();
407            vec.push(&value);
408            baseline.push(value);
409        }
410        for _ in 0..500 {
411            let index = rng.gen::<u64>() % vec.len();
412            let value = rng.gen::<u64>();
413            let old_value0 = vec.get(index).unwrap();
414            let old_value1 = vec.replace(index, &value);
415            let old_value2 = baseline[index as usize];
416            assert_eq!(old_value0, old_value1);
417            assert_eq!(old_value0, old_value2);
418            *baseline.get_mut(index as usize).unwrap() = value;
419        }
420        let actual = vec.to_vec();
421        assert_eq!(actual, baseline);
422    }
423
424    #[test]
425    pub fn test_swap_remove() {
426        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(2);
427        let mut vec = Vector::new(b"v".to_vec());
428        let mut baseline = vec![];
429        for _ in 0..500 {
430            let value = rng.gen::<u64>();
431            vec.push(&value);
432            baseline.push(value);
433        }
434        for _ in 0..500 {
435            let index = rng.gen::<u64>() % vec.len();
436            let old_value0 = vec.get(index).unwrap();
437            let old_value1 = vec.swap_remove(index);
438            let old_value2 = baseline[index as usize];
439            let last_index = baseline.len() - 1;
440            baseline.swap(index as usize, last_index);
441            baseline.pop();
442            assert_eq!(old_value0, old_value1);
443            assert_eq!(old_value0, old_value2);
444        }
445        let actual = vec.to_vec();
446        assert_eq!(actual, baseline);
447    }
448
449    #[test]
450    pub fn test_clear() {
451        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(3);
452        let mut vec = Vector::new(b"v".to_vec());
453        for _ in 0..100 {
454            for _ in 0..(rng.gen::<u64>() % 20 + 1) {
455                let value = rng.gen::<u64>();
456                vec.push(&value);
457            }
458            assert!(!vec.is_empty());
459            vec.clear();
460            assert!(vec.is_empty());
461        }
462    }
463
464    #[test]
465    pub fn test_extend() {
466        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(0);
467        let mut vec = Vector::new(b"v".to_vec());
468        let mut baseline = vec![];
469        for _ in 0..100 {
470            let value = rng.gen::<u64>();
471            vec.push(&value);
472            baseline.push(value);
473        }
474
475        for _ in 0..100 {
476            let mut tmp = vec![];
477            for _ in 0..=(rng.gen::<u64>() % 20 + 1) {
478                let value = rng.gen::<u64>();
479                tmp.push(value);
480            }
481            baseline.extend(tmp.clone());
482            vec.extend(tmp.clone());
483        }
484        let actual = vec.to_vec();
485        assert_eq!(actual, baseline);
486    }
487
488    #[test]
489    fn test_debug() {
490        let mut rng = rand_xorshift::XorShiftRng::seed_from_u64(4);
491        let prefix = b"v".to_vec();
492        let mut vec = Vector::new(prefix.clone());
493        let mut baseline = vec![];
494        for _ in 0..10 {
495            let value = rng.gen::<u64>();
496            vec.push(&value);
497            baseline.push(value);
498        }
499        let actual = vec.to_vec();
500        assert_eq!(actual, baseline);
501        for _ in 0..5 {
502            assert_eq!(baseline.pop(), vec.pop());
503        }
504        if cfg!(feature = "expensive-debug") {
505            assert_eq!(format!("{:#?}", vec), format!("{:#?}", baseline));
506        } else {
507            assert_eq!(
508                format!("{:?}", vec),
509                format!("Vector {{ len: 5, prefix: {:?} }}", vec.prefix)
510            );
511        }
512
513        #[derive(Debug, BorshDeserialize)]
514        #[allow(dead_code)]
515        struct WithoutBorshSerialize(u64);
516
517        let deserialize_only_vec =
518            Vector::<WithoutBorshSerialize> { len: vec.len(), prefix, el: Default::default() };
519        let baseline: Vec<_> = baseline.into_iter().map(WithoutBorshSerialize).collect();
520        if cfg!(feature = "expensive-debug") {
521            assert_eq!(format!("{:#?}", deserialize_only_vec), format!("{:#?}", baseline));
522        } else {
523            assert_eq!(
524                format!("{:?}", deserialize_only_vec),
525                format!("Vector {{ len: 5, prefix: {:?} }}", deserialize_only_vec.prefix)
526            );
527        }
528    }
529
530    #[test]
531    pub fn iterator_checks() {
532        let mut vec = Vector::new(b"v");
533        let mut baseline = vec![];
534        for i in 0..10 {
535            vec.push(&i);
536            baseline.push(i);
537        }
538
539        let mut vec_iter = vec.iter();
540        let mut bl_iter = baseline.iter();
541        assert_eq!(vec_iter.next(), bl_iter.next().copied());
542        assert_eq!(vec_iter.next_back(), bl_iter.next_back().copied());
543        assert_eq!(vec_iter.nth(3), bl_iter.nth(3).copied());
544        assert_eq!(vec_iter.nth_back(2), bl_iter.nth_back(2).copied());
545
546        // Check to make sure indexing overflow is handled correctly
547        assert!(vec_iter.nth(5).is_none());
548        assert!(bl_iter.nth(5).is_none());
549
550        assert!(vec_iter.next().is_none());
551        assert!(bl_iter.next().is_none());
552
553        // Count check
554        assert_eq!(vec.iter().count(), baseline.len());
555    }
556}