pchain_sdk/collections/
vector.rs

1/*
2    Copyright © 2023, ParallelChain Lab 
3    Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
4*/
5
6//! Defines the collection struct [Vector].
7
8use std::cell::RefCell;
9use std::collections::BTreeMap;
10use std::ops::Index;
11use std::ops::IndexMut;
12use borsh::{BorshSerialize, BorshDeserialize};
13
14use crate::storage;
15use crate::{Storable, StoragePath};
16
17/// [Vector] is a contract-level data structure to provide abstraction by utilizing Get and Set operations associated with Contract Storage.
18/// It supports lazy read/write on elements that can be iterated.
19/// 
20/// ## Vector
21/// 
22/// `Vector` can be a Contract Field defined in the contract struct. E.g.
23///
24/// ```rust
25/// #[contract]
26/// struct MyContract {
27///     vector: Vector<u64> // this vector declares to store u64 integers to world state
28/// }
29/// ```
30///
31/// The value can be obtained by indexing operations. E.g.
32/// ```rust
33/// let data = self.vector[0]; // can be either a read from cached value or a read from world state 
34/// self.vector[0] = data; // No actual write to world state at this line
35/// ```
36///
37/// ### Iteration
38///
39/// Iteration may involve read from world state. E.g.
40/// ```rust
41/// // Iterate over immutable reference to the data
42/// self.vector.iter().for_each(|item|{
43///     ...
44/// });
45/// 
46/// // Iterate over mutable reference to the data
47/// self.vector.iter_mut().for_each(|item|{
48///     //...
49/// });
50/// ```
51/// 
52/// ### Storage Model
53/// 
54/// Account Storage State Key Format:
55/// 
56/// |Component|Key|Value (Data type) |
57/// |:---|:---|:---|
58/// |Length|P, 0| u32 |
59/// |Element|P, 1, I| user defined data (borsh-serialized)|
60/// - P: parent key
61/// - I: little endian bytes of index (u32)
62/// 
63/// ### Lazy Write
64/// 
65/// Trait `Storage` implements the `Vector` so that data can be saved to world state
66/// 1. after execution of action method with receiver `&mut self`; or
67/// 2. explicitly calling the setter `Self::set()`.
68#[derive(Clone, Default)]
69pub struct Vector<T> where T: Storable {
70    write_set: RefCell<BTreeMap<usize, T>>,
71    read_set: RefCell<BTreeMap<usize, T>>,
72    /// runtime length of the vector
73    length: usize,
74    /// The key of contract field, which is used to formulate the key for elements.
75    parent_key: Vec<u8>
76}
77
78/// Iterator created by `Vector::iter()`
79pub struct VectorIter<'a, T> where T: Storable + Clone {
80    vector: &'a Vector<T>,
81    idx: usize,
82}
83
84/// Mutable Iterator created by `Vector::iter_mut()`
85pub struct VectorIterMut<'a, T> where T: Storable + Clone {
86    vector: &'a mut Vector<T>,
87    idx: usize,
88}
89
90impl<'a, T> Vector<T> where T: Storable + Clone {
91    pub fn new() -> Self {
92        Self {
93            write_set: RefCell::new(BTreeMap::new()),
94            read_set: RefCell::new(BTreeMap::new()),
95            length:0,
96            parent_key: vec![]
97        }
98    }
99
100    /// length of the vector
101    pub fn len(&self) -> usize {
102        self.length
103    }
104
105    /// check if it is empty vector 
106    pub fn is_empty(&self) -> bool {
107        self.len() == 0
108    }
109
110    /// `push` adds item to the last of vector, which does not immediately take effect in Contract Storage.
111    pub fn push(&mut self, value: &T) {
112        self.write_set.get_mut().insert(self.length, value.clone());
113        self.length += 1;
114    }
115
116    /// `pop` removes the last item in the vector, which does not immediately take effect in Contract Storage. 
117    /// Pop doest not return the poped item for saving reading cost.
118    pub fn pop(&mut self) {
119        if self.length > 0 {
120            self.length -= 1;
121            self.write_set.get_mut().remove(&(self.length));
122            self.read_set.get_mut().remove(&(self.length)); 
123        }
124    }
125
126    fn get(&self, idx: usize) -> &T {
127        self.get_mut(idx)
128    }
129
130    /// get mutable reference from read_set
131    #[allow(clippy::mut_from_ref)]
132    fn get_mut(&self, idx: usize) -> &mut T {
133        if idx >= self.length {
134            panic!()
135        }
136
137        // get from write set
138        if let Some(value) = self.write_set.borrow_mut().get_mut(&idx) {
139            // cache to read set and return reference of it
140            return self.write_to_read_set(idx, value.clone())
141        }
142        
143        // if not in write set, get from read set
144        if let Some(value) = self.read_set.borrow_mut().get_mut(&idx) {
145            return unsafe {
146                let r = value as * const T;
147                &mut *(r as *mut T) 
148            }
149        }
150
151        // parent key absent, cannot query world state data
152        if self.parent_key.is_empty() { panic!() }
153
154        // if not in read set, read from storage
155        let value = T::__load_storage(&StoragePath::new().append(Self::wskey_index(self.parent_key.clone(), idx)));
156
157        // cache to read set and return reference of it
158        self.write_to_read_set(idx, value)
159    }
160
161    #[allow(clippy::mut_from_ref)]
162    fn write_to_read_set(&self, idx: usize, value: T) -> &mut T {
163        let mut read_set = self.read_set.borrow_mut();
164        read_set.insert(idx, value);
165
166        match read_set.get_mut(&idx) {
167            Some(value) => {
168                unsafe{
169                    let r = value as * const T;
170                    &mut *(r as *mut T) 
171                }
172            }
173            None => unreachable!()
174        }
175    }
176
177    fn write_to_write_set(&mut self, idx: usize, value: T) -> &mut T {
178        let mut write_set = self.write_set.borrow_mut();
179        write_set.insert(idx, value);
180
181        match write_set.get_mut(&idx) {
182            Some(value) => {
183                unsafe{
184                    let r = value as * const T;
185                    &mut *(r as *mut T) 
186                }
187            }
188            None => unreachable!()
189        }
190    }
191
192    /// `iter` returns `VectorIter` which implements Iterator
193    pub fn iter(&'a self) -> VectorIter<'a, T> {
194        VectorIter { vector: self, idx: 0 }
195    }
196
197    /// `iter_mut` returns `VectorIterMut` which implements Iterator
198    pub fn iter_mut(&'a mut self) -> VectorIterMut<'a, T> {
199        VectorIterMut { vector: self, idx: 0 }
200    }
201
202    /// The length of the vector, which is the data stored in world state.
203    fn len_in_ws(parent_key: Vec<u8>) -> usize {
204        storage::get(Self::wskey_len(parent_key).as_slice()).map_or(0, |bytes|{
205            usize::deserialize(&mut bytes.as_slice()).map_or(0, std::convert::identity)
206        })
207    }
208
209    /// Account Storage State Key for saving the length of vector.
210    fn wskey_len(parent_key: Vec<u8>) -> Vec<u8> {
211        [
212            parent_key,
213            [0u8].to_vec()
214        ].concat()
215    }
216    
217    /// Account Storage State Key for saving the value of vector element, keyed by index of the element.
218    fn wskey_index(parent_key: Vec<u8>, idx: usize) -> Vec<u8> {
219        [
220            parent_key, 
221            [1u8].to_vec(), 
222            (idx as u32).to_le_bytes().to_vec()
223        ].concat()
224    }
225}
226
227impl<'a, T> Iterator for VectorIter<'a, T> where T: Storable + Clone {
228    type Item = &'a T;
229
230    fn next(&mut self) -> Option<Self::Item> {
231        if self.idx >= self.vector.len() {
232            return None
233        }
234        let value = self.vector.get(self.idx);
235        self.idx += 1;
236        Some(value)
237    }
238}
239
240impl<'a, T> Iterator for VectorIterMut<'a, T> where T: Storable + Clone {
241    type Item = &'a mut T;
242
243    fn next(&mut self) -> Option<Self::Item> {
244        if self.idx >= self.vector.len() {
245            return None
246        };
247        let value = self.vector.get(self.idx);
248        let ret = self.vector.write_to_write_set(self.idx, value.clone());
249        self.idx += 1;
250        Some(unsafe{
251            let r = ret as * const T;
252            &mut *(r as *mut T) 
253        })
254    }
255}
256
257impl<T> Index<usize> for Vector<T> where T: Storable + Clone {
258    type Output = T;
259
260    fn index(&self, index: usize) -> &Self::Output {
261        self.get(index)
262    }
263}
264
265impl<T> IndexMut<usize> for Vector<T> where T: Storable + Clone {
266    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
267        let value = self.get(index);
268        // return reference to write set
269        self.write_to_write_set(index, value.clone())
270    }
271}
272
273impl<T> Storable for Vector<T> where T: Storable + Clone {
274    fn __load_storage(field: &StoragePath) -> Self {
275        let parent_key = field.get_path().to_vec();
276        Self {
277            write_set: RefCell::new(BTreeMap::new()),
278            read_set: RefCell::new(BTreeMap::new()),
279            length: Self::len_in_ws(parent_key.clone()),
280            parent_key,
281        }
282    }
283
284    fn __save_storage(&mut self, field :&StoragePath) {
285        let field_path = field.get_path().to_vec();
286        // set parent key here for the cases that Vector is instantiated first and then assigned to field in contract struct
287        if self.parent_key != field_path {
288            self.parent_key = field_path;
289        }
290
291        // update new length
292        if self.length != Self::len_in_ws(self.parent_key.clone()) {
293            storage::set(&Self::wskey_len(self.parent_key.clone()), self.length.try_to_vec().unwrap().as_slice());
294        }
295
296        // save changes to world state
297        let mut write_set = self.write_set.borrow_mut();
298        write_set.iter_mut().for_each(|(idx, v)|{
299            v.__save_storage(&StoragePath::new().append(Self::wskey_index(self.parent_key.clone(), *idx)));
300        });
301    }
302}