multiversx_sc/storage/mappers/
set_mapper.rs1use core::marker::PhantomData;
2
3pub use super::queue_mapper::Iter;
4use super::{QueueMapper, StorageClearable, StorageMapper, StorageMapperFromAddress};
5use crate::{
6 abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
7 api::StorageMapperApi,
8 codec::{
9 self, EncodeErrorHandler, NestedDecode, NestedEncode, TopDecode, TopEncode, TopEncodeMulti,
10 TopEncodeMultiOutput, multi_encode_iter_or_handle_err,
11 },
12 storage::{
13 StorageKey,
14 mappers::source::{CurrentStorage, StorageAddress},
15 storage_set,
16 },
17 types::{ManagedAddress, ManagedType, MultiValueEncoded},
18};
19
20const NULL_ENTRY: u32 = 0;
21const NODE_ID_IDENTIFIER: &[u8] = b".node_id";
22
23pub struct SetMapper<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 queue_mapper: QueueMapper<SA, T, A>,
33}
34
35impl<SA, T> StorageMapper<SA> for SetMapper<SA, T, CurrentStorage>
36where
37 SA: StorageMapperApi,
38 T: TopEncode + TopDecode + NestedEncode + NestedDecode,
39{
40 fn new(base_key: StorageKey<SA>) -> Self {
41 SetMapper {
42 _phantom_api: PhantomData,
43 address: CurrentStorage,
44 base_key: base_key.clone(),
45 queue_mapper: QueueMapper::new(base_key),
46 }
47 }
48}
49
50impl<SA, T> StorageClearable for SetMapper<SA, T, CurrentStorage>
51where
52 SA: StorageMapperApi,
53 T: TopEncode + TopDecode + NestedEncode + NestedDecode,
54{
55 fn clear(&mut self) {
56 for value in self.queue_mapper.iter() {
57 self.clear_node_id(&value);
58 }
59 self.queue_mapper.clear();
60 }
61}
62
63impl<SA, T> StorageMapperFromAddress<SA> for SetMapper<SA, T, ManagedAddress<SA>>
64where
65 SA: StorageMapperApi,
66 T: TopEncode + TopDecode + NestedEncode + NestedDecode,
67{
68 fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
69 SetMapper {
70 _phantom_api: PhantomData,
71 address: address.clone(),
72 base_key: base_key.clone(),
73 queue_mapper: QueueMapper::new_from_address(address, base_key),
74 }
75 }
76}
77
78impl<SA, T> SetMapper<SA, T, CurrentStorage>
79where
80 SA: StorageMapperApi,
81 T: TopEncode + TopDecode + NestedEncode + NestedDecode,
82{
83 fn set_node_id(&self, value: &T, node_id: u32) {
84 storage_set(
85 self.build_named_value_key(NODE_ID_IDENTIFIER, value)
86 .as_ref(),
87 &node_id,
88 );
89 }
90
91 fn clear_node_id(&self, value: &T) {
92 storage_set(
93 self.build_named_value_key(NODE_ID_IDENTIFIER, value)
94 .as_ref(),
95 &codec::Empty,
96 );
97 }
98
99 pub fn insert(&mut self, value: T) -> bool {
105 if self.contains(&value) {
106 return false;
107 }
108 let new_node_id = self.queue_mapper.push_back_node_id(&value);
109 self.set_node_id(&value, new_node_id);
110 true
111 }
112
113 pub fn remove(&mut self, value: &T) -> bool {
116 let node_id = self.get_node_id(value);
117 if node_id == NULL_ENTRY {
118 return false;
119 }
120 self.queue_mapper.remove_by_node_id(node_id);
121 self.clear_node_id(value);
122 true
123 }
124
125 pub fn remove_all<I>(&mut self, iter: I)
126 where
127 I: IntoIterator<Item = T>,
128 {
129 for item in iter {
130 self.remove(&item);
131 }
132 }
133}
134
135impl<SA, A, T> SetMapper<SA, T, A>
136where
137 SA: StorageMapperApi,
138 A: StorageAddress<SA>,
139 T: TopEncode + TopDecode + NestedEncode + NestedDecode,
140{
141 pub fn build_named_value_key(&self, name: &[u8], value: &T) -> StorageKey<SA> {
142 let mut named_key = self.base_key.clone();
143 named_key.append_bytes(name);
144 named_key.append_item(value);
145 named_key
146 }
147
148 pub fn iter(&self) -> Iter<'_, SA, A, T> {
151 self.queue_mapper.iter()
152 }
153
154 pub fn iter_from(&self, value: &T) -> Iter<'_, SA, A, T> {
155 let node_id = self.get_node_id(value);
156 self.queue_mapper.iter_from_node_id(node_id)
157 }
158
159 fn get_node_id(&self, value: &T) -> u32 {
160 self.address.address_storage_get(
161 self.build_named_value_key(NODE_ID_IDENTIFIER, value)
162 .as_ref(),
163 )
164 }
165
166 pub fn contains(&self, value: &T) -> bool {
168 self.get_node_id(value) != NULL_ENTRY
169 }
170
171 pub fn is_empty(&self) -> bool {
173 self.queue_mapper.is_empty()
174 }
175
176 pub fn len(&self) -> usize {
178 self.queue_mapper.len()
179 }
180
181 pub fn check_internal_consistency(&self) -> bool {
183 self.queue_mapper.check_internal_consistency()
184 }
185
186 pub fn next(&self, value: &T) -> Option<T> {
187 let node_id = self.get_node_id(value);
188 if node_id == NULL_ENTRY {
189 return None;
190 }
191
192 let next_node_id = self.queue_mapper.get_node(node_id).next;
193
194 self.queue_mapper.get_value_option(next_node_id)
195 }
196
197 pub fn previous(&self, value: &T) -> Option<T> {
198 let node_id = self.get_node_id(value);
199 if node_id == NULL_ENTRY {
200 return None;
201 }
202
203 let next_node_id = self.queue_mapper.get_node(node_id).previous;
204
205 self.queue_mapper.get_value_option(next_node_id)
206 }
207
208 pub fn front(&self) -> Option<T> {
209 self.queue_mapper.front()
210 }
211
212 pub fn back(&self) -> Option<T> {
213 self.queue_mapper.back()
214 }
215}
216
217impl<'a, SA, A, T> IntoIterator for &'a SetMapper<SA, T, A>
218where
219 SA: StorageMapperApi,
220 A: StorageAddress<SA>,
221 T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
222{
223 type Item = T;
224
225 type IntoIter = Iter<'a, SA, A, T>;
226
227 fn into_iter(self) -> Self::IntoIter {
228 self.iter()
229 }
230}
231
232impl<SA, T> Extend<T> for SetMapper<SA, T, CurrentStorage>
233where
234 SA: StorageMapperApi,
235 T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
236{
237 fn extend<I>(&mut self, iter: I)
238 where
239 I: IntoIterator<Item = T>,
240 {
241 for item in iter {
242 self.insert(item);
243 }
244 }
245}
246
247impl<SA, T> TopEncodeMulti for SetMapper<SA, T, CurrentStorage>
249where
250 SA: StorageMapperApi,
251 T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
252{
253 fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
254 where
255 O: TopEncodeMultiOutput,
256 H: EncodeErrorHandler,
257 {
258 multi_encode_iter_or_handle_err(self.iter(), output, h)
259 }
260}
261
262impl<SA, T> TypeAbiFrom<SetMapper<SA, T, CurrentStorage>> for MultiValueEncoded<SA, T>
263where
264 SA: StorageMapperApi,
265 T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
266{
267}
268
269impl<SA, T> TypeAbiFrom<Self> for SetMapper<SA, T, CurrentStorage>
270where
271 SA: StorageMapperApi,
272 T: TopEncode + TopDecode + NestedEncode + NestedDecode + 'static,
273{
274}
275
276impl<SA, T> TypeAbi for SetMapper<SA, T, CurrentStorage>
278where
279 SA: StorageMapperApi,
280 T: TopEncode + TopDecode + NestedEncode + NestedDecode + TypeAbi,
281{
282 type Unmanaged = Self;
283
284 fn type_name() -> TypeName {
285 crate::abi::type_name_variadic::<T>()
286 }
287
288 fn type_name_rust() -> TypeName {
289 crate::abi::type_name_multi_value_encoded::<T>()
290 }
291
292 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
293 T::provide_type_descriptions(accumulator);
294 }
295
296 fn is_variadic() -> bool {
297 true
298 }
299}