multiversx_sc/storage/mappers/
whitelist_mapper.rs1use core::marker::PhantomData;
2
3use multiversx_sc_codec::{TopDecode, TopEncode};
4
5use super::{
6 source::{CurrentStorage, StorageAddress},
7 SingleValueMapper, StorageMapper, StorageMapperFromAddress,
8};
9use crate::{
10 api::{ErrorApiImpl, StorageMapperApi},
11 codec::NestedEncode,
12 storage::StorageKey,
13 types::ManagedAddress,
14};
15
16type FlagMapper<SA, A> = SingleValueMapper<SA, bool, A>;
17
18static ITEM_NOT_WHITELISTED_ERR_MSG: &[u8] = b"Item not whitelisted";
19
20pub struct WhitelistMapper<SA, T, A = CurrentStorage>
24where
25 SA: StorageMapperApi,
26 A: StorageAddress<SA>,
27 T: NestedEncode + 'static,
28{
29 address: A,
30 base_key: StorageKey<SA>,
31 _phantom: PhantomData<T>,
32}
33
34impl<SA, T> StorageMapper<SA> for WhitelistMapper<SA, T, CurrentStorage>
35where
36 SA: StorageMapperApi,
37 T: NestedEncode + 'static,
38{
39 fn new(base_key: StorageKey<SA>) -> Self {
40 Self {
41 address: CurrentStorage,
42 base_key,
43 _phantom: PhantomData,
44 }
45 }
46}
47
48impl<SA, T> StorageMapperFromAddress<SA> for WhitelistMapper<SA, T, ManagedAddress<SA>>
49where
50 SA: StorageMapperApi,
51 T: NestedEncode + 'static,
52{
53 fn new_from_address(address: ManagedAddress<SA>, base_key: StorageKey<SA>) -> Self {
54 Self {
55 address,
56 base_key,
57 _phantom: PhantomData,
58 }
59 }
60}
61
62impl<SA, T> WhitelistMapper<SA, T, ManagedAddress<SA>>
63where
64 SA: StorageMapperApi,
65 T: TopDecode + TopEncode + NestedEncode + 'static,
66{
67 pub fn contains(&self, item: &T) -> bool {
68 let mapper = self.build_mapper_for_item(item);
69 !mapper.is_empty()
70 }
71
72 pub fn require_whitelisted(&self, item: &T) {
73 if !self.contains(item) {
74 SA::error_api_impl().signal_error(ITEM_NOT_WHITELISTED_ERR_MSG);
75 }
76 }
77
78 fn build_mapper_for_item(&self, item: &T) -> FlagMapper<SA, ManagedAddress<SA>> {
79 let mut key = self.base_key.clone();
80 key.append_item(item);
81
82 FlagMapper::<SA, ManagedAddress<SA>>::new_from_address(self.address.clone(), key)
83 }
84}
85
86impl<SA, T> WhitelistMapper<SA, T, CurrentStorage>
87where
88 SA: StorageMapperApi,
89 T: TopDecode + TopEncode + NestedEncode + 'static,
90{
91 pub fn contains(&self, item: &T) -> bool {
92 let mapper = self.build_mapper_for_item(item);
93 !mapper.is_empty()
94 }
95
96 pub fn require_whitelisted(&self, item: &T) {
97 if !self.contains(item) {
98 SA::error_api_impl().signal_error(ITEM_NOT_WHITELISTED_ERR_MSG);
99 }
100 }
101
102 pub fn add(&self, item: &T) {
103 let mapper = self.build_mapper_for_item(item);
104 mapper.set(true);
105 }
106
107 pub fn remove(&self, item: &T) {
108 let mapper = self.build_mapper_for_item(item);
109 mapper.clear();
110 }
111
112 fn build_mapper_for_item(&self, item: &T) -> FlagMapper<SA, CurrentStorage> {
113 let mut key = self.base_key.clone();
114 key.append_item(item);
115
116 FlagMapper::<SA, CurrentStorage>::new(key)
117 }
118}