odra_core/
named_keys.rs

1/// Creates an Odra module that stores a single value under a given named key.
2///
3/// The module has two methods: `set` and `get`.
4/// If the value is not set and an error is passed as the fourth argument, `get` will revert with the provided error.
5#[macro_export]
6macro_rules! single_value_storage {
7    ($name:ident, $value_ty:ty, $key:expr, $err:expr) => {
8        #[odra::module]
9        pub struct $name;
10
11        impl $name {
12            pub fn set(&self, value: $value_ty) {
13                self.env().set_named_value($key, value);
14            }
15
16            pub fn get(&self) -> $value_ty {
17                self.env()
18                    .get_named_value($key)
19                    .unwrap_or_revert_with(self, $err)
20            }
21        }
22    };
23    ($name:ident, $value_ty:ty, $key:expr) => {
24        #[odra::module]
25        pub struct $name;
26
27        impl $name {
28            pub fn set(&self, value: $value_ty) {
29                self.env().set_named_value($key, value);
30            }
31
32            pub fn get(&self) -> Option<$value_ty> {
33                self.env().get_named_value($key)
34            }
35        }
36    };
37}
38
39/// Creates an Odra module that stores a values in a given dictionary.
40///
41/// The module has three methods: `set`, `get` and `init`.
42/// The `key` argument of `set` and `get` is used as a dictionary key.
43/// The `init` method initializes the dictionary with the given name.
44#[macro_export]
45macro_rules! key_value_storage {
46    ($name:ident, $dict:expr, $value_type:ty) => {
47        #[odra::module]
48        pub struct $name;
49
50        impl $name {
51            pub fn set(&self, key: &str, value: $value_type) {
52                self.env()
53                    .set_dictionary_value($dict, key.as_bytes(), value);
54            }
55
56            pub fn get(&self, key: &str) -> Option<$value_type> {
57                self.env().get_dictionary_value($dict, key.as_bytes())
58            }
59
60            pub fn init(&self) {
61                self.env().init_dictionary($dict);
62            }
63        }
64    };
65}
66
67/// Creates an Odra module that stores a values in a given dictionary.
68///
69/// The module has three methods: `set`, `get` and `init`.
70/// The `key` argument of `set` and `get` is base64-encoded and then used as a dictionary key.
71/// The `init` method initializes the dictionary with the given name.
72#[macro_export]
73macro_rules! base64_encoded_key_value_storage {
74    ($name:ident, $dict:expr, $key:ty, $value_type:ty) => {
75        #[odra::module]
76        pub struct $name;
77
78        impl $name {
79            pub fn set(&self, key: &$key, value: $value_type) {
80                let encoded_key = Self::key(self, key);
81                self.env()
82                    .set_dictionary_value($dict, encoded_key.as_bytes(), value);
83            }
84
85            pub fn get(&self, key: &$key) -> Option<$value_type> {
86                let encoded_key = Self::key(self, key);
87                self.env()
88                    .get_dictionary_value($dict, encoded_key.as_bytes())
89            }
90
91            pub fn init(&self) {
92                self.env().init_dictionary($dict);
93            }
94
95            #[inline]
96            fn key<R: odra::module::Revertible>(rev: &R, key: &$key) -> String {
97                use base64::prelude::{Engine, BASE64_STANDARD};
98
99                let preimage = key.to_bytes().unwrap_or_revert(rev);
100                BASE64_STANDARD.encode(preimage)
101            }
102        }
103    };
104}
105
106/// Creates an Odra module that stores a values in a given dictionary.
107///
108/// The module has three methods: `set`, `get` and `init`.
109/// The `key1` and `key2` arguments of `set` and `get` are converted to bytes, combined into a single bytes vector,
110/// and finally hex-encoded and then used as a dictionary key.
111/// The `init` method initializes the dictionary with the given name.
112#[macro_export]
113macro_rules! compound_key_value_storage {
114    ($name:ident, $dict:expr, $k1_type:ty, $k2_type:ty, $value_type:ty) => {
115        #[odra::module]
116        pub struct $name;
117
118        impl $name {
119            pub fn set(&self, key1: &$k1_type, key2: &$k2_type, value: $value_type) {
120                let mut key = [0u8; 64];
121                let mut preimage = odra::prelude::Vec::new();
122                preimage.extend_from_slice(&key1.to_bytes().unwrap_or_revert(self));
123                preimage.extend_from_slice(&key2.to_bytes().unwrap_or_revert(self));
124
125                let env = self.env();
126                let key_bytes = env.hash(&preimage);
127                odra::utils::hex_to_slice(&key_bytes, &mut key);
128                env.set_dictionary_value($dict, &key, value);
129            }
130
131            pub fn get_or_default(&self, key1: &$k1_type, key2: &$k2_type) -> $value_type {
132                let mut key = [0u8; 64];
133                let mut preimage = odra::prelude::Vec::new();
134                preimage.extend_from_slice(&key1.to_bytes().unwrap_or_revert(self));
135                preimage.extend_from_slice(&key2.to_bytes().unwrap_or_revert(self));
136
137                let env = self.env();
138                let key_bytes = env.hash(&preimage);
139                odra::utils::hex_to_slice(&key_bytes, &mut key);
140                env.get_dictionary_value($dict, &key).unwrap_or_default()
141            }
142
143            pub fn init(&self) {
144                self.env().init_dictionary($dict);
145            }
146        }
147    };
148    ($name:ident, $dict:expr, $k1_type:ty, $value_type:ty) => {
149        compound_key_value_storage!($name, $dict, $k1_type, $k1_type, $value_type);
150    };
151}