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