multiversx_sc/storage/mappers/
single_value_mapper.rs1use core::{borrow::Borrow, marker::PhantomData};
2
3pub use super::{
4 source::{CurrentStorage, StorageAddress},
5 StorageMapper, StorageMapperFromAddress,
6};
7use crate::{
8 abi::{TypeAbi, TypeAbiFrom, TypeDescriptionContainer, TypeName},
9 api::StorageMapperApi,
10 codec::{
11 multi_types::PlaceholderOutput, DecodeErrorHandler, EncodeErrorHandler, TopDecode,
12 TopDecodeInput, TopEncode, TopEncodeMulti, TopEncodeMultiOutput, TopEncodeOutput,
13 },
14 storage::{storage_clear, storage_set, StorageKey},
15 types::{ManagedAddress, ManagedType},
16};
17
18pub struct SingleValueMapper<SA, T, A = CurrentStorage>
20where
21 SA: StorageMapperApi,
22 A: StorageAddress<SA>,
23 T: TopEncode + TopDecode + 'static,
24{
25 address: A,
26 key: StorageKey<SA>,
27 _phantom_api: PhantomData<SA>,
28 _phantom_item: PhantomData<T>,
29}
30
31impl<SA, T> StorageMapper<SA> for SingleValueMapper<SA, T, CurrentStorage>
32where
33 SA: StorageMapperApi,
34 T: TopEncode + TopDecode,
35{
36 #[inline]
37 fn new(base_key: StorageKey<SA>) -> Self {
38 SingleValueMapper {
39 address: CurrentStorage,
40 key: base_key,
41 _phantom_api: PhantomData,
42 _phantom_item: PhantomData,
43 }
44 }
45}
46
47impl<SA, T> StorageMapperFromAddress<SA> for SingleValueMapper<SA, T, ManagedAddress<SA>>
48where
49 SA: StorageMapperApi,
50 T: TopEncode + TopDecode,
51{
52 #[inline]
53 fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
54 SingleValueMapper {
55 address,
56 key: base_key,
57 _phantom_api: PhantomData,
58 _phantom_item: PhantomData,
59 }
60 }
61}
62
63impl<SA, T, A> SingleValueMapper<SA, T, A>
64where
65 SA: StorageMapperApi,
66 A: StorageAddress<SA>,
67 T: TopEncode + TopDecode,
68{
69 pub fn get(&self) -> T {
71 self.address.address_storage_get(self.key.as_ref())
72 }
73
74 pub fn is_empty(&self) -> bool {
76 self.raw_byte_length() == 0
77 }
78
79 pub fn raw_byte_length(&self) -> usize {
80 self.address.address_storage_get_len(self.key.as_ref())
81 }
82}
83
84impl<SA, T> SingleValueMapper<SA, T, CurrentStorage>
85where
86 SA: StorageMapperApi,
87 T: TopEncode + TopDecode,
88{
89 #[inline]
93 pub fn set<BT>(&self, new_value: BT)
94 where
95 BT: Borrow<T>,
96 {
97 storage_set(self.key.as_ref(), new_value.borrow());
98 }
99
100 pub fn set_if_empty<BT>(&self, value: BT)
103 where
104 BT: Borrow<T>,
105 {
106 if self.is_empty() {
107 self.set(value);
108 }
109 }
110
111 pub fn clear(&self) {
113 storage_clear(self.key.as_ref());
114 }
115
116 pub fn update<R, F: FnOnce(&mut T) -> R>(&self, f: F) -> R {
120 let mut value = self.get();
121 let result = f(&mut value);
122 self.set(value);
123 result
124 }
125
126 pub fn take(&self) -> T {
128 let value = self.get();
129 self.clear();
130 value
131 }
132
133 pub fn replace<BT>(&self, new_value: BT) -> T
135 where
136 BT: Borrow<T>,
137 {
138 let value = self.get();
139 self.set(new_value);
140 value
141 }
142}
143
144impl<SA, T> TopEncodeMulti for SingleValueMapper<SA, T, CurrentStorage>
145where
146 SA: StorageMapperApi,
147 T: TopEncode + TopDecode,
148{
149 fn multi_encode_or_handle_err<O, H>(&self, output: &mut O, h: H) -> Result<(), H::HandledErr>
150 where
151 O: TopEncodeMultiOutput,
152 H: EncodeErrorHandler,
153 {
154 output.push_single_value(&self.get(), h)
155 }
156}
157
158pub struct SingleValue<T: TopDecode>(T);
162
163impl<T: TopEncode + TopDecode> TopEncode for SingleValue<T> {
164 fn top_encode_or_handle_err<O, H>(&self, output: O, h: H) -> Result<(), H::HandledErr>
165 where
166 O: TopEncodeOutput,
167 H: EncodeErrorHandler,
168 {
169 self.0.top_encode_or_handle_err(output, h)
170 }
171}
172
173impl<T: TopDecode> TopDecode for SingleValue<T> {
174 fn top_decode_or_handle_err<I, H>(input: I, h: H) -> Result<Self, H::HandledErr>
175 where
176 I: TopDecodeInput,
177 H: DecodeErrorHandler,
178 {
179 Ok(SingleValue::<T>(T::top_decode_or_handle_err(input, h)?))
180 }
181}
182
183impl<T: TopDecode> From<T> for SingleValue<T> {
184 fn from(value: T) -> Self {
185 SingleValue::<T>(value)
186 }
187}
188
189impl<T: TopDecode> SingleValue<T> {
190 #[inline]
191 pub fn into(self) -> T {
192 self.0
193 }
194}
195
196impl<SA, T, R> TypeAbiFrom<SingleValueMapper<SA, T, CurrentStorage>> for SingleValue<R>
197where
198 SA: StorageMapperApi,
199 T: TopEncode + TopDecode,
200 R: TopDecode + TypeAbiFrom<T>,
201{
202}
203
204impl<SA, T> TypeAbiFrom<SingleValueMapper<SA, T>> for PlaceholderOutput
205where
206 SA: StorageMapperApi,
207 T: TopEncode + TopDecode,
208{
209}
210
211impl<SA, T> TypeAbiFrom<Self> for SingleValueMapper<SA, T, CurrentStorage>
212where
213 SA: StorageMapperApi,
214 T: TopEncode + TopDecode + TypeAbi,
215{
216}
217
218impl<SA, T> TypeAbi for SingleValueMapper<SA, T, CurrentStorage>
219where
220 SA: StorageMapperApi,
221 T: TopEncode + TopDecode + TypeAbi,
222{
223 type Unmanaged = T::Unmanaged;
224
225 fn type_name() -> TypeName {
226 T::type_name()
227 }
228
229 fn type_name_rust() -> TypeName {
230 T::type_name_rust()
231 }
232
233 fn provide_type_descriptions<TDC: TypeDescriptionContainer>(accumulator: &mut TDC) {
234 T::provide_type_descriptions(accumulator)
235 }
236}