clone_cw_multi_test/prefixed_storage/
mod.rs1use cosmwasm_std::Storage;
2use cosmwasm_std::{Order, Record};
3use length_prefixed::to_length_prefixed_nested;
4use namespace_helpers::{get_with_prefix, range_with_prefix, remove_with_prefix, set_with_prefix};
5
6mod length_prefixed;
7mod namespace_helpers;
8
9pub use length_prefixed::{
10 contract_namespace, decode_length, get_full_contract_storage_namespace, to_length_prefixed,
11 CONTRACT_STORAGE_PREFIX,
12};
13
14pub fn prefixed<'a>(storage: &'a mut dyn Storage, namespace: &[u8]) -> PrefixedStorage<'a> {
16 PrefixedStorage::new(storage, namespace)
17}
18
19pub fn prefixed_read<'a>(
21 storage: &'a dyn Storage,
22 namespace: &[u8],
23) -> ReadonlyPrefixedStorage<'a> {
24 ReadonlyPrefixedStorage::new(storage, namespace)
25}
26
27pub struct PrefixedStorage<'a> {
28 storage: &'a mut dyn Storage,
29 prefix: Vec<u8>,
30}
31
32impl<'a> PrefixedStorage<'a> {
33 pub fn new(storage: &'a mut dyn Storage, namespace: &[u8]) -> Self {
34 PrefixedStorage {
35 storage,
36 prefix: to_length_prefixed(namespace),
37 }
38 }
39
40 pub fn multilevel(storage: &'a mut dyn Storage, namespaces: &[&[u8]]) -> Self {
43 PrefixedStorage {
44 storage,
45 prefix: to_length_prefixed_nested(namespaces),
46 }
47 }
48}
49
50impl<'a> Storage for PrefixedStorage<'a> {
51 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
52 get_with_prefix(self.storage, &self.prefix, key)
53 }
54
55 fn set(&mut self, key: &[u8], value: &[u8]) {
56 set_with_prefix(self.storage, &self.prefix, key, value);
57 }
58
59 fn remove(&mut self, key: &[u8]) {
60 remove_with_prefix(self.storage, &self.prefix, key);
61 }
62
63 fn range<'b>(
66 &'b self,
67 start: Option<&[u8]>,
68 end: Option<&[u8]>,
69 order: Order,
70 ) -> Box<dyn Iterator<Item = Record> + 'b> {
71 range_with_prefix(self.storage, &self.prefix, start, end, order)
72 }
73}
74
75pub struct ReadonlyPrefixedStorage<'a> {
76 storage: &'a dyn Storage,
77 prefix: Vec<u8>,
78}
79
80impl<'a> ReadonlyPrefixedStorage<'a> {
81 pub fn new(storage: &'a dyn Storage, namespace: &[u8]) -> Self {
82 ReadonlyPrefixedStorage {
83 storage,
84 prefix: to_length_prefixed(namespace),
85 }
86 }
87
88 pub fn multilevel(storage: &'a dyn Storage, namespaces: &[&[u8]]) -> Self {
91 ReadonlyPrefixedStorage {
92 storage,
93 prefix: to_length_prefixed_nested(namespaces),
94 }
95 }
96}
97
98impl<'a> Storage for ReadonlyPrefixedStorage<'a> {
99 fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
100 get_with_prefix(self.storage, &self.prefix, key)
101 }
102
103 fn set(&mut self, _key: &[u8], _value: &[u8]) {
104 unimplemented!();
105 }
106
107 fn remove(&mut self, _key: &[u8]) {
108 unimplemented!();
109 }
110
111 fn range<'b>(
113 &'b self,
114 start: Option<&[u8]>,
115 end: Option<&[u8]>,
116 order: Order,
117 ) -> Box<dyn Iterator<Item = Record> + 'b> {
118 range_with_prefix(self.storage, &self.prefix, start, end, order)
119 }
120}
121
122#[cfg(test)]
123mod tests {
124 use super::*;
125 use cosmwasm_std::testing::MockStorage;
126
127 #[test]
128 fn prefixed_storage_set_and_get() {
129 let mut storage = MockStorage::new();
130
131 let mut s1 = PrefixedStorage::new(&mut storage, b"foo");
133 s1.set(b"bar", b"gotcha");
134 assert_eq!(storage.get(b"\x00\x03foobar").unwrap(), b"gotcha".to_vec());
135
136 let s2 = PrefixedStorage::new(&mut storage, b"foo");
138 assert_eq!(s2.get(b"bar"), Some(b"gotcha".to_vec()));
139 assert_eq!(s2.get(b"elsewhere"), None);
140 }
141
142 #[test]
143 fn prefixed_storage_multilevel_set_and_get() {
144 let mut storage = MockStorage::new();
145
146 let mut bar = PrefixedStorage::multilevel(&mut storage, &[b"foo", b"bar"]);
148 bar.set(b"baz", b"winner");
149 assert_eq!(
150 storage.get(b"\x00\x03foo\x00\x03barbaz").unwrap(),
151 b"winner".to_vec()
152 );
153
154 let bar = PrefixedStorage::multilevel(&mut storage, &[b"foo", b"bar"]);
156 assert_eq!(bar.get(b"baz"), Some(b"winner".to_vec()));
157 assert_eq!(bar.get(b"elsewhere"), None);
158 }
159
160 #[test]
161 fn readonly_prefixed_storage_get() {
162 let mut storage = MockStorage::new();
163 storage.set(b"\x00\x03foobar", b"gotcha");
164
165 let s1 = ReadonlyPrefixedStorage::new(&storage, b"foo");
167 assert_eq!(s1.get(b"bar"), Some(b"gotcha".to_vec()));
168 assert_eq!(s1.get(b"elsewhere"), None);
169
170 let s2 = ReadonlyPrefixedStorage::new(&storage, b"fo");
172 assert_eq!(s2.get(b"obar"), None);
173 }
174
175 #[test]
176 fn readonly_prefixed_storage_multilevel_get() {
177 let mut storage = MockStorage::new();
178 storage.set(b"\x00\x03foo\x00\x03barbaz", b"winner");
179
180 let bar = ReadonlyPrefixedStorage::multilevel(&storage, &[b"foo", b"bar"]);
181 assert_eq!(bar.get(b"baz"), Some(b"winner".to_vec()));
182 assert_eq!(bar.get(b"elsewhere"), None);
183 }
184}