1#![cfg(feature = "iterator")]
2use core::fmt;
3use serde::de::DeserializeOwned;
4use serde::Serialize;
5use std::fmt::Debug;
6
7use cosmwasm_std::{Order, Record, StdResult, Storage};
8use std::ops::Deref;
9
10use crate::de::KeyDeserialize;
11use crate::iter_helpers::{deserialize_kv, deserialize_v};
12use crate::keys::Key;
13use crate::{Bound, PrimaryKey};
14
15type DeserializeVFn<T> = fn(&dyn Storage, &[u8], Record) -> StdResult<Record<T>>;
16
17type DeserializeKvFn<K, T> =
18 fn(&dyn Storage, &[u8], Record) -> StdResult<(<K as KeyDeserialize>::Output, T)>;
19
20pub fn default_deserializer_v<T: DeserializeOwned>(
21 _: &dyn Storage,
22 _: &[u8],
23 raw: Record,
24) -> StdResult<Record<T>> {
25 deserialize_v(raw)
26}
27
28pub fn default_deserializer_kv<K: KeyDeserialize, T: DeserializeOwned>(
29 _: &dyn Storage,
30 _: &[u8],
31 raw: Record,
32) -> StdResult<(K::Output, T)> {
33 deserialize_kv::<K, T>(raw)
34}
35
36#[derive(Clone)]
37pub struct IndexPrefix<K, T, B = Vec<u8>>
38where
39 K: KeyDeserialize,
40 T: Serialize + DeserializeOwned,
41{
42 inner: crate::prefix::Prefix<K, T, B>,
43 pk_name: Vec<u8>,
44 de_fn_kv: DeserializeKvFn<K, T>,
45 de_fn_v: DeserializeVFn<T>,
46}
47
48impl<K, T> Debug for IndexPrefix<K, T>
49where
50 K: KeyDeserialize,
51 T: Serialize + DeserializeOwned,
52{
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 f.debug_struct("IndexPrefix")
55 .field("storage_prefix", &self.inner.storage_prefix)
56 .field("pk_name", &self.pk_name)
57 .finish_non_exhaustive()
58 }
59}
60
61impl<K, T> Deref for IndexPrefix<K, T>
62where
63 K: KeyDeserialize,
64 T: Serialize + DeserializeOwned,
65{
66 type Target = [u8];
67
68 fn deref(&self) -> &[u8] {
69 &self.inner.storage_prefix
70 }
71}
72
73impl<K, T, B> IndexPrefix<K, T, B>
74where
75 K: KeyDeserialize,
76 T: Serialize + DeserializeOwned,
77{
78 pub fn new(top_name: &[u8], sub_names: &[Key]) -> Self {
79 IndexPrefix::with_deserialization_functions(
80 top_name,
81 sub_names,
82 &[],
83 default_deserializer_kv::<K, T>,
84 default_deserializer_v,
85 )
86 }
87
88 pub fn with_deserialization_functions(
89 top_name: &[u8],
90 sub_names: &[Key],
91 pk_name: &[u8],
92 de_fn_kv: DeserializeKvFn<K, T>,
93 de_fn_v: DeserializeVFn<T>,
94 ) -> Self {
95 IndexPrefix {
96 inner: crate::prefix::Prefix::new(top_name, sub_names),
97 pk_name: pk_name.to_vec(),
98 de_fn_kv,
99 de_fn_v,
100 }
101 }
102}
103
104impl<'b, K, T, B> IndexPrefix<K, T, B>
105where
106 B: PrimaryKey<'b>,
107 K: KeyDeserialize,
108 T: Serialize + DeserializeOwned,
109{
110 pub fn range_raw<'a>(
111 &self,
112 store: &'a dyn Storage,
113 min: Option<Bound<'b, B>>,
114 max: Option<Bound<'b, B>>,
115 order: Order,
116 ) -> Box<dyn Iterator<Item = StdResult<Record<T>>> + 'a>
117 where
118 T: 'a,
119 {
120 let de_fn = self.de_fn_v;
121 let pk_name = self.pk_name.clone();
122 let mapped = crate::prefix::range_with_prefix(
123 store,
124 &self.inner.storage_prefix,
125 min.map(|b| b.to_raw_bound()),
126 max.map(|b| b.to_raw_bound()),
127 order,
128 )
129 .map(move |kv| (de_fn)(store, &pk_name, kv));
130 Box::new(mapped)
131 }
132
133 pub fn keys_raw<'a>(
134 &self,
135 store: &'a dyn Storage,
136 min: Option<Bound<'b, B>>,
137 max: Option<Bound<'b, B>>,
138 order: Order,
139 ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
140 crate::prefix::keys_with_prefix(
141 store,
142 &self.inner.storage_prefix,
143 min.map(|b| b.to_raw_bound()),
144 max.map(|b| b.to_raw_bound()),
145 order,
146 )
147 }
148
149 pub fn clear(&self, store: &mut dyn Storage, limit: Option<usize>) {
151 self.inner.clear(store, limit);
152 }
153
154 pub fn is_empty(&self, store: &dyn Storage) -> bool {
156 crate::prefix::keys_full(
157 store,
158 &self.inner.storage_prefix,
159 None,
160 None,
161 Order::Ascending,
162 )
163 .next()
164 .is_none()
165 }
166
167 pub fn range<'a>(
168 &self,
169 store: &'a dyn Storage,
170 min: Option<Bound<'b, B>>,
171 max: Option<Bound<'b, B>>,
172 order: Order,
173 ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'a>
174 where
175 T: 'a,
176 K::Output: 'static,
177 {
178 let de_fn = self.de_fn_kv;
179 let pk_name = self.pk_name.clone();
180 let mapped = crate::prefix::range_with_prefix(
181 store,
182 &self.inner.storage_prefix,
183 min.map(|b| b.to_raw_bound()),
184 max.map(|b| b.to_raw_bound()),
185 order,
186 )
187 .map(move |kv| (de_fn)(store, &pk_name, kv));
188 Box::new(mapped)
189 }
190
191 pub fn keys<'a>(
192 &self,
193 store: &'a dyn Storage,
194 min: Option<Bound<'b, B>>,
195 max: Option<Bound<'b, B>>,
196 order: Order,
197 ) -> Box<dyn Iterator<Item = StdResult<K::Output>> + 'a>
198 where
199 T: 'a,
200 K::Output: 'static,
201 {
202 let de_fn = self.de_fn_kv;
203 let pk_name = self.pk_name.clone();
204 let mapped = crate::prefix::range_with_prefix(
205 store,
206 &self.inner.storage_prefix,
207 min.map(|b| b.to_raw_bound()),
208 max.map(|b| b.to_raw_bound()),
209 order,
210 )
211 .map(move |kv| (de_fn)(store, &pk_name, kv).map(|(k, _)| k));
212 Box::new(mapped)
213 }
214}
215
216#[cfg(test)]
217mod test {
218 use super::*;
219
220 use std::marker::PhantomData;
221
222 use cosmwasm_std::testing::MockStorage;
223
224 #[test]
225 fn ensure_proper_range_bounds() {
226 let mut store = MockStorage::new();
227 let prefix: IndexPrefix<Vec<u8>, u64> = IndexPrefix {
229 inner: crate::prefix::Prefix {
230 storage_prefix: b"foo".to_vec(),
231 data: PhantomData::<(u64, _, _)>,
232 },
233 pk_name: vec![],
234 de_fn_kv: |_, _, kv| deserialize_kv::<Vec<u8>, u64>(kv),
235 de_fn_v: |_, _, kv| deserialize_v(kv),
236 };
237
238 store.set(b"foobar", b"1");
240 store.set(b"foora", b"2");
241 store.set(b"foozi", b"3");
242 store.set(b"foply", b"100");
244 store.set(b"font", b"200");
245
246 let expected = vec![
247 (b"bar".to_vec(), 1u64),
248 (b"ra".to_vec(), 2u64),
249 (b"zi".to_vec(), 3u64),
250 ];
251 let expected_reversed: Vec<(Vec<u8>, u64)> = expected.iter().rev().cloned().collect();
252
253 let res: StdResult<Vec<_>> = prefix
255 .range_raw(&store, None, None, Order::Ascending)
256 .collect();
257 assert_eq!(&expected, &res.unwrap());
258 let res: StdResult<Vec<_>> = prefix
259 .range_raw(&store, None, None, Order::Descending)
260 .collect();
261 assert_eq!(&expected_reversed, &res.unwrap());
262
263 let res: StdResult<Vec<_>> = prefix
265 .range_raw(
266 &store,
267 Some(Bound::inclusive(b"ra".to_vec())),
268 None,
269 Order::Ascending,
270 )
271 .collect();
272 assert_eq!(&expected[1..], res.unwrap().as_slice());
273 let res: StdResult<Vec<_>> = prefix
275 .range_raw(
276 &store,
277 Some(Bound::exclusive(b"ra".to_vec())),
278 None,
279 Order::Ascending,
280 )
281 .collect();
282 assert_eq!(&expected[2..], res.unwrap().as_slice());
283 let res: StdResult<Vec<_>> = prefix
285 .range_raw(
286 &store,
287 Some(Bound::exclusive(b"r".to_vec())),
288 None,
289 Order::Ascending,
290 )
291 .collect();
292 assert_eq!(&expected[1..], res.unwrap().as_slice());
293
294 let res: StdResult<Vec<_>> = prefix
296 .range_raw(
297 &store,
298 None,
299 Some(Bound::inclusive(b"ra".to_vec())),
300 Order::Descending,
301 )
302 .collect();
303 assert_eq!(&expected_reversed[1..], res.unwrap().as_slice());
304 let res: StdResult<Vec<_>> = prefix
306 .range_raw(
307 &store,
308 None,
309 Some(Bound::exclusive(b"ra".to_vec())),
310 Order::Descending,
311 )
312 .collect();
313 assert_eq!(&expected_reversed[2..], res.unwrap().as_slice());
314 let res: StdResult<Vec<_>> = prefix
316 .range_raw(
317 &store,
318 None,
319 Some(Bound::exclusive(b"rb".to_vec())),
320 Order::Descending,
321 )
322 .collect();
323 assert_eq!(&expected_reversed[1..], res.unwrap().as_slice());
324
325 let res: StdResult<Vec<_>> = prefix
327 .range_raw(
328 &store,
329 Some(Bound::inclusive(b"ra".to_vec())),
330 Some(Bound::exclusive(b"zi".to_vec())),
331 Order::Ascending,
332 )
333 .collect();
334 assert_eq!(&expected[1..2], res.unwrap().as_slice());
335 let res: StdResult<Vec<_>> = prefix
337 .range_raw(
338 &store,
339 Some(Bound::inclusive(b"ra".to_vec())),
340 Some(Bound::exclusive(b"zi".to_vec())),
341 Order::Descending,
342 )
343 .collect();
344 assert_eq!(&expected[1..2], res.unwrap().as_slice());
345 let res: StdResult<Vec<_>> = prefix
347 .range_raw(
348 &store,
349 Some(Bound::inclusive(b"ra".to_vec())),
350 Some(Bound::inclusive(b"zi".to_vec())),
351 Order::Descending,
352 )
353 .collect();
354 assert_eq!(&expected_reversed[..2], res.unwrap().as_slice());
355 let res: StdResult<Vec<_>> = prefix
357 .range_raw(
358 &store,
359 Some(Bound::exclusive(b"ra".to_vec())),
360 Some(Bound::exclusive(b"zi".to_vec())),
361 Order::Ascending,
362 )
363 .collect();
364 assert_eq!(res.unwrap().as_slice(), &[]);
365 }
366
367 #[test]
368 fn prefix_debug() {
369 let prefix: IndexPrefix<String, String> = IndexPrefix::new(b"lol", &[Key::Val8([8; 1])]);
370 assert_eq!(
371 format!("{prefix:?}"),
372 "IndexPrefix { storage_prefix: [0, 3, 108, 111, 108, 0, 1, 8], pk_name: [], .. }"
373 );
374 }
375
376 #[test]
377 fn is_empty_works() {
378 let prefix: IndexPrefix<Vec<u8>, u64> = IndexPrefix {
380 inner: crate::prefix::Prefix {
381 storage_prefix: b"foo".to_vec(),
382 data: PhantomData::<(u64, _, _)>,
383 },
384 pk_name: vec![],
385 de_fn_kv: |_, _, kv| deserialize_kv::<Vec<u8>, u64>(kv),
386 de_fn_v: |_, _, kv| deserialize_v(kv),
387 };
388
389 let mut storage = MockStorage::new();
390
391 assert!(prefix.is_empty(&storage));
392
393 storage.set(b"fookey1", b"1");
394 storage.set(b"fookey2", b"2");
395
396 assert!(!prefix.is_empty(&storage));
397 }
398}