cw_multi_test/prefixed_storage/
namespace_helpers.rs1use cosmwasm_std::Storage;
2use cosmwasm_std::{Order, Record};
3
4pub(crate) fn get_with_prefix(
5 storage: &dyn Storage,
6 namespace: &[u8],
7 key: &[u8],
8) -> Option<Vec<u8>> {
9 storage.get(&concat(namespace, key))
10}
11
12pub(crate) fn set_with_prefix(
13 storage: &mut dyn Storage,
14 namespace: &[u8],
15 key: &[u8],
16 value: &[u8],
17) {
18 storage.set(&concat(namespace, key), value);
19}
20
21pub(crate) fn remove_with_prefix(storage: &mut dyn Storage, namespace: &[u8], key: &[u8]) {
22 storage.remove(&concat(namespace, key));
23}
24
25#[inline]
26fn concat(namespace: &[u8], key: &[u8]) -> Vec<u8> {
27 let mut k = namespace.to_vec();
28 k.extend_from_slice(key);
29 k
30}
31
32pub(crate) fn range_with_prefix<'a>(
33 storage: &'a dyn Storage,
34 namespace: &[u8],
35 start: Option<&[u8]>,
36 end: Option<&[u8]>,
37 order: Order,
38) -> Box<dyn Iterator<Item = Record> + 'a> {
39 let start = match start {
41 Some(s) => concat(namespace, s),
42 None => namespace.to_vec(),
43 };
44 let end = match end {
45 Some(e) => concat(namespace, e),
46 None => namespace_upper_bound(namespace),
48 };
49
50 let base_iterator = storage.range(Some(&start), Some(&end), order);
52
53 let prefix = namespace.to_vec();
55 let mapped = base_iterator.map(move |(k, v)| (trim(&prefix, &k), v));
56 Box::new(mapped)
57}
58
59#[inline]
60fn trim(namespace: &[u8], key: &[u8]) -> Vec<u8> {
61 key[namespace.len()..].to_vec()
62}
63
64fn namespace_upper_bound(input: &[u8]) -> Vec<u8> {
68 let mut copy = input.to_vec();
69 for i in (0..input.len()).rev() {
71 if copy[i] == 255 {
72 copy[i] = 0;
73 } else {
74 copy[i] += 1;
75 break;
76 }
77 }
78 copy
79}
80
81#[cfg(test)]
82mod tests {
83 use super::super::length_prefixed::to_length_prefixed;
84 use super::*;
85 use cosmwasm_std::testing::MockStorage;
86
87 #[test]
88 fn prefix_get_set() {
89 let mut storage = MockStorage::new();
90 let prefix = to_length_prefixed(b"foo");
91
92 set_with_prefix(&mut storage, &prefix, b"bar", b"gotcha");
93 let value = get_with_prefix(&storage, &prefix, b"bar");
94 assert_eq!(value, Some(b"gotcha".to_vec()));
95
96 let other_prefix = to_length_prefixed(b"fo");
98 let collision = get_with_prefix(&storage, &other_prefix, b"obar");
99 assert_eq!(collision, None);
100 }
101
102 #[test]
103 fn range_works() {
104 let mut storage = MockStorage::new();
105 let prefix = to_length_prefixed(b"foo");
106 let other_prefix = to_length_prefixed(b"food");
107
108 set_with_prefix(&mut storage, &prefix, b"bar", b"none");
110 set_with_prefix(&mut storage, &prefix, b"snowy", b"day");
111
112 set_with_prefix(&mut storage, &other_prefix, b"moon", b"buggy");
114
115 let mut iter = range_with_prefix(&storage, &prefix, None, None, Order::Descending);
117 let first = iter.next().unwrap();
118 assert_eq!(first, (b"snowy".to_vec(), b"day".to_vec()));
119 let second = iter.next().unwrap();
120 assert_eq!(second, (b"bar".to_vec(), b"none".to_vec()));
121 assert!(iter.next().is_none());
122
123 let iter = storage.range(None, None, Order::Ascending);
125 assert_eq!(3, iter.count());
126
127 let mut iter = storage.range(None, None, Order::Ascending);
129 let first = iter.next().unwrap();
130 let expected_key = concat(&prefix, b"bar");
131 assert_eq!(first, (expected_key, b"none".to_vec()));
132 }
133
134 #[test]
135 fn range_with_prefix_wrap_over() {
136 let mut storage = MockStorage::new();
137 let prefix = to_length_prefixed(b"f\xff\xff");
139 let other_prefix = to_length_prefixed(b"f\xff\x44");
140
141 set_with_prefix(&mut storage, &prefix, b"bar", b"none");
143 set_with_prefix(&mut storage, &prefix, b"snowy", b"day");
144
145 set_with_prefix(&mut storage, &other_prefix, b"moon", b"buggy");
147
148 let iter = range_with_prefix(&storage, &prefix, None, None, Order::Descending);
150 let elements: Vec<Record> = iter.collect();
151 assert_eq!(
152 elements,
153 vec![
154 (b"snowy".to_vec(), b"day".to_vec()),
155 (b"bar".to_vec(), b"none".to_vec()),
156 ]
157 );
158 }
159
160 #[test]
161 fn range_with_start_end_set() {
162 let mut storage = MockStorage::new();
163 let prefix = to_length_prefixed(b"f\xff\xff");
165 let other_prefix = to_length_prefixed(b"f\xff\x44");
166
167 set_with_prefix(&mut storage, &prefix, b"bar", b"none");
169 set_with_prefix(&mut storage, &prefix, b"snowy", b"day");
170
171 set_with_prefix(&mut storage, &other_prefix, b"moon", b"buggy");
173
174 let res: Vec<Record> =
176 range_with_prefix(&storage, &prefix, Some(b"b"), Some(b"c"), Order::Ascending)
177 .collect();
178 assert_eq!(res.len(), 1);
179 assert_eq!(res[0], (b"bar".to_vec(), b"none".to_vec()));
180
181 let res_count = range_with_prefix(
183 &storage,
184 &prefix,
185 Some(b"bas"),
186 Some(b"sno"),
187 Order::Ascending,
188 )
189 .count();
190 assert_eq!(res_count, 0);
191
192 let res: Vec<Record> =
193 range_with_prefix(&storage, &prefix, Some(b"ant"), None, Order::Ascending).collect();
194 assert_eq!(res.len(), 2);
195 assert_eq!(res[0], (b"bar".to_vec(), b"none".to_vec()));
196 assert_eq!(res[1], (b"snowy".to_vec(), b"day".to_vec()));
197 }
198
199 #[test]
200 fn namespace_upper_bound_works() {
201 assert_eq!(namespace_upper_bound(b"bob"), b"boc".to_vec());
202 assert_eq!(namespace_upper_bound(b"fo\xfe"), b"fo\xff".to_vec());
203 assert_eq!(namespace_upper_bound(b"fo\xff"), b"fp\x00".to_vec());
204 assert_eq!(
206 namespace_upper_bound(b"fo\xff\xff\xff"),
207 b"fp\x00\x00\x00".to_vec()
208 );
209 assert_eq!(namespace_upper_bound(b"\xffabc"), b"\xffabd".to_vec());
211 }
212}