multiversx_sc/storage/mappers/
user_mapper.rs1use core::marker::PhantomData;
2
3use crate::{
4 abi::TypeAbiFrom,
5 codec::{
6 multi_encode_iter_or_handle_err, EncodeErrorHandler, TopEncodeMulti, TopEncodeMultiOutput,
7 },
8};
9
10use super::{
11 source::{CurrentStorage, StorageAddress},
12 StorageMapper, StorageMapperFromAddress,
13};
14use crate::{
15 abi::{TypeAbi, TypeName},
16 api::StorageMapperApi,
17 storage::{storage_set, StorageKey},
18 types::{ManagedAddress, ManagedType, ManagedVec, MultiValueEncoded},
19};
20
21const ADDRESS_TO_ID_SUFFIX: &[u8] = b"_address_to_id";
22const ID_TO_ADDRESS_SUFFIX: &[u8] = b"_id_to_address";
23const COUNT_SUFFIX: &[u8] = b"_count";
24
25pub struct UserMapper<SA, A = CurrentStorage>
35where
36 SA: StorageMapperApi,
37 A: StorageAddress<SA>,
38{
39 _phantom_api: PhantomData<SA>,
40 address: A,
41 base_key: StorageKey<SA>,
42}
43
44impl<SA> StorageMapper<SA> for UserMapper<SA>
45where
46 SA: StorageMapperApi,
47{
48 fn new(base_key: StorageKey<SA>) -> Self {
49 UserMapper {
50 _phantom_api: PhantomData,
51 address: CurrentStorage,
52 base_key,
53 }
54 }
55}
56
57impl<SA> StorageMapperFromAddress<SA> for UserMapper<SA, ManagedAddress<SA>>
58where
59 SA: StorageMapperApi,
60{
61 fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
62 UserMapper {
63 _phantom_api: PhantomData,
64 address,
65 base_key,
66 }
67 }
68}
69
70impl<SA, A> UserMapper<SA, A>
71where
72 SA: StorageMapperApi,
73 A: StorageAddress<SA>,
74{
75 fn get_user_id_key(&self, address: &ManagedAddress<SA>) -> StorageKey<SA> {
76 let mut user_id_key = self.base_key.clone();
77 user_id_key.append_bytes(ADDRESS_TO_ID_SUFFIX);
78 user_id_key.append_item(address);
79 user_id_key
80 }
81
82 fn get_user_address_key(&self, id: usize) -> StorageKey<SA> {
83 let mut user_address_key = self.base_key.clone();
84 user_address_key.append_bytes(ID_TO_ADDRESS_SUFFIX);
85 user_address_key.append_item(&id);
86 user_address_key
87 }
88
89 fn get_user_count_key(&self) -> StorageKey<SA> {
90 let mut user_count_key = self.base_key.clone();
91 user_count_key.append_bytes(COUNT_SUFFIX);
92 user_count_key
93 }
94
95 pub fn get_user_id(&self, address: &ManagedAddress<SA>) -> usize {
98 self.address
99 .address_storage_get(self.get_user_id_key(address).as_ref())
100 }
101
102 pub fn get_user_address(&self, id: usize) -> Option<ManagedAddress<SA>> {
104 let key = self.get_user_address_key(id);
105 if self.address.address_storage_get_len(key.as_ref()) > 0 {
108 Some(self.address.address_storage_get(key.as_ref()))
109 } else {
110 None
111 }
112 }
113
114 pub fn get_user_address_unchecked(&self, id: usize) -> ManagedAddress<SA> {
117 self.address
118 .address_storage_get(self.get_user_address_key(id).as_ref())
119 }
120
121 pub fn get_user_address_or_zero(&self, id: usize) -> ManagedAddress<SA> {
124 let key = self.get_user_address_key(id);
125 if self.address.address_storage_get_len(key.as_ref()) > 0 {
127 self.address.address_storage_get(key.as_ref())
128 } else {
129 ManagedAddress::zero()
130 }
131 }
132
133 pub fn get_user_count(&self) -> usize {
135 self.address
136 .address_storage_get(self.get_user_count_key().as_ref())
137 }
138
139 pub fn get_all_addresses(&self) -> ManagedVec<SA, ManagedAddress<SA>> {
142 let user_count = self.get_user_count();
143 let mut result = ManagedVec::new();
144 for i in 1..=user_count {
145 result.push(self.get_user_address_or_zero(i));
146 }
147 result
148 }
149}
150
151impl<SA> UserMapper<SA, CurrentStorage>
152where
153 SA: StorageMapperApi,
154{
155 fn set_user_id(&self, address: &ManagedAddress<SA>, id: usize) {
156 storage_set(self.get_user_id_key(address).as_ref(), &id);
157 }
158
159 fn set_user_address(&self, id: usize, address: &ManagedAddress<SA>) {
160 storage_set(self.get_user_address_key(id).as_ref(), address);
161 }
162
163 fn set_user_count(&self, user_count: usize) {
164 storage_set(self.get_user_count_key().as_ref(), &user_count);
165 }
166
167 pub fn get_or_create_users<AddressIter, F>(
170 &self,
171 address_iter: AddressIter,
172 mut user_id_lambda: F,
173 ) where
174 AddressIter: Iterator<Item = ManagedAddress<SA>>,
175 F: FnMut(usize, bool),
176 {
177 let mut user_count = self.get_user_count();
178 for address in address_iter {
179 let user_id = self.get_user_id(&address);
180 if user_id > 0 {
181 user_id_lambda(user_id, false);
182 } else {
183 user_count += 1;
184 let new_user_id = user_count;
185 self.set_user_id(&address, new_user_id);
186 self.set_user_address(new_user_id, &address);
187 user_id_lambda(new_user_id, true);
188 }
189 }
190 self.set_user_count(user_count);
191 }
192
193 pub fn get_or_create_user(&self, address: &ManagedAddress<SA>) -> usize {
196 let mut user_id = self.get_user_id(address);
197 if user_id == 0 {
198 let next_user_count = self.get_user_count() + 1;
199 self.set_user_count(next_user_count);
200 user_id = next_user_count;
201 self.set_user_id(address, user_id);
202 self.set_user_address(user_id, address);
203 }
204 user_id
205 }
206}
207
208impl<SA> TopEncodeMulti for UserMapper<SA, CurrentStorage>
211where
212 SA: StorageMapperApi,
213{
214 fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
215 where
216 O: TopEncodeMultiOutput,
217 H: EncodeErrorHandler,
218 {
219 let all_addresses = self.get_all_addresses();
220 multi_encode_iter_or_handle_err(all_addresses.into_iter(), output, h)
221 }
222}
223
224impl<SA> TypeAbiFrom<UserMapper<SA, CurrentStorage>> for MultiValueEncoded<SA, ManagedAddress<SA>> where
225 SA: StorageMapperApi
226{
227}
228
229impl<SA> TypeAbiFrom<Self> for UserMapper<SA, CurrentStorage> where SA: StorageMapperApi {}
230
231impl<SA> TypeAbi for UserMapper<SA, CurrentStorage>
233where
234 SA: StorageMapperApi,
235{
236 type Unmanaged = Self;
237
238 fn type_name() -> TypeName {
239 crate::abi::type_name_variadic::<ManagedAddress<SA>>()
240 }
241
242 fn type_name_rust() -> TypeName {
243 crate::abi::type_name_multi_value_encoded::<ManagedAddress<SA>>()
244 }
245
246 fn is_variadic() -> bool {
247 true
248 }
249}