Skip to main content

casper_contract_sdk/collections/
vector.rs

1use crate::{
2    abi::{CasperABI, Declaration, Definition, Definitions, StructField},
3    casper::{self, read_into_vec},
4    prelude::{cmp::Ordering, marker::PhantomData},
5    serializers::borsh::{BorshDeserialize, BorshSerialize},
6};
7
8use casper_executor_wasm_common::keyspace::Keyspace;
9
10#[derive(BorshSerialize, BorshDeserialize, Debug, Clone)]
11#[borsh(crate = "crate::serializers::borsh")]
12pub struct Vector<T> {
13    pub(crate) prefix: String,
14    pub(crate) length: u64,
15    pub(crate) _marker: PhantomData<T>,
16}
17
18impl<T: CasperABI> CasperABI for Vector<T> {
19    fn populate_definitions(_definitions: &mut Definitions) {}
20
21    fn declaration() -> Declaration {
22        format!("Vector<{}>", T::declaration())
23    }
24
25    fn definition() -> Definition {
26        Definition::Struct {
27            items: vec![
28                StructField {
29                    name: "prefix".into(),
30                    decl: String::declaration(),
31                },
32                StructField {
33                    name: "length".into(),
34                    decl: u64::declaration(),
35                },
36            ],
37        }
38    }
39}
40
41impl<T> Vector<T>
42where
43    T: BorshSerialize + BorshDeserialize,
44{
45    /// Constructs a new, empty [`Vector<T>`].
46    ///
47    /// The vector header will not write itself to the GS, even if
48    /// values are pushed onto it later.
49    pub fn new<S: Into<String>>(prefix: S) -> Self {
50        Self {
51            prefix: prefix.into(),
52            length: 0,
53            _marker: PhantomData,
54        }
55    }
56
57    /// Appends an element to the back of a collection.
58    pub fn push(&mut self, value: T) {
59        let prefix_bytes = self.compute_prefix_bytes_for_index(self.length);
60        let prefix = Keyspace::Context(&prefix_bytes);
61        casper::write(prefix, &borsh::to_vec(&value).unwrap()).unwrap();
62        self.length += 1;
63    }
64
65    /// Removes the last element from a vector and returns it, or None if it is empty.
66    pub fn pop(&mut self) -> Option<T> {
67        if self.is_empty() {
68            return None;
69        }
70        self.swap_remove(self.len() - 1)
71    }
72
73    /// Returns true if the slice contains an element with the given value.
74    ///
75    /// This operation is O(n).
76    pub fn contains(&self, value: &T) -> bool
77    where
78        T: PartialEq,
79    {
80        self.iter().any(|v| v == *value)
81    }
82
83    /// Returns an element at index, deserialized.
84    pub fn get(&self, index: u64) -> Option<T> {
85        let prefix = self.compute_prefix_bytes_for_index(index);
86        let item_keyspace = Keyspace::Context(&prefix);
87        read_into_vec(item_keyspace)
88            .unwrap()
89            .map(|vec| borsh::from_slice(&vec).unwrap())
90    }
91
92    /// Returns an iterator over self, with elements deserialized.
93    pub fn iter(&self) -> impl Iterator<Item = T> + '_ {
94        (0..self.length).map(move |i| self.get(i).unwrap())
95    }
96
97    /// Inserts an element at position `index` within the vector, shifting all elements after it to
98    /// the right.
99    pub fn insert(&mut self, index: u64, value: T) {
100        assert!(index <= self.length, "index out of bounds");
101
102        // Shift elements to the right
103        for i in (index..self.length).rev() {
104            if let Some(src_value) = self.get(i) {
105                self.write(i + 1, src_value);
106            }
107        }
108
109        // Write the new value at the specified index
110        self.write(index, value);
111
112        self.length += 1;
113    }
114
115    /// Clears the vector, removing all values from the global state.
116    /// This is potentially expensive, as it requires an iteration over all elements to remove them
117    /// from the global state.
118    pub fn clear(&mut self) {
119        for i in 0..self.length {
120            let prefix_bytes = self.compute_prefix_bytes_for_index(i);
121            let item_keyspace = Keyspace::Context(&prefix_bytes);
122            casper::remove(item_keyspace).unwrap();
123        }
124        self.length = 0;
125    }
126
127    /// Returns the number of elements in the vector, also referred to as its ‘length’.
128    #[inline(always)]
129    pub fn len(&self) -> u64 {
130        self.length
131    }
132
133    /// Returns `true` if the vector contains no elements.
134    #[inline(always)]
135    pub fn is_empty(&self) -> bool {
136        self.length == 0
137    }
138
139    /// Binary searches this vector for a given element. If the vector is not sorted, the returned
140    /// result is unspecified and meaningless.
141    pub fn binary_search(&self, value: &T) -> Result<u64, u64>
142    where
143        T: Ord,
144    {
145        self.binary_search_by(|v| v.cmp(value))
146    }
147
148    /// Binary searches this slice with a comparator function.
149    ///
150    /// The comparator function should return an [Ordering] that indicates whether its argument is
151    /// `Less`, `Equal` or `Greater` the desired target. If the slice is not sorted or if the
152    /// comparator function does not implement an order consistent with the sort order of the
153    /// underlying slice, the returned result is unspecified and meaningless.
154    pub fn binary_search_by<F>(&self, mut f: F) -> Result<u64, u64>
155    where
156        F: FnMut(&T) -> Ordering,
157    {
158        // INVARIANTS:
159        // - 0 <= left <= left + size = right <= self.len()
160        // - f returns Less for everything in self[..left]
161        // - f returns Greater for everything in self[right..]
162        let mut size = self.len();
163        let mut left = 0;
164        let mut right = size;
165        while left < right {
166            let mid = left + size / 2;
167
168            // SAFETY: the while condition means `size` is strictly positive, so
169            // `size/2 < size`. Thus `left + size/2 < left + size`, which
170            // coupled with the `left + size <= self.len()` invariant means
171            // we have `left + size/2 < self.len()`, and this is in-bounds.
172            let cmp = f(&self.get(mid).unwrap());
173
174            // This control flow produces conditional moves, which results in
175            // fewer branches and instructions than if/else or matching on
176            // cmp::Ordering.
177            // This is x86 asm for u8: https://rust.godbolt.org/z/698eYffTx.
178            left = if cmp == Ordering::Less { mid + 1 } else { left };
179            right = if cmp == Ordering::Greater { mid } else { right };
180            if cmp == Ordering::Equal {
181                // SAFETY: same as the `get_unchecked` above
182                assert!(mid < self.len());
183                return Ok(mid);
184            }
185
186            size = right - left;
187        }
188
189        // SAFETY: directly true from the overall invariant.
190        // Note that this is `<=`, unlike the assume in the `Ok` path.
191        assert!(left <= self.len());
192        Err(left)
193    }
194
195    /// Removes the element at the specified index and returns it.
196    ///
197    /// Note: Because this shifts over the remaining elements, it has a
198    /// worst-case performance of O(n). If you don’t need the order of
199    /// elements to be preserved, use `swap_remove` instead.
200    pub fn remove(&mut self, index: u64) -> Option<T> {
201        if index >= self.length {
202            return None;
203        }
204
205        let value_to_remove = self.get(index).unwrap();
206
207        // Shift elements to the left
208        for i in index..(self.length - 1) {
209            if let Some(next_value) = self.get(i + 1) {
210                self.write(i, next_value);
211            }
212        }
213
214        // Remove the last element from storage
215        self.length -= 1;
216        casper::remove(Keyspace::Context(
217            &self.compute_prefix_bytes_for_index(self.length),
218        ))
219        .unwrap();
220
221        Some(value_to_remove)
222    }
223
224    /// Removes the element at the specified index and returns it.
225    ///
226    /// The removed element is replaced by the last element of the vector.
227    /// This does not preserve ordering of the remaining elements, but is O(1).
228    pub fn swap_remove(&mut self, index: u64) -> Option<T> {
229        if index >= self.length {
230            return None;
231        }
232
233        let value_to_remove = self.get(index).unwrap();
234        let last_value = self.get(self.len() - 1).unwrap();
235
236        if index != self.len() - 1 {
237            self.write(index, last_value);
238        }
239
240        self.length -= 1;
241        casper::remove(Keyspace::Context(
242            &self.compute_prefix_bytes_for_index(self.length),
243        ))
244        .unwrap();
245
246        Some(value_to_remove)
247    }
248
249    /// Retains only the elements specified by the predicate.
250    pub fn retain<F>(&mut self, mut f: F)
251    where
252        F: FnMut(&T) -> bool,
253    {
254        let mut i = 0;
255        while i < self.length {
256            if !f(&self.get(i).unwrap()) {
257                self.remove(i).unwrap();
258            } else {
259                i += 1;
260            }
261        }
262    }
263
264    #[inline(always)]
265    fn compute_prefix_bytes_for_index(&self, index: u64) -> Vec<u8> {
266        compute_prefix_bytes_for_index(&self.prefix, index)
267    }
268
269    fn write(&self, index: u64, value: T) {
270        let prefix_bytes = self.compute_prefix_bytes_for_index(index);
271        let prefix = Keyspace::Context(&prefix_bytes);
272        casper::write(prefix, &borsh::to_vec(&value).unwrap()).unwrap();
273    }
274}
275
276fn compute_prefix_bytes_for_index(prefix: &str, index: u64) -> Vec<u8> {
277    let mut prefix_bytes = prefix.as_bytes().to_owned();
278    prefix_bytes.extend(&index.to_le_bytes());
279    prefix_bytes
280}
281
282#[cfg(all(test, feature = "std"))]
283pub(crate) mod tests {
284    use core::ptr::NonNull;
285
286    use self::casper::native::dispatch;
287
288    use super::*;
289
290    const TEST_VEC_PREFIX: &str = "test_vector";
291    type VecU64 = Vector<u64>;
292
293    fn get_vec_elements_from_storage(prefix: &str) -> Vec<u64> {
294        let mut values = Vec::new();
295        for idx in 0..64 {
296            let prefix = compute_prefix_bytes_for_index(prefix, idx);
297            let mut value: [u8; 8] = [0; 8];
298            let result = casper::read(Keyspace::Context(&prefix), |size| {
299                assert_eq!(size, 8);
300                NonNull::new(value.as_mut_ptr())
301            })
302            .unwrap();
303
304            if result.is_some() {
305                values.push(u64::from_le_bytes(value));
306            }
307        }
308        values
309    }
310
311    #[test]
312    fn should_not_panic_with_empty_vec() {
313        dispatch(|| {
314            let mut vec = VecU64::new(TEST_VEC_PREFIX);
315            assert_eq!(vec.len(), 0);
316            assert_eq!(vec.remove(0), None);
317            vec.retain(|_| false);
318            let _ = vec.binary_search(&123);
319            assert_eq!(
320                get_vec_elements_from_storage(TEST_VEC_PREFIX),
321                Vec::<u64>::new()
322            );
323        })
324        .unwrap();
325    }
326
327    #[test]
328    fn should_retain() {
329        dispatch(|| {
330            let mut vec = VecU64::new(TEST_VEC_PREFIX);
331
332            vec.push(1);
333            vec.push(2);
334            vec.push(3);
335            vec.push(4);
336            vec.push(5);
337
338            vec.retain(|v| *v % 2 == 0);
339
340            let vec: Vec<_> = vec.iter().collect();
341            assert_eq!(vec, vec![2, 4]);
342
343            assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![2, 4]);
344        })
345        .unwrap();
346    }
347
348    #[test]
349    fn test_vec() {
350        dispatch(|| {
351            let mut vec = VecU64::new(TEST_VEC_PREFIX);
352
353            assert!(vec.get(0).is_none());
354            vec.push(111);
355            assert_eq!(vec.get(0), Some(111));
356            vec.push(222);
357            assert_eq!(vec.get(1), Some(222));
358
359            vec.insert(0, 42);
360            vec.insert(0, 41);
361            vec.insert(1, 43);
362            vec.insert(5, 333);
363            vec.insert(5, 334);
364            assert_eq!(vec.remove(5), Some(334));
365            assert_eq!(vec.remove(55), None);
366
367            let mut iter = vec.iter();
368            assert_eq!(iter.next(), Some(41));
369            assert_eq!(iter.next(), Some(43));
370            assert_eq!(iter.next(), Some(42));
371            assert_eq!(iter.next(), Some(111));
372            assert_eq!(iter.next(), Some(222));
373            assert_eq!(iter.next(), Some(333));
374            assert_eq!(iter.next(), None);
375
376            {
377                let ser = borsh::to_vec(&vec).unwrap();
378                let deser: Vector<u64> = borsh::from_slice(&ser).unwrap();
379                let mut iter = deser.iter();
380                assert_eq!(iter.next(), Some(41));
381                assert_eq!(iter.next(), Some(43));
382                assert_eq!(iter.next(), Some(42));
383                assert_eq!(iter.next(), Some(111));
384                assert_eq!(iter.next(), Some(222));
385                assert_eq!(iter.next(), Some(333));
386                assert_eq!(iter.next(), None);
387            }
388
389            assert_eq!(
390                get_vec_elements_from_storage(TEST_VEC_PREFIX),
391                vec![41, 43, 42, 111, 222, 333]
392            );
393
394            let vec2 = VecU64::new("test1");
395            assert_eq!(vec2.get(0), None);
396
397            assert_eq!(get_vec_elements_from_storage("test1"), Vec::<u64>::new());
398        })
399        .unwrap();
400    }
401
402    #[test]
403    fn test_pop() {
404        dispatch(|| {
405            let mut vec = VecU64::new(TEST_VEC_PREFIX);
406            assert_eq!(vec.pop(), None);
407            vec.push(1);
408            vec.push(2);
409            assert_eq!(vec.pop(), Some(2));
410            assert_eq!(vec.len(), 1);
411            assert_eq!(vec.pop(), Some(1));
412            assert!(vec.is_empty());
413
414            assert_eq!(
415                get_vec_elements_from_storage(TEST_VEC_PREFIX),
416                Vec::<u64>::new()
417            );
418        })
419        .unwrap();
420    }
421
422    #[test]
423    fn test_contains() {
424        dispatch(|| {
425            let mut vec = VecU64::new(TEST_VEC_PREFIX);
426            vec.push(1);
427            vec.push(2);
428            assert!(vec.contains(&1));
429            assert!(vec.contains(&2));
430            assert!(!vec.contains(&3));
431            vec.remove(0);
432            assert!(!vec.contains(&1));
433            assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![2]);
434        })
435        .unwrap();
436    }
437
438    #[test]
439    fn test_clear() {
440        dispatch(|| {
441            let mut vec = VecU64::new(TEST_VEC_PREFIX);
442            vec.push(1);
443            vec.push(2);
444            vec.clear();
445            assert_eq!(vec.len(), 0);
446            assert!(vec.is_empty());
447            assert_eq!(vec.get(0), None);
448            vec.push(3);
449            assert_eq!(vec.get(0), Some(3));
450
451            assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![3]);
452        })
453        .unwrap();
454    }
455
456    #[test]
457    fn test_binary_search() {
458        dispatch(|| {
459            let mut vec = VecU64::new(TEST_VEC_PREFIX);
460            vec.push(1);
461            vec.push(2);
462            vec.push(3);
463            vec.push(4);
464            vec.push(5);
465            assert_eq!(vec.binary_search(&3), Ok(2));
466            assert_eq!(vec.binary_search(&0), Err(0));
467            assert_eq!(vec.binary_search(&6), Err(5));
468        })
469        .unwrap();
470    }
471
472    #[test]
473    fn test_swap_remove() {
474        dispatch(|| {
475            let mut vec = VecU64::new(TEST_VEC_PREFIX);
476            vec.push(1);
477            vec.push(2);
478            vec.push(3);
479            vec.push(4);
480            assert_eq!(vec.swap_remove(1), Some(2));
481            assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 4, 3]);
482            assert_eq!(vec.swap_remove(2), Some(3));
483            assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 4]);
484
485            assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![1, 4]);
486        })
487        .unwrap();
488    }
489
490    #[test]
491    fn test_insert_at_len() {
492        dispatch(|| {
493            let mut vec = VecU64::new(TEST_VEC_PREFIX);
494            vec.push(1);
495            vec.insert(1, 2);
496            assert_eq!(vec.iter().collect::<Vec<_>>(), vec![1, 2]);
497            assert_eq!(get_vec_elements_from_storage(TEST_VEC_PREFIX), vec![1, 2]);
498        })
499        .unwrap();
500    }
501
502    #[test]
503    fn test_struct_elements() {
504        #[derive(BorshSerialize, BorshDeserialize, PartialEq, Debug)]
505        struct TestStruct {
506            field: u64,
507        }
508
509        dispatch(|| {
510            let mut vec = Vector::new(TEST_VEC_PREFIX);
511            vec.push(TestStruct { field: 1 });
512            vec.push(TestStruct { field: 2 });
513            assert_eq!(vec.get(1), Some(TestStruct { field: 2 }));
514        })
515        .unwrap();
516    }
517
518    #[test]
519    fn test_multiple_operations() {
520        dispatch(|| {
521            let mut vec = VecU64::new(TEST_VEC_PREFIX);
522            assert!(vec.is_empty());
523            vec.push(1);
524            vec.insert(0, 2);
525            vec.push(3);
526            assert_eq!(vec.iter().collect::<Vec<_>>(), vec![2, 1, 3]);
527            assert_eq!(vec.swap_remove(0), Some(2));
528            assert_eq!(vec.iter().collect::<Vec<_>>(), vec![3, 1]);
529            assert_eq!(vec.pop(), Some(1));
530            assert_eq!(vec.get(0), Some(3));
531            vec.clear();
532            assert!(vec.is_empty());
533
534            assert_eq!(
535                get_vec_elements_from_storage(TEST_VEC_PREFIX),
536                Vec::<u64>::new()
537            );
538        })
539        .unwrap();
540    }
541
542    #[test]
543    fn test_remove_invalid_index() {
544        dispatch(|| {
545            let mut vec = VecU64::new(TEST_VEC_PREFIX);
546            vec.push(1);
547            assert_eq!(vec.remove(1), None);
548            assert_eq!(vec.remove(0), Some(1));
549            assert_eq!(vec.remove(0), None);
550        })
551        .unwrap();
552    }
553
554    #[test]
555    #[should_panic(expected = "index out of bounds")]
556    fn test_insert_out_of_bounds() {
557        dispatch(|| {
558            let mut vec = VecU64::new(TEST_VEC_PREFIX);
559            vec.insert(1, 1);
560        })
561        .unwrap();
562    }
563}