1#![cfg(feature = "iterator")]
2use core::fmt;
3use cosmwasm_std::storage_keys::to_length_prefixed_nested;
4use serde::de::DeserializeOwned;
5use serde::Serialize;
6use std::fmt::Debug;
7use std::marker::PhantomData;
8
9use cosmwasm_std::{Order, Record, StdResult, Storage};
10use std::ops::Deref;
11
12use crate::bound::{PrefixBound, RawBound};
13use crate::de::KeyDeserialize;
14use crate::iter_helpers::{concat, deserialize_kv, deserialize_v, trim};
15use crate::keys::Key;
16use crate::{Bound, Prefixer, PrimaryKey};
17
18#[derive(Clone)]
19pub struct Prefix<K, T, B = Vec<u8>>
20where
21 K: KeyDeserialize,
22 T: Serialize + DeserializeOwned,
23{
24 pub(crate) storage_prefix: Vec<u8>,
26 pub(crate) data: PhantomData<(T, K, B)>,
28}
29
30impl<K, T> Debug for Prefix<K, T>
31where
32 K: KeyDeserialize,
33 T: Serialize + DeserializeOwned,
34{
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 f.debug_struct("Prefix")
37 .field("storage_prefix", &self.storage_prefix)
38 .finish_non_exhaustive()
39 }
40}
41
42impl<K, T> Deref for Prefix<K, T>
43where
44 K: KeyDeserialize,
45 T: Serialize + DeserializeOwned,
46{
47 type Target = [u8];
48
49 fn deref(&self) -> &[u8] {
50 &self.storage_prefix
51 }
52}
53
54impl<K, T, B> Prefix<K, T, B>
55where
56 K: KeyDeserialize,
57 T: Serialize + DeserializeOwned,
58{
59 pub fn new(top_name: &[u8], sub_names: &[Key]) -> Self {
60 let calculated_len = 1 + sub_names.len();
61 let mut combined: Vec<&[u8]> = Vec::with_capacity(calculated_len);
62 combined.push(top_name);
63 combined.extend(sub_names.iter().map(|sub_name| sub_name.as_ref()));
64 debug_assert_eq!(calculated_len, combined.len()); let storage_prefix = to_length_prefixed_nested(&combined);
66 Prefix {
67 storage_prefix,
68 data: PhantomData,
69 }
70 }
71}
72
73impl<'b, K, T, B> Prefix<K, T, B>
74where
75 B: PrimaryKey<'b>,
76 K: KeyDeserialize,
77 T: Serialize + DeserializeOwned,
78{
79 pub fn range_raw<'a>(
80 &self,
81 store: &'a dyn Storage,
82 min: Option<Bound<'b, B>>,
83 max: Option<Bound<'b, B>>,
84 order: Order,
85 ) -> Box<dyn Iterator<Item = StdResult<Record<T>>> + 'a>
86 where
87 T: 'a,
88 {
89 let mapped = range_with_prefix(
90 store,
91 &self.storage_prefix,
92 min.map(|b| b.to_raw_bound()),
93 max.map(|b| b.to_raw_bound()),
94 order,
95 )
96 .map(deserialize_v);
97 Box::new(mapped)
98 }
99
100 pub fn keys_raw<'a>(
101 &self,
102 store: &'a dyn Storage,
103 min: Option<Bound<'b, B>>,
104 max: Option<Bound<'b, B>>,
105 order: Order,
106 ) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
107 keys_with_prefix(
108 store,
109 &self.storage_prefix,
110 min.map(|b| b.to_raw_bound()),
111 max.map(|b| b.to_raw_bound()),
112 order,
113 )
114 }
115
116 pub fn clear(&self, store: &mut dyn Storage, limit: Option<usize>) {
118 const TAKE: usize = 10;
119 let mut cleared = false;
120
121 let mut left_to_clear = limit.unwrap_or(usize::MAX);
122
123 while !cleared {
124 let take = TAKE.min(left_to_clear);
127
128 let paths = keys_full(store, &self.storage_prefix, None, None, Order::Ascending)
129 .take(take)
130 .collect::<Vec<_>>();
131
132 for path in &paths {
133 store.remove(path);
134 }
135 left_to_clear -= paths.len();
136
137 cleared = paths.len() < take || left_to_clear == 0;
138 }
139 }
140
141 pub fn is_empty(&self, store: &dyn Storage) -> bool {
143 keys_full(store, &self.storage_prefix, None, None, Order::Ascending)
144 .next()
145 .is_none()
146 }
147
148 pub fn range<'a>(
149 &self,
150 store: &'a dyn Storage,
151 min: Option<Bound<'b, B>>,
152 max: Option<Bound<'b, B>>,
153 order: Order,
154 ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'a>
155 where
156 T: 'a,
157 K::Output: 'static,
158 {
159 let mapped = range_with_prefix(
160 store,
161 &self.storage_prefix,
162 min.map(|b| b.to_raw_bound()),
163 max.map(|b| b.to_raw_bound()),
164 order,
165 )
166 .map(|kv| deserialize_kv::<K, T>(kv));
167 Box::new(mapped)
168 }
169
170 pub fn keys<'a>(
171 &self,
172 store: &'a dyn Storage,
173 min: Option<Bound<'b, B>>,
174 max: Option<Bound<'b, B>>,
175 order: Order,
176 ) -> Box<dyn Iterator<Item = StdResult<K::Output>> + 'a>
177 where
178 T: 'a,
179 K::Output: 'static,
180 {
181 let mapped = keys_with_prefix(
182 store,
183 &self.storage_prefix,
184 min.map(|b| b.to_raw_bound()),
185 max.map(|b| b.to_raw_bound()),
186 order,
187 )
188 .map(|k| K::from_vec(k));
189 Box::new(mapped)
190 }
191}
192
193pub fn range_with_prefix<'a>(
196 storage: &'a dyn Storage,
197 namespace: &[u8],
198 start: Option<RawBound>,
199 end: Option<RawBound>,
200 order: Order,
201) -> Box<dyn Iterator<Item = Record> + 'a> {
202 let prefix = namespace.to_vec();
204 let mapped =
205 range_full(storage, namespace, start, end, order).map(move |(k, v)| (trim(&prefix, &k), v));
206 Box::new(mapped)
207}
208
209pub fn keys_with_prefix<'a>(
212 storage: &'a dyn Storage,
213 namespace: &[u8],
214 start: Option<RawBound>,
215 end: Option<RawBound>,
216 order: Order,
217) -> Box<dyn Iterator<Item = Vec<u8>> + 'a> {
218 let prefix = namespace.to_vec();
220 let mapped = keys_full(storage, namespace, start, end, order).map(move |k| trim(&prefix, &k));
221 Box::new(mapped)
222}
223
224pub(crate) fn range_full<'a>(
227 store: &'a dyn Storage,
228 namespace: &[u8],
229 start: Option<RawBound>,
230 end: Option<RawBound>,
231 order: Order,
232) -> impl Iterator<Item = Record> + 'a {
233 let start = calc_start_bound(namespace, start);
234 let end = calc_end_bound(namespace, end);
235
236 store.range(Some(&start), Some(&end), order)
238}
239
240pub(crate) fn keys_full<'a>(
243 store: &'a dyn Storage,
244 namespace: &[u8],
245 start: Option<RawBound>,
246 end: Option<RawBound>,
247 order: Order,
248) -> impl Iterator<Item = Vec<u8>> + 'a {
249 let start = calc_start_bound(namespace, start);
250 let end = calc_end_bound(namespace, end);
251
252 store.range_keys(Some(&start), Some(&end), order)
254}
255
256fn calc_start_bound(namespace: &[u8], bound: Option<RawBound>) -> Vec<u8> {
257 match bound {
258 None => namespace.to_vec(),
259 Some(RawBound::Inclusive(limit)) => concat(namespace, &limit),
261 Some(RawBound::Exclusive(limit)) => concat(namespace, &extend_one_byte(&limit)),
262 }
263}
264
265fn calc_end_bound(namespace: &[u8], bound: Option<RawBound>) -> Vec<u8> {
266 match bound {
267 None => increment_last_byte(namespace),
268 Some(RawBound::Exclusive(limit)) => concat(namespace, &limit),
270 Some(RawBound::Inclusive(limit)) => concat(namespace, &extend_one_byte(&limit)),
271 }
272}
273
274pub fn namespaced_prefix_range<'a, 'c, K: Prefixer<'a>>(
275 storage: &'c dyn Storage,
276 namespace: &[u8],
277 start: Option<PrefixBound<'a, K>>,
278 end: Option<PrefixBound<'a, K>>,
279 order: Order,
280) -> Box<dyn Iterator<Item = Record> + 'c> {
281 let prefix = to_length_prefixed_nested(&[namespace]);
282 let start = calc_prefix_start_bound(&prefix, start);
283 let end = calc_prefix_end_bound(&prefix, end);
284
285 let base_iterator = storage.range(Some(&start), Some(&end), order);
287
288 let mapped = base_iterator.map(move |(k, v)| (trim(&prefix, &k), v));
290 Box::new(mapped)
291}
292
293fn calc_prefix_start_bound<'a, K: Prefixer<'a>>(
294 namespace: &[u8],
295 bound: Option<PrefixBound<'a, K>>,
296) -> Vec<u8> {
297 match bound.map(|b| b.to_raw_bound()) {
298 None => namespace.to_vec(),
299 Some(RawBound::Inclusive(limit)) => concat(namespace, &limit),
301 Some(RawBound::Exclusive(limit)) => concat(namespace, &increment_last_byte(&limit)),
302 }
303}
304
305fn calc_prefix_end_bound<'a, K: Prefixer<'a>>(
306 namespace: &[u8],
307 bound: Option<PrefixBound<'a, K>>,
308) -> Vec<u8> {
309 match bound.map(|b| b.to_raw_bound()) {
310 None => increment_last_byte(namespace),
311 Some(RawBound::Exclusive(limit)) => concat(namespace, &limit),
313 Some(RawBound::Inclusive(limit)) => concat(namespace, &increment_last_byte(&limit)),
314 }
315}
316
317pub(crate) fn extend_one_byte(limit: &[u8]) -> Vec<u8> {
318 let mut v = limit.to_vec();
319 v.push(0);
320 v
321}
322
323fn increment_last_byte(input: &[u8]) -> Vec<u8> {
327 let mut copy = input.to_vec();
328 for i in (0..input.len()).rev() {
330 if copy[i] == 255 {
331 copy[i] = 0;
332 } else {
333 copy[i] += 1;
334 break;
335 }
336 }
337 copy
338}
339
340#[cfg(test)]
341mod test {
342 use super::*;
343 use cosmwasm_std::testing::MockStorage;
344
345 #[test]
346 fn ensure_proper_range_bounds() {
347 let mut store = MockStorage::new();
348 let prefix: Prefix<Vec<u8>, u64> = Prefix {
350 storage_prefix: b"foo".to_vec(),
351 data: PhantomData,
352 };
353
354 store.set(b"foobar", b"1");
356 store.set(b"foora", b"2");
357 store.set(b"foozi", b"3");
358 store.set(b"foply", b"100");
360 store.set(b"font", b"200");
361
362 let expected = vec![
363 (b"bar".to_vec(), 1u64),
364 (b"ra".to_vec(), 2u64),
365 (b"zi".to_vec(), 3u64),
366 ];
367 let expected_reversed: Vec<(Vec<u8>, u64)> = expected.iter().rev().cloned().collect();
368
369 let res: StdResult<Vec<_>> = prefix
371 .range_raw(&store, None, None, Order::Ascending)
372 .collect();
373 assert_eq!(&expected, &res.unwrap());
374 let res: StdResult<Vec<_>> = prefix
375 .range_raw(&store, None, None, Order::Descending)
376 .collect();
377 assert_eq!(&expected_reversed, &res.unwrap());
378
379 let res: StdResult<Vec<_>> = prefix
381 .range_raw(
382 &store,
383 Some(Bound::inclusive(b"ra".to_vec())),
384 None,
385 Order::Ascending,
386 )
387 .collect();
388 assert_eq!(&expected[1..], res.unwrap().as_slice());
389 let res: StdResult<Vec<_>> = prefix
391 .range_raw(
392 &store,
393 Some(Bound::exclusive(b"ra".to_vec())),
394 None,
395 Order::Ascending,
396 )
397 .collect();
398 assert_eq!(&expected[2..], res.unwrap().as_slice());
399 let res: StdResult<Vec<_>> = prefix
401 .range_raw(
402 &store,
403 Some(Bound::exclusive(b"r".to_vec())),
404 None,
405 Order::Ascending,
406 )
407 .collect();
408 assert_eq!(&expected[1..], res.unwrap().as_slice());
409
410 let res: StdResult<Vec<_>> = prefix
412 .range_raw(
413 &store,
414 None,
415 Some(Bound::inclusive(b"ra".to_vec())),
416 Order::Descending,
417 )
418 .collect();
419 assert_eq!(&expected_reversed[1..], res.unwrap().as_slice());
420 let res: StdResult<Vec<_>> = prefix
422 .range_raw(
423 &store,
424 None,
425 Some(Bound::exclusive(b"ra".to_vec())),
426 Order::Descending,
427 )
428 .collect();
429 assert_eq!(&expected_reversed[2..], res.unwrap().as_slice());
430 let res: StdResult<Vec<_>> = prefix
432 .range_raw(
433 &store,
434 None,
435 Some(Bound::exclusive(b"rb".to_vec())),
436 Order::Descending,
437 )
438 .collect();
439 assert_eq!(&expected_reversed[1..], res.unwrap().as_slice());
440
441 let res: StdResult<Vec<_>> = prefix
443 .range_raw(
444 &store,
445 Some(Bound::inclusive(b"ra".to_vec())),
446 Some(Bound::exclusive(b"zi".to_vec())),
447 Order::Ascending,
448 )
449 .collect();
450 assert_eq!(&expected[1..2], res.unwrap().as_slice());
451 let res: StdResult<Vec<_>> = prefix
453 .range_raw(
454 &store,
455 Some(Bound::inclusive(b"ra".to_vec())),
456 Some(Bound::exclusive(b"zi".to_vec())),
457 Order::Descending,
458 )
459 .collect();
460 assert_eq!(&expected[1..2], res.unwrap().as_slice());
461 let res: StdResult<Vec<_>> = prefix
463 .range_raw(
464 &store,
465 Some(Bound::inclusive(b"ra".to_vec())),
466 Some(Bound::inclusive(b"zi".to_vec())),
467 Order::Descending,
468 )
469 .collect();
470 assert_eq!(&expected_reversed[..2], res.unwrap().as_slice());
471 let res: StdResult<Vec<_>> = prefix
473 .range_raw(
474 &store,
475 Some(Bound::exclusive(b"ra".to_vec())),
476 Some(Bound::exclusive(b"zi".to_vec())),
477 Order::Ascending,
478 )
479 .collect();
480 assert_eq!(res.unwrap().as_slice(), &[]);
481 }
482
483 #[test]
484 fn prefix_debug() {
485 let prefix: Prefix<String, String> = Prefix::new(b"lol", &[Key::Val8([8; 1])]);
486 assert_eq!(
487 format!("{:?}", prefix),
488 "Prefix { storage_prefix: [0, 3, 108, 111, 108, 0, 1, 8], .. }"
489 );
490 }
491
492 #[test]
493 fn prefix_clear_limited() {
494 let mut store = MockStorage::new();
495 let prefix: Prefix<Vec<u8>, u64> = Prefix {
497 storage_prefix: b"foo".to_vec(),
498 data: PhantomData,
499 };
500
501 for i in 0..100u32 {
503 store.set(format!("foo{}", i).as_bytes(), b"1");
504 }
505
506 prefix.clear(&mut store, Some(1));
508 assert_eq!(
509 prefix.range(&store, None, None, Order::Ascending).count(),
510 99
511 );
512
513 prefix.clear(&mut store, Some(12));
515 assert_eq!(
516 prefix.range(&store, None, None, Order::Ascending).count(),
517 99 - 12
518 );
519
520 prefix.clear(&mut store, Some(20));
522 assert_eq!(
523 prefix.range(&store, None, None, Order::Ascending).count(),
524 99 - 12 - 20
525 );
526
527 prefix.clear(&mut store, Some(1000));
529 assert_eq!(
530 prefix.range(&store, None, None, Order::Ascending).count(),
531 0
532 );
533 }
534
535 #[test]
536 fn prefix_clear_unlimited() {
537 let mut store = MockStorage::new();
538 let prefix: Prefix<Vec<u8>, u64> = Prefix {
540 storage_prefix: b"foo".to_vec(),
541 data: PhantomData,
542 };
543
544 for i in 0..1000u32 {
546 store.set(format!("foo{}", i).as_bytes(), b"1");
547 }
548
549 prefix.clear(&mut store, None);
551 assert_eq!(
552 prefix.range(&store, None, None, Order::Ascending).count(),
553 0
554 );
555
556 for i in 0..5u32 {
558 store.set(format!("foo{}", i).as_bytes(), b"1");
559 }
560
561 prefix.clear(&mut store, None);
563 assert_eq!(
564 prefix.range(&store, None, None, Order::Ascending).count(),
565 0
566 );
567 }
568
569 #[test]
570 fn is_empty_works() {
571 let prefix: Prefix<Vec<u8>, u64> = Prefix {
573 storage_prefix: b"foo".to_vec(),
574 data: PhantomData,
575 };
576
577 let mut storage = MockStorage::new();
578
579 assert!(prefix.is_empty(&storage));
580
581 storage.set(b"fookey1", b"1");
582 storage.set(b"fookey2", b"2");
583
584 assert!(!prefix.is_empty(&storage));
585 }
586
587 #[test]
588 fn keys_raw_works() {
589 let prefix: Prefix<Vec<u8>, u64> = Prefix {
591 storage_prefix: b"foo".to_vec(),
592 data: PhantomData,
593 };
594
595 let mut storage = MockStorage::new();
596 storage.set(b"fookey1", b"1");
597 storage.set(b"fookey2", b"2");
598
599 let keys: Vec<_> = prefix
600 .keys_raw(&storage, None, None, Order::Ascending)
601 .collect();
602 assert_eq!(keys, vec![b"key1", b"key2"]);
603
604 let keys: Vec<_> = prefix
605 .keys_raw(
606 &storage,
607 Some(Bound::exclusive("key1")),
608 None,
609 Order::Ascending,
610 )
611 .collect();
612 assert_eq!(keys, vec![b"key2"]);
613 }
614}