multiversx_sc/storage/mappers/
unordered_set_mapper.rs

1use core::marker::PhantomData;
2
3pub use super::vec_mapper::Iter;
4use super::{
5    source::{CurrentStorage, StorageAddress},
6    StorageClearable, StorageMapper, StorageMapperFromAddress, VecMapper,
7};
8use crate::{
9    abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
10    api::StorageMapperApi,
11    codec::{
12        multi_encode_iter_or_handle_err, EncodeErrorHandler, NestedDecode, NestedEncode, TopDecode,
13        TopEncode, TopEncodeMulti, TopEncodeMultiOutput,
14    },
15    storage::StorageKey,
16    storage_clear, storage_set,
17    types::{ManagedAddress, ManagedType, MultiValueEncoded},
18};
19
20const ITEM_INDEX: &[u8] = b".index";
21const NULL_ENTRY: usize = 0;
22
23pub struct UnorderedSetMapper<SA, T, A = CurrentStorage>
24where
25    SA: StorageMapperApi,
26    A: StorageAddress<SA>,
27    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
28{
29    _phantom_api: PhantomData<SA>,
30    address: A,
31    base_key: StorageKey<SA>,
32    vec_mapper: VecMapper<SA, T, A>,
33}
34
35impl<SA, T> StorageMapper<SA> for UnorderedSetMapper<SA, T, CurrentStorage>
36where
37    SA: StorageMapperApi,
38    T: TopEncode + TopDecode + NestedEncode + NestedDecode,
39{
40    fn new(base_key: StorageKey<SA>) -> Self {
41        UnorderedSetMapper {
42            _phantom_api: PhantomData,
43            address: CurrentStorage,
44            base_key: base_key.clone(),
45            vec_mapper: VecMapper::<SA, T>::new(base_key),
46        }
47    }
48}
49
50impl<SA, T> StorageMapperFromAddress<SA> for UnorderedSetMapper<SA, T, ManagedAddress<SA>>
51where
52    SA: StorageMapperApi,
53    T: TopEncode + TopDecode + NestedEncode + NestedDecode,
54{
55    fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
56        UnorderedSetMapper {
57            _phantom_api: PhantomData,
58            address: address.clone(),
59            base_key: base_key.clone(),
60            vec_mapper: VecMapper::new_from_address(address, base_key),
61        }
62    }
63}
64
65impl<SA, T> StorageClearable for UnorderedSetMapper<SA, T, CurrentStorage>
66where
67    SA: StorageMapperApi,
68    T: TopEncode + TopDecode + NestedEncode + NestedDecode,
69{
70    fn clear(&mut self) {
71        for value in self.vec_mapper.iter() {
72            self.clear_index(&value);
73        }
74        self.vec_mapper.clear();
75    }
76}
77
78impl<SA, T, A> UnorderedSetMapper<SA, T, A>
79where
80    SA: StorageMapperApi,
81    A: StorageAddress<SA>,
82    T: TopEncode + TopDecode + NestedEncode + NestedDecode,
83{
84    fn item_index_key(&self, value: &T) -> StorageKey<SA> {
85        let mut item_key = self.base_key.clone();
86        item_key.append_bytes(ITEM_INDEX);
87        item_key.append_item(value);
88        item_key
89    }
90
91    /// Gets the item's index at the given address' mapper.
92    /// Returns `0` if the item is not in the list.
93    pub fn get_index(&self, value: &T) -> usize {
94        self.address
95            .address_storage_get(self.item_index_key(value).as_ref())
96    }
97
98    /// Get item at index from the given address.
99    /// Index must be valid (1 <= index <= count).
100    pub fn get_by_index(&self, index: usize) -> T {
101        self.vec_mapper.get(index)
102    }
103
104    /// Returns `true` if the set contains no elements.
105    pub fn is_empty(&self) -> bool {
106        self.vec_mapper.is_empty()
107    }
108
109    /// Returns the number of elements in the set.
110    pub fn len(&self) -> usize {
111        self.vec_mapper.len()
112    }
113
114    /// Returns `true` if the set contains a value.
115    pub fn contains(&self, value: &T) -> bool {
116        self.get_index(value) != NULL_ENTRY
117    }
118
119    /// An iterator visiting all elements in arbitrary order.
120    /// The iterator element type is `&'a T`.
121    pub fn iter(&self) -> Iter<'_, SA, T, A> {
122        self.vec_mapper.iter()
123    }
124}
125
126impl<SA, T> UnorderedSetMapper<SA, T, CurrentStorage>
127where
128    SA: StorageMapperApi,
129    T: TopEncode + TopDecode + NestedEncode + NestedDecode,
130{
131    fn set_index(&self, value: &T, index: usize) {
132        storage_set(self.item_index_key(value).as_ref(), &index);
133    }
134
135    fn clear_index(&self, value: &T) {
136        storage_clear(self.item_index_key(value).as_ref());
137    }
138
139    /// Adds a value to the set.
140    ///
141    /// If the set did not have this value present, `true` is returned.
142    ///
143    /// If the set did have this value present, `false` is returned.
144    pub fn insert(&mut self, value: T) -> bool {
145        if self.contains(&value) {
146            return false;
147        }
148        self.vec_mapper.push(&value);
149        self.set_index(&value, self.len());
150        true
151    }
152
153    /// Removes a value from the set. Returns whether the value was
154    /// present in the set.
155    pub fn swap_remove(&mut self, value: &T) -> bool {
156        let index = self.get_index(value);
157        if index == NULL_ENTRY {
158            return false;
159        }
160        if let Some(last_item) = self.vec_mapper.swap_remove_and_get_old_last(index) {
161            self.set_index(&last_item, index);
162        }
163        self.clear_index(value);
164        true
165    }
166
167    /// Exchanges the indexes of two values. Returns whether the operation was
168    /// successful.
169    pub fn swap_indexes(&mut self, index1: usize, index2: usize) -> bool {
170        if index1 == NULL_ENTRY || index2 == NULL_ENTRY {
171            return false;
172        }
173        let value1 = self.get_by_index(index1);
174        let value2 = self.get_by_index(index2);
175        self.vec_mapper.set(index2, &value1);
176        self.vec_mapper.set(index1, &value2);
177        self.set_index(&value1, index2);
178        self.set_index(&value2, index1);
179        true
180    }
181}
182
183impl<'a, SA, T, A> IntoIterator for &'a UnorderedSetMapper<SA, T, A>
184where
185    SA: StorageMapperApi,
186    A: StorageAddress<SA>,
187    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
188{
189    type Item = T;
190
191    type IntoIter = Iter<'a, SA, T, A>;
192
193    fn into_iter(self) -> Self::IntoIter {
194        self.iter()
195    }
196}
197
198impl<SA, T> Extend<T> for UnorderedSetMapper<SA, T>
199where
200    SA: StorageMapperApi,
201    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
202{
203    fn extend<I>(&mut self, iter: I)
204    where
205        I: IntoIterator<Item = T>,
206    {
207        for item in iter {
208            self.insert(item);
209        }
210    }
211}
212
213/// Behaves like a MultiResultVec when an endpoint result.
214impl<SA, T> TopEncodeMulti for UnorderedSetMapper<SA, T>
215where
216    SA: StorageMapperApi,
217    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
218{
219    fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
220    where
221        O: TopEncodeMultiOutput,
222        H: EncodeErrorHandler,
223    {
224        multi_encode_iter_or_handle_err(self.iter(), output, h)
225    }
226}
227
228impl<SA, T> TypeAbiFrom<UnorderedSetMapper<SA, T>> for MultiValueEncoded<SA, T>
229where
230    SA: StorageMapperApi,
231    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
232{
233}
234
235impl<SA, T> TypeAbiFrom<Self> for UnorderedSetMapper<SA, T>
236where
237    SA: StorageMapperApi,
238    T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
239{
240}
241
242/// Behaves like a MultiResultVec when an endpoint result.
243impl<SA, T> TypeAbi for UnorderedSetMapper<SA, T>
244where
245    SA: StorageMapperApi,
246    T: TopEncode + TopDecode + NestedEncode + NestedDecode + TypeAbi,
247{
248    type Unmanaged = Self;
249
250    fn type_name() -> TypeName {
251        crate::abi::type_name_variadic::<T>()
252    }
253
254    fn type_name_rust() -> TypeName {
255        crate::abi::type_name_multi_value_encoded::<T>()
256    }
257
258    fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
259        T::provide_type_descriptions(accumulator);
260    }
261
262    fn is_variadic() -> bool {
263        true
264    }
265}