cw_storage_plus/
indexed_map.rs

1// this module requires iterator to be useful at all
2#![cfg(feature = "iterator")]
3
4use crate::namespace::Namespace;
5use crate::PrefixBound;
6use cosmwasm_std::{StdError, StdResult, Storage};
7use serde::de::DeserializeOwned;
8use serde::Serialize;
9
10use crate::de::KeyDeserialize;
11use crate::indexes::Index;
12use crate::iter_helpers::{deserialize_kv, deserialize_v};
13use crate::keys::{Prefixer, PrimaryKey};
14use crate::map::Map;
15use crate::prefix::{namespaced_prefix_range, Prefix};
16use crate::{Bound, Path};
17
18pub trait IndexList<T> {
19    fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<T>> + '_>;
20}
21
22/// `IndexedMap` works like a `Map` but has a secondary index
23pub struct IndexedMap<K, T, I> {
24    pk_namespace: Namespace,
25    primary: Map<K, T>,
26    /// This is meant to be read directly to get the proper types, like:
27    /// map.idx.owner.items(...)
28    pub idx: I,
29}
30
31impl<'a, K, T, I> IndexedMap<K, T, I>
32where
33    K: PrimaryKey<'a>,
34    T: Serialize + DeserializeOwned + Clone,
35    I: IndexList<T>,
36{
37    /// Creates a new [`IndexedMap`] with the given storage key. This is a constant function only suitable
38    /// when you have a prefix in the form of a static string slice.
39    pub const fn new(pk_namespace: &'static str, indexes: I) -> Self {
40        IndexedMap {
41            pk_namespace: Namespace::from_static_str(pk_namespace),
42            primary: Map::new(pk_namespace),
43            idx: indexes,
44        }
45    }
46
47    /// Creates a new [`IndexedMap`] with the given storage key. Use this if you might need to handle
48    /// a dynamic string. Otherwise, you should probably prefer [`IndexedMap::new`].
49    pub fn new_dyn(pk_namespace: impl Into<Namespace>, indexes: I) -> Self {
50        let pk_namespace = pk_namespace.into();
51
52        IndexedMap {
53            pk_namespace: pk_namespace.clone(),
54            primary: Map::new_dyn(pk_namespace),
55            idx: indexes,
56        }
57    }
58
59    pub fn key(&self, k: K) -> Path<T> {
60        self.primary.key(k)
61    }
62}
63
64impl<'a, K, T, I> IndexedMap<K, T, I>
65where
66    K: PrimaryKey<'a>,
67    T: Serialize + DeserializeOwned + Clone,
68    I: IndexList<T>,
69{
70    /// save will serialize the model and store, returns an error on serialization issues.
71    /// this must load the old value to update the indexes properly
72    /// if you loaded the old value earlier in the same function, use replace to avoid needless db reads
73    pub fn save(&self, store: &mut dyn Storage, key: K, data: &T) -> StdResult<()> {
74        let old_data = self.may_load(store, key.clone())?;
75        self.replace(store, key, Some(data), old_data.as_ref())
76    }
77
78    pub fn remove(&self, store: &mut dyn Storage, key: K) -> StdResult<()> {
79        let old_data = self.may_load(store, key.clone())?;
80        self.replace(store, key, None, old_data.as_ref())
81    }
82
83    /// replace writes data to key. old_data must be the current stored value (from a previous load)
84    /// and is used to properly update the index. This is used by save, replace, and update
85    /// and can be called directly if you want to optimize
86    pub fn replace(
87        &self,
88        store: &mut dyn Storage,
89        key: K,
90        data: Option<&T>,
91        old_data: Option<&T>,
92    ) -> StdResult<()> {
93        // this is the key *relative* to the primary map namespace
94        let pk = key.joined_key();
95        if let Some(old) = old_data {
96            for index in self.idx.get_indexes() {
97                index.remove(store, &pk, old)?;
98            }
99        }
100        if let Some(updated) = data {
101            for index in self.idx.get_indexes() {
102                index.save(store, &pk, updated)?;
103            }
104            self.primary.save(store, key, updated)?;
105        } else {
106            self.primary.remove(store, key);
107        }
108        Ok(())
109    }
110
111    /// Loads the data, perform the specified action, and store the result
112    /// in the database. This is shorthand for some common sequences, which may be useful.
113    ///
114    /// If the data exists, `action(Some(value))` is called. Otherwise `action(None)` is called.
115    pub fn update<A, E>(&self, store: &mut dyn Storage, key: K, action: A) -> Result<T, E>
116    where
117        A: FnOnce(Option<T>) -> Result<T, E>,
118        E: From<StdError>,
119    {
120        let input = self.may_load(store, key.clone())?;
121        let old_val = input.clone();
122        let output = action(input)?;
123        self.replace(store, key, Some(&output), old_val.as_ref())?;
124        Ok(output)
125    }
126
127    // Everything else, that doesn't touch indexers, is just pass-through from self.core,
128    // thus can be used from while iterating over indexes
129
130    /// load will return an error if no data is set at the given key, or on parse error
131    pub fn load(&self, store: &dyn Storage, key: K) -> StdResult<T> {
132        self.primary.load(store, key)
133    }
134
135    /// may_load will parse the data stored at the key if present, returns Ok(None) if no data there.
136    /// returns an error on issues parsing
137    pub fn may_load(&self, store: &dyn Storage, key: K) -> StdResult<Option<T>> {
138        self.primary.may_load(store, key)
139    }
140
141    /// Returns true if storage contains this key, without parsing or interpreting the contents.
142    pub fn has(&self, store: &dyn Storage, k: K) -> bool {
143        self.primary.key(k).has(store)
144    }
145
146    // use no_prefix to scan -> range
147    fn no_prefix_raw(&self) -> Prefix<Vec<u8>, T, K> {
148        Prefix::new(self.pk_namespace.as_slice(), &[])
149    }
150
151    /// Clears the map, removing all elements.
152    pub fn clear(&self, store: &mut dyn Storage) {
153        const TAKE: usize = 10;
154        let mut cleared = false;
155
156        while !cleared {
157            let paths = self
158                .no_prefix_raw()
159                .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
160                .map(|raw_key| Path::<T>::new(self.pk_namespace.as_slice(), &[raw_key.as_slice()]))
161                // Take just TAKE elements to prevent possible heap overflow if the Map is big.
162                .take(TAKE)
163                .collect::<Vec<_>>();
164
165            paths.iter().for_each(|path| store.remove(path));
166
167            cleared = paths.len() < TAKE;
168        }
169    }
170
171    /// Returns `true` if the map is empty.
172    pub fn is_empty(&self, store: &dyn Storage) -> bool {
173        self.no_prefix_raw()
174            .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
175            .next()
176            .is_none()
177    }
178}
179
180#[cfg(feature = "iterator")]
181impl<'a, K, T, I> IndexedMap<K, T, I>
182where
183    K: PrimaryKey<'a>,
184    T: Serialize + DeserializeOwned + Clone,
185    I: IndexList<T>,
186{
187    /// While `range_raw` over a `prefix` fixes the prefix to one element and iterates over the
188    /// remaining, `prefix_range_raw` accepts bounds for the lowest and highest elements of the `Prefix`
189    /// itself, and iterates over those (inclusively or exclusively, depending on `PrefixBound`).
190    /// There are some issues that distinguish these two, and blindly casting to `Vec<u8>` doesn't
191    /// solve them.
192    pub fn prefix_range_raw<'c>(
193        &self,
194        store: &'c dyn Storage,
195        min: Option<PrefixBound<'a, K::Prefix>>,
196        max: Option<PrefixBound<'a, K::Prefix>>,
197        order: cosmwasm_std::Order,
198    ) -> Box<dyn Iterator<Item = StdResult<cosmwasm_std::Record<T>>> + 'c>
199    where
200        T: 'c,
201        'a: 'c,
202    {
203        let mapped = namespaced_prefix_range(store, self.pk_namespace.as_slice(), min, max, order)
204            .map(deserialize_v);
205        Box::new(mapped)
206    }
207}
208
209#[cfg(feature = "iterator")]
210impl<'a, K, T, I> IndexedMap<K, T, I>
211where
212    T: Serialize + DeserializeOwned + Clone,
213    K: PrimaryKey<'a>,
214    I: IndexList<T>,
215{
216    pub fn sub_prefix(&self, p: K::SubPrefix) -> Prefix<K::SuperSuffix, T, K::SuperSuffix> {
217        Prefix::new(self.pk_namespace.as_slice(), &p.prefix())
218    }
219
220    pub fn prefix(&self, p: K::Prefix) -> Prefix<K::Suffix, T, K::Suffix> {
221        Prefix::new(self.pk_namespace.as_slice(), &p.prefix())
222    }
223}
224
225#[cfg(feature = "iterator")]
226impl<'a, K, T, I> IndexedMap<K, T, I>
227where
228    T: Serialize + DeserializeOwned + Clone,
229    K: PrimaryKey<'a> + KeyDeserialize,
230    I: IndexList<T>,
231{
232    /// While `range` over a `prefix` fixes the prefix to one element and iterates over the
233    /// remaining, `prefix_range` accepts bounds for the lowest and highest elements of the
234    /// `Prefix` itself, and iterates over those (inclusively or exclusively, depending on
235    /// `PrefixBound`).
236    /// There are some issues that distinguish these two, and blindly casting to `Vec<u8>` doesn't
237    /// solve them.
238    pub fn prefix_range<'c>(
239        &self,
240        store: &'c dyn Storage,
241        min: Option<PrefixBound<'a, K::Prefix>>,
242        max: Option<PrefixBound<'a, K::Prefix>>,
243        order: cosmwasm_std::Order,
244    ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'c>
245    where
246        T: 'c,
247        'a: 'c,
248        K: 'c,
249        K::Output: 'static,
250    {
251        let mapped = namespaced_prefix_range(store, self.pk_namespace.as_slice(), min, max, order)
252            .map(deserialize_kv::<K, T>);
253        Box::new(mapped)
254    }
255
256    pub fn range_raw<'c>(
257        &self,
258        store: &'c dyn Storage,
259        min: Option<Bound<'a, K>>,
260        max: Option<Bound<'a, K>>,
261        order: cosmwasm_std::Order,
262    ) -> Box<dyn Iterator<Item = StdResult<cosmwasm_std::Record<T>>> + 'c>
263    where
264        T: 'c,
265    {
266        self.no_prefix_raw().range_raw(store, min, max, order)
267    }
268
269    pub fn keys_raw<'c>(
270        &self,
271        store: &'c dyn Storage,
272        min: Option<Bound<'a, K>>,
273        max: Option<Bound<'a, K>>,
274        order: cosmwasm_std::Order,
275    ) -> Box<dyn Iterator<Item = Vec<u8>> + 'c> {
276        self.no_prefix_raw().keys_raw(store, min, max, order)
277    }
278
279    pub fn range<'c>(
280        &self,
281        store: &'c dyn Storage,
282        min: Option<Bound<'a, K>>,
283        max: Option<Bound<'a, K>>,
284        order: cosmwasm_std::Order,
285    ) -> Box<dyn Iterator<Item = StdResult<(K::Output, T)>> + 'c>
286    where
287        T: 'c,
288        K::Output: 'static,
289    {
290        self.no_prefix().range(store, min, max, order)
291    }
292
293    pub fn keys<'c>(
294        &self,
295        store: &'c dyn Storage,
296        min: Option<Bound<'a, K>>,
297        max: Option<Bound<'a, K>>,
298        order: cosmwasm_std::Order,
299    ) -> Box<dyn Iterator<Item = StdResult<K::Output>> + 'c>
300    where
301        T: 'c,
302        K::Output: 'static,
303    {
304        self.no_prefix().keys(store, min, max, order)
305    }
306
307    fn no_prefix(&self) -> Prefix<K, T, K> {
308        Prefix::new(self.pk_namespace.as_slice(), &[])
309    }
310}
311
312#[cfg(test)]
313mod test {
314
315    use super::*;
316
317    use crate::indexes::test::{index_string_tuple, index_tuple};
318    use crate::{MultiIndex, UniqueIndex};
319    use cosmwasm_std::testing::MockStorage;
320    use cosmwasm_std::Order;
321    use serde::{Deserialize, Serialize};
322
323    #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
324    struct Data {
325        pub name: String,
326        pub last_name: String,
327        pub age: u32,
328    }
329
330    struct DataIndexes<'a> {
331        // Last type parameters are for signaling pk deserialization
332        pub name: MultiIndex<'a, String, Data, String>,
333        pub age: UniqueIndex<'a, u32, Data, String>,
334        pub name_lastname: UniqueIndex<'a, (Vec<u8>, Vec<u8>), Data, String>,
335    }
336
337    // Future Note: this can likely be macro-derived
338    impl IndexList<Data> for DataIndexes<'_> {
339        fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
340            let v: Vec<&dyn Index<Data>> = vec![&self.name, &self.age, &self.name_lastname];
341            Box::new(v.into_iter())
342        }
343    }
344
345    // For composite multi index tests
346    struct DataCompositeMultiIndex<'a> {
347        // Last type parameter is for signaling pk deserialization
348        pub name_age: MultiIndex<'a, (Vec<u8>, u32), Data, String>,
349    }
350
351    // Future Note: this can likely be macro-derived
352    impl IndexList<Data> for DataCompositeMultiIndex<'_> {
353        fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
354            let v: Vec<&dyn Index<Data>> = vec![&self.name_age];
355            Box::new(v.into_iter())
356        }
357    }
358
359    const DATA: IndexedMap<&str, Data, DataIndexes> = IndexedMap::new(
360        "data",
361        DataIndexes {
362            name: MultiIndex::new(|_pk, d| d.name.clone(), "data", "data__name"),
363            age: UniqueIndex::new(|d| d.age, "data__age"),
364            name_lastname: UniqueIndex::new(
365                |d| index_string_tuple(&d.name, &d.last_name),
366                "data__name_lastname",
367            ),
368        },
369    );
370
371    fn save_data<'a>(store: &mut MockStorage) -> (Vec<&'a str>, Vec<Data>) {
372        let mut pks = vec![];
373        let mut datas = vec![];
374        let data = Data {
375            name: "Maria".to_string(),
376            last_name: "Doe".to_string(),
377            age: 42,
378        };
379        let pk = "1";
380        DATA.save(store, pk, &data).unwrap();
381        pks.push(pk);
382        datas.push(data);
383
384        // same name (multi-index), different last name, different age => ok
385        let data = Data {
386            name: "Maria".to_string(),
387            last_name: "Williams".to_string(),
388            age: 23,
389        };
390        let pk = "2";
391        DATA.save(store, pk, &data).unwrap();
392        pks.push(pk);
393        datas.push(data);
394
395        // different name, different last name, different age => ok
396        let data = Data {
397            name: "John".to_string(),
398            last_name: "Wayne".to_string(),
399            age: 32,
400        };
401        let pk = "3";
402        DATA.save(store, pk, &data).unwrap();
403        pks.push(pk);
404        datas.push(data);
405
406        let data = Data {
407            name: "Maria Luisa".to_string(),
408            last_name: "Rodriguez".to_string(),
409            age: 12,
410        };
411        let pk = "4";
412        DATA.save(store, pk, &data).unwrap();
413        pks.push(pk);
414        datas.push(data);
415
416        let data = Data {
417            name: "Marta".to_string(),
418            last_name: "After".to_string(),
419            age: 90,
420        };
421        let pk = "5";
422        DATA.save(store, pk, &data).unwrap();
423        pks.push(pk);
424        datas.push(data);
425
426        (pks, datas)
427    }
428
429    #[test]
430    fn store_and_load_by_index() {
431        let mut store = MockStorage::new();
432
433        // save data
434        let (pks, datas) = save_data(&mut store);
435        let pk = pks[0];
436        let data = &datas[0];
437
438        // load it properly
439        let loaded = DATA.load(&store, pk).unwrap();
440        assert_eq!(*data, loaded);
441
442        let count = DATA
443            .idx
444            .name
445            .prefix("Maria".to_string())
446            .range_raw(&store, None, None, Order::Ascending)
447            .count();
448        assert_eq!(2, count);
449
450        // load it by secondary index
451        let marias: Vec<_> = DATA
452            .idx
453            .name
454            .prefix("Maria".to_string())
455            .range_raw(&store, None, None, Order::Ascending)
456            .collect::<StdResult<_>>()
457            .unwrap();
458        assert_eq!(2, marias.len());
459        let (k, v) = &marias[0];
460        assert_eq!(pk, String::from_slice(k).unwrap());
461        assert_eq!(data, v);
462
463        // other index doesn't match (1 byte after)
464        let count = DATA
465            .idx
466            .name
467            .prefix("Marib".to_string())
468            .range_raw(&store, None, None, Order::Ascending)
469            .count();
470        assert_eq!(0, count);
471
472        // other index doesn't match (1 byte before)
473        let count = DATA
474            .idx
475            .name
476            .prefix("Mari`".to_string())
477            .range_raw(&store, None, None, Order::Ascending)
478            .count();
479        assert_eq!(0, count);
480
481        // other index doesn't match (longer)
482        let count = DATA
483            .idx
484            .name
485            .prefix("Maria5".to_string())
486            .range_raw(&store, None, None, Order::Ascending)
487            .count();
488        assert_eq!(0, count);
489
490        // In a MultiIndex, the index key is composed by the index and the primary key.
491        // Primary key may be empty (so that to iterate over all elements that match just the index)
492        let key = ("Maria".to_string(), "".to_string());
493        // Iterate using an inclusive bound over the key
494        let marias = DATA
495            .idx
496            .name
497            .range_raw(&store, Some(Bound::inclusive(key)), None, Order::Ascending)
498            .collect::<StdResult<Vec<_>>>()
499            .unwrap();
500        // gets from the first "Maria" until the end
501        assert_eq!(4, marias.len());
502
503        // This is equivalent to using prefix_range
504        let key = "Maria".to_string();
505        let marias2 = DATA
506            .idx
507            .name
508            .prefix_range_raw(
509                &store,
510                Some(PrefixBound::inclusive(key)),
511                None,
512                Order::Ascending,
513            )
514            .collect::<StdResult<Vec<_>>>()
515            .unwrap();
516        assert_eq!(4, marias2.len());
517        assert_eq!(marias, marias2);
518
519        // Build key including a non-empty pk
520        let key = ("Maria".to_string(), "1".to_string());
521        // Iterate using a (exclusive) bound over the key.
522        // (Useful for pagination / continuation contexts).
523        let count = DATA
524            .idx
525            .name
526            .range_raw(&store, Some(Bound::exclusive(key)), None, Order::Ascending)
527            .count();
528        // gets from the 2nd "Maria" until the end
529        assert_eq!(3, count);
530
531        // index_key() over UniqueIndex works.
532        let age_key = 23u32;
533        // Iterate using a (inclusive) bound over the key.
534        let count = DATA
535            .idx
536            .age
537            .range_raw(
538                &store,
539                Some(Bound::inclusive(age_key)),
540                None,
541                Order::Ascending,
542            )
543            .count();
544        // gets all the greater than or equal to 23 years old people
545        assert_eq!(4, count);
546
547        // match on proper age
548        let proper = 42u32;
549        let aged = DATA.idx.age.item(&store, proper).unwrap().unwrap();
550        assert_eq!(pk, String::from_vec(aged.0).unwrap());
551        assert_eq!(*data, aged.1);
552
553        // no match on wrong age
554        let too_old = 43u32;
555        let aged = DATA.idx.age.item(&store, too_old).unwrap();
556        assert_eq!(None, aged);
557    }
558
559    #[test]
560    fn existence() {
561        let mut store = MockStorage::new();
562        let (pks, _) = save_data(&mut store);
563
564        assert!(DATA.has(&store, pks[0]));
565        assert!(!DATA.has(&store, "6"));
566    }
567
568    #[test]
569    fn range_raw_simple_key_by_multi_index() {
570        let mut store = MockStorage::new();
571
572        // save data
573        let data1 = Data {
574            name: "Maria".to_string(),
575            last_name: "".to_string(),
576            age: 42,
577        };
578        let pk = "5627";
579        DATA.save(&mut store, pk, &data1).unwrap();
580
581        let data2 = Data {
582            name: "Juan".to_string(),
583            last_name: "Perez".to_string(),
584            age: 13,
585        };
586        let pk = "5628";
587        DATA.save(&mut store, pk, &data2).unwrap();
588
589        let data3 = Data {
590            name: "Maria".to_string(),
591            last_name: "Williams".to_string(),
592            age: 24,
593        };
594        let pk = "5629";
595        DATA.save(&mut store, pk, &data3).unwrap();
596
597        let data4 = Data {
598            name: "Maria Luisa".to_string(),
599            last_name: "Bemberg".to_string(),
600            age: 12,
601        };
602        let pk = "5630";
603        DATA.save(&mut store, pk, &data4).unwrap();
604
605        let marias: Vec<_> = DATA
606            .idx
607            .name
608            .prefix("Maria".to_string())
609            .range_raw(&store, None, None, Order::Descending)
610            .collect::<StdResult<_>>()
611            .unwrap();
612        let count = marias.len();
613        assert_eq!(2, count);
614
615        // Pks, sorted by (descending) pk
616        assert_eq!(marias[0].0, b"5629");
617        assert_eq!(marias[1].0, b"5627");
618        // Data is correct
619        assert_eq!(marias[0].1, data3);
620        assert_eq!(marias[1].1, data1);
621    }
622
623    #[test]
624    fn range_simple_key_by_multi_index() {
625        let mut store = MockStorage::new();
626
627        // save data
628        let data1 = Data {
629            name: "Maria".to_string(),
630            last_name: "".to_string(),
631            age: 42,
632        };
633        let pk = "5627";
634        DATA.save(&mut store, pk, &data1).unwrap();
635
636        let data2 = Data {
637            name: "Juan".to_string(),
638            last_name: "Perez".to_string(),
639            age: 13,
640        };
641        let pk = "5628";
642        DATA.save(&mut store, pk, &data2).unwrap();
643
644        let data3 = Data {
645            name: "Maria".to_string(),
646            last_name: "Williams".to_string(),
647            age: 24,
648        };
649        let pk = "5629";
650        DATA.save(&mut store, pk, &data3).unwrap();
651
652        let data4 = Data {
653            name: "Maria Luisa".to_string(),
654            last_name: "Bemberg".to_string(),
655            age: 12,
656        };
657        let pk = "5630";
658        DATA.save(&mut store, pk, &data4).unwrap();
659
660        let marias: Vec<_> = DATA
661            .idx
662            .name
663            .prefix("Maria".to_string())
664            .range(&store, None, None, Order::Descending)
665            .collect::<StdResult<_>>()
666            .unwrap();
667        let count = marias.len();
668        assert_eq!(2, count);
669
670        // Pks, sorted by (descending) pk
671        assert_eq!(marias[0].0, "5629");
672        assert_eq!(marias[1].0, "5627");
673        // Data is correct
674        assert_eq!(marias[0].1, data3);
675        assert_eq!(marias[1].1, data1);
676    }
677
678    #[test]
679    fn range_raw_composite_key_by_multi_index() {
680        let mut store = MockStorage::new();
681
682        let indexes = DataCompositeMultiIndex {
683            name_age: MultiIndex::new(
684                |_pk, d| index_tuple(&d.name, d.age),
685                "data",
686                "data__name_age",
687            ),
688        };
689        let map = IndexedMap::new("data", indexes);
690
691        // save data
692        let data1 = Data {
693            name: "Maria".to_string(),
694            last_name: "".to_string(),
695            age: 42,
696        };
697        let pk1: &[u8] = b"5627";
698        map.save(&mut store, pk1, &data1).unwrap();
699
700        let data2 = Data {
701            name: "Juan".to_string(),
702            last_name: "Perez".to_string(),
703            age: 13,
704        };
705        let pk2: &[u8] = b"5628";
706        map.save(&mut store, pk2, &data2).unwrap();
707
708        let data3 = Data {
709            name: "Maria".to_string(),
710            last_name: "Young".to_string(),
711            age: 24,
712        };
713        let pk3: &[u8] = b"5629";
714        map.save(&mut store, pk3, &data3).unwrap();
715
716        let data4 = Data {
717            name: "Maria Luisa".to_string(),
718            last_name: "Bemberg".to_string(),
719            age: 43,
720        };
721        let pk4: &[u8] = b"5630";
722        map.save(&mut store, pk4, &data4).unwrap();
723
724        let marias: Vec<_> = map
725            .idx
726            .name_age
727            .sub_prefix(b"Maria".to_vec())
728            .range_raw(&store, None, None, Order::Descending)
729            .collect::<StdResult<_>>()
730            .unwrap();
731        let count = marias.len();
732        assert_eq!(2, count);
733
734        // Pks, sorted by (descending) age
735        assert_eq!(pk1, marias[0].0);
736        assert_eq!(pk3, marias[1].0);
737
738        // Data
739        assert_eq!(data1, marias[0].1);
740        assert_eq!(data3, marias[1].1);
741    }
742
743    #[test]
744    fn range_composite_key_by_multi_index() {
745        let mut store = MockStorage::new();
746
747        let indexes = DataCompositeMultiIndex {
748            name_age: MultiIndex::new(
749                |_pk, d| index_tuple(&d.name, d.age),
750                "data",
751                "data__name_age",
752            ),
753        };
754        let map = IndexedMap::new("data", indexes);
755
756        // save data
757        let data1 = Data {
758            name: "Maria".to_string(),
759            last_name: "".to_string(),
760            age: 42,
761        };
762        let pk1 = "5627";
763        map.save(&mut store, pk1, &data1).unwrap();
764
765        let data2 = Data {
766            name: "Juan".to_string(),
767            last_name: "Perez".to_string(),
768            age: 13,
769        };
770        let pk2 = "5628";
771        map.save(&mut store, pk2, &data2).unwrap();
772
773        let data3 = Data {
774            name: "Maria".to_string(),
775            last_name: "Young".to_string(),
776            age: 24,
777        };
778        let pk3 = "5629";
779        map.save(&mut store, pk3, &data3).unwrap();
780
781        let data4 = Data {
782            name: "Maria Luisa".to_string(),
783            last_name: "Bemberg".to_string(),
784            age: 43,
785        };
786        let pk4 = "5630";
787        map.save(&mut store, pk4, &data4).unwrap();
788
789        let marias: Vec<_> = map
790            .idx
791            .name_age
792            .sub_prefix(b"Maria".to_vec())
793            .range(&store, None, None, Order::Descending)
794            .collect::<StdResult<_>>()
795            .unwrap();
796        let count = marias.len();
797        assert_eq!(2, count);
798
799        // Pks, sorted by (descending) age
800        assert_eq!(pk1, marias[0].0);
801        assert_eq!(pk3, marias[1].0);
802
803        // Data
804        assert_eq!(data1, marias[0].1);
805        assert_eq!(data3, marias[1].1);
806    }
807
808    #[test]
809    fn unique_index_enforced() {
810        let mut store = MockStorage::new();
811
812        // save data
813        let (pks, datas) = save_data(&mut store);
814
815        // different name, different last name, same age => error
816        let data5 = Data {
817            name: "Marcel".to_string(),
818            last_name: "Laurens".to_string(),
819            age: 42,
820        };
821        let pk5 = "4";
822
823        // enforce this returns some error
824        DATA.save(&mut store, pk5, &data5).unwrap_err();
825
826        // query by unique key
827        // match on proper age
828        let age42 = 42u32;
829        let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
830        assert_eq!(String::from_vec(k).unwrap(), pks[0]);
831        assert_eq!(v.name, datas[0].name);
832        assert_eq!(v.age, datas[0].age);
833
834        // match on other age
835        let age23 = 23u32;
836        let (k, v) = DATA.idx.age.item(&store, age23).unwrap().unwrap();
837        assert_eq!(String::from_vec(k).unwrap(), pks[1]);
838        assert_eq!(v.name, datas[1].name);
839        assert_eq!(v.age, datas[1].age);
840
841        // if we delete the first one, we can add the blocked one
842        DATA.remove(&mut store, pks[0]).unwrap();
843        DATA.save(&mut store, pk5, &data5).unwrap();
844        // now 42 is the new owner
845        let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
846        assert_eq!(String::from_vec(k).unwrap(), pk5);
847        assert_eq!(v.name, data5.name);
848        assert_eq!(v.age, data5.age);
849    }
850
851    #[test]
852    fn unique_index_enforced_composite_key() {
853        let mut store = MockStorage::new();
854
855        // save data
856        save_data(&mut store);
857
858        // same name, same lastname => error
859        let data5 = Data {
860            name: "Maria".to_string(),
861            last_name: "Doe".to_string(),
862            age: 24,
863        };
864        let pk5 = "5";
865        // enforce this returns some error
866        DATA.save(&mut store, pk5, &data5).unwrap_err();
867    }
868
869    #[test]
870    fn remove_and_update_reflected_on_indexes() {
871        let mut store = MockStorage::new();
872
873        let name_count = |store: &MockStorage, name: &str| -> usize {
874            DATA.idx
875                .name
876                .prefix(name.to_string())
877                .keys_raw(store, None, None, Order::Ascending)
878                .count()
879        };
880
881        // save data
882        let (pks, _) = save_data(&mut store);
883
884        // find 2 Marias, 1 John, and no Mary
885        assert_eq!(name_count(&store, "Maria"), 2);
886        assert_eq!(name_count(&store, "John"), 1);
887        assert_eq!(name_count(&store, "Maria Luisa"), 1);
888        assert_eq!(name_count(&store, "Mary"), 0);
889
890        // remove maria 2
891        DATA.remove(&mut store, pks[1]).unwrap();
892
893        // change john to mary
894        DATA.update(&mut store, pks[2], |d| -> StdResult<_> {
895            let mut x = d.unwrap();
896            assert_eq!(&x.name, "John");
897            x.name = "Mary".to_string();
898            Ok(x)
899        })
900        .unwrap();
901
902        // find 1 maria, 1 maria luisa, no john, and 1 mary
903        assert_eq!(name_count(&store, "Maria"), 1);
904        assert_eq!(name_count(&store, "Maria Luisa"), 1);
905        assert_eq!(name_count(&store, "John"), 0);
906        assert_eq!(name_count(&store, "Mary"), 1);
907    }
908
909    #[test]
910    fn range_raw_simple_key_by_unique_index() {
911        let mut store = MockStorage::new();
912
913        // save data
914        let (pks, datas) = save_data(&mut store);
915
916        let res: StdResult<Vec<_>> = DATA
917            .idx
918            .age
919            .range_raw(&store, None, None, Order::Ascending)
920            .collect();
921        let ages = res.unwrap();
922
923        let count = ages.len();
924        assert_eq!(5, count);
925
926        // The pks, sorted by age ascending
927        assert_eq!(pks[3], String::from_slice(&ages[0].0).unwrap()); // 12
928        assert_eq!(pks[1], String::from_slice(&ages[1].0).unwrap()); // 23
929        assert_eq!(pks[2], String::from_slice(&ages[2].0).unwrap()); // 32
930        assert_eq!(pks[0], String::from_slice(&ages[3].0).unwrap()); // 42
931        assert_eq!(pks[4], String::from_slice(&ages[4].0).unwrap()); // 90
932
933        // The associated data
934        assert_eq!(datas[3], ages[0].1);
935        assert_eq!(datas[1], ages[1].1);
936        assert_eq!(datas[2], ages[2].1);
937        assert_eq!(datas[0], ages[3].1);
938        assert_eq!(datas[4], ages[4].1);
939    }
940
941    #[test]
942    fn range_simple_key_by_unique_index() {
943        let mut store = MockStorage::new();
944
945        // save data
946        let (pks, datas) = save_data(&mut store);
947
948        let res: StdResult<Vec<_>> = DATA
949            .idx
950            .age
951            .range(&store, None, None, Order::Ascending)
952            .collect();
953        let ages = res.unwrap();
954
955        let count = ages.len();
956        assert_eq!(5, count);
957
958        // The pks, sorted by age ascending
959        assert_eq!(pks[3], ages[0].0);
960        assert_eq!(pks[1], ages[1].0);
961        assert_eq!(pks[2], ages[2].0);
962        assert_eq!(pks[0], ages[3].0);
963        assert_eq!(pks[4], ages[4].0);
964
965        // The associated data
966        assert_eq!(datas[3], ages[0].1);
967        assert_eq!(datas[1], ages[1].1);
968        assert_eq!(datas[2], ages[2].1);
969        assert_eq!(datas[0], ages[3].1);
970        assert_eq!(datas[4], ages[4].1);
971    }
972
973    #[test]
974    fn range_raw_composite_key_by_unique_index() {
975        let mut store = MockStorage::new();
976
977        // save data
978        let (pks, datas) = save_data(&mut store);
979
980        let res: StdResult<Vec<_>> = DATA
981            .idx
982            .name_lastname
983            .prefix(b"Maria".to_vec())
984            .range_raw(&store, None, None, Order::Ascending)
985            .collect();
986        let marias = res.unwrap();
987
988        // Only two people are called "Maria"
989        let count = marias.len();
990        assert_eq!(2, count);
991
992        // The pks
993        assert_eq!(pks[0], String::from_slice(&marias[0].0).unwrap());
994        assert_eq!(pks[1], String::from_slice(&marias[1].0).unwrap());
995
996        // The associated data
997        assert_eq!(datas[0], marias[0].1);
998        assert_eq!(datas[1], marias[1].1);
999    }
1000
1001    #[test]
1002    fn range_composite_key_by_unique_index() {
1003        let mut store = MockStorage::new();
1004
1005        // save data
1006        let (pks, datas) = save_data(&mut store);
1007
1008        let res: StdResult<Vec<_>> = DATA
1009            .idx
1010            .name_lastname
1011            .prefix(b"Maria".to_vec())
1012            .range(&store, None, None, Order::Ascending)
1013            .collect();
1014        let marias = res.unwrap();
1015
1016        // Only two people are called "Maria"
1017        let count = marias.len();
1018        assert_eq!(2, count);
1019
1020        // The pks
1021        assert_eq!(pks[0], marias[0].0);
1022        assert_eq!(pks[1], marias[1].0);
1023
1024        // The associated data
1025        assert_eq!(datas[0], marias[0].1);
1026        assert_eq!(datas[1], marias[1].1);
1027    }
1028
1029    #[test]
1030    #[cfg(feature = "iterator")]
1031    fn range_simple_string_key() {
1032        let mut store = MockStorage::new();
1033
1034        // save data
1035        let (pks, datas) = save_data(&mut store);
1036
1037        // let's try to iterate!
1038        let all: StdResult<Vec<_>> = DATA.range(&store, None, None, Order::Ascending).collect();
1039        let all = all.unwrap();
1040        assert_eq!(
1041            all,
1042            pks.clone()
1043                .into_iter()
1044                .map(str::to_string)
1045                .zip(datas.clone().into_iter())
1046                .collect::<Vec<_>>()
1047        );
1048
1049        // let's try to iterate over a range
1050        let all: StdResult<Vec<_>> = DATA
1051            .range(&store, Some(Bound::inclusive("3")), None, Order::Ascending)
1052            .collect();
1053        let all = all.unwrap();
1054        assert_eq!(
1055            all,
1056            pks.into_iter()
1057                .map(str::to_string)
1058                .zip(datas.into_iter())
1059                .rev()
1060                .take(3)
1061                .rev()
1062                .collect::<Vec<_>>()
1063        );
1064    }
1065
1066    #[test]
1067    #[cfg(feature = "iterator")]
1068    fn prefix_simple_string_key() {
1069        let mut store = MockStorage::new();
1070
1071        // save data
1072        let (pks, datas) = save_data(&mut store);
1073
1074        // Let's prefix and iterate.
1075        // This is similar to calling range() directly, but added here for completeness / prefix
1076        // type checks
1077        let all: StdResult<Vec<_>> = DATA
1078            .prefix(())
1079            .range(&store, None, None, Order::Ascending)
1080            .collect();
1081        let all = all.unwrap();
1082        assert_eq!(
1083            all,
1084            pks.clone()
1085                .into_iter()
1086                .map(str::to_string)
1087                .zip(datas.into_iter())
1088                .collect::<Vec<_>>()
1089        );
1090    }
1091
1092    #[test]
1093    #[cfg(feature = "iterator")]
1094    fn prefix_composite_key() {
1095        let mut store = MockStorage::new();
1096
1097        let indexes = DataCompositeMultiIndex {
1098            name_age: MultiIndex::new(
1099                |_pk, d| index_tuple(&d.name, d.age),
1100                "data",
1101                "data__name_age",
1102            ),
1103        };
1104        let map = IndexedMap::new("data", indexes);
1105
1106        // save data
1107        let data1 = Data {
1108            name: "Maria".to_string(),
1109            last_name: "".to_string(),
1110            age: 42,
1111        };
1112        let pk1 = ("1", "5627");
1113        map.save(&mut store, pk1, &data1).unwrap();
1114
1115        let data2 = Data {
1116            name: "Juan".to_string(),
1117            last_name: "Perez".to_string(),
1118            age: 13,
1119        };
1120        let pk2 = ("2", "5628");
1121        map.save(&mut store, pk2, &data2).unwrap();
1122
1123        let data3 = Data {
1124            name: "Maria".to_string(),
1125            last_name: "Young".to_string(),
1126            age: 24,
1127        };
1128        let pk3 = ("2", "5629");
1129        map.save(&mut store, pk3, &data3).unwrap();
1130
1131        let data4 = Data {
1132            name: "Maria Luisa".to_string(),
1133            last_name: "Bemberg".to_string(),
1134            age: 43,
1135        };
1136        let pk4 = ("3", "5630");
1137        map.save(&mut store, pk4, &data4).unwrap();
1138
1139        // let's prefix and iterate
1140        let result: StdResult<Vec<_>> = map
1141            .prefix("2")
1142            .range(&store, None, None, Order::Ascending)
1143            .collect();
1144        let result = result.unwrap();
1145        assert_eq!(
1146            result,
1147            [("5628".to_string(), data2), ("5629".to_string(), data3),]
1148        );
1149    }
1150
1151    #[test]
1152    #[cfg(feature = "iterator")]
1153    fn prefix_triple_key() {
1154        let mut store = MockStorage::new();
1155
1156        let indexes = DataCompositeMultiIndex {
1157            name_age: MultiIndex::new(
1158                |_pk, d| index_tuple(&d.name, d.age),
1159                "data",
1160                "data__name_age",
1161            ),
1162        };
1163        let map = IndexedMap::new("data", indexes);
1164
1165        // save data
1166        let data1 = Data {
1167            name: "Maria".to_string(),
1168            last_name: "".to_string(),
1169            age: 42,
1170        };
1171        let pk1 = ("1", "1", "5627");
1172        map.save(&mut store, pk1, &data1).unwrap();
1173
1174        let data2 = Data {
1175            name: "Juan".to_string(),
1176            last_name: "Perez".to_string(),
1177            age: 13,
1178        };
1179        let pk2 = ("1", "2", "5628");
1180        map.save(&mut store, pk2, &data2).unwrap();
1181
1182        let data3 = Data {
1183            name: "Maria".to_string(),
1184            last_name: "Young".to_string(),
1185            age: 24,
1186        };
1187        let pk3 = ("2", "1", "5629");
1188        map.save(&mut store, pk3, &data3).unwrap();
1189
1190        let data4 = Data {
1191            name: "Maria Luisa".to_string(),
1192            last_name: "Bemberg".to_string(),
1193            age: 43,
1194        };
1195        let pk4 = ("2", "2", "5630");
1196        map.save(&mut store, pk4, &data4).unwrap();
1197
1198        // let's prefix and iterate
1199        let result: StdResult<Vec<_>> = map
1200            .prefix(("1", "2"))
1201            .range(&store, None, None, Order::Ascending)
1202            .collect();
1203        let result = result.unwrap();
1204        assert_eq!(result, [("5628".to_string(), data2),]);
1205    }
1206
1207    #[test]
1208    #[cfg(feature = "iterator")]
1209    fn sub_prefix_triple_key() {
1210        let mut store = MockStorage::new();
1211
1212        let indexes = DataCompositeMultiIndex {
1213            name_age: MultiIndex::new(
1214                |_pk, d| index_tuple(&d.name, d.age),
1215                "data",
1216                "data__name_age",
1217            ),
1218        };
1219        let map = IndexedMap::new("data", indexes);
1220
1221        // save data
1222        let data1 = Data {
1223            name: "Maria".to_string(),
1224            last_name: "".to_string(),
1225            age: 42,
1226        };
1227        let pk1 = ("1", "1", "5627");
1228        map.save(&mut store, pk1, &data1).unwrap();
1229
1230        let data2 = Data {
1231            name: "Juan".to_string(),
1232            last_name: "Perez".to_string(),
1233            age: 13,
1234        };
1235        let pk2 = ("1", "2", "5628");
1236        map.save(&mut store, pk2, &data2).unwrap();
1237
1238        let data3 = Data {
1239            name: "Maria".to_string(),
1240            last_name: "Young".to_string(),
1241            age: 24,
1242        };
1243        let pk3 = ("2", "1", "5629");
1244        map.save(&mut store, pk3, &data3).unwrap();
1245
1246        let data4 = Data {
1247            name: "Maria Luisa".to_string(),
1248            last_name: "Bemberg".to_string(),
1249            age: 43,
1250        };
1251        let pk4 = ("2", "2", "5630");
1252        map.save(&mut store, pk4, &data4).unwrap();
1253
1254        // let's sub-prefix and iterate
1255        let result: StdResult<Vec<_>> = map
1256            .sub_prefix("1")
1257            .range(&store, None, None, Order::Ascending)
1258            .collect();
1259        let result = result.unwrap();
1260        assert_eq!(
1261            result,
1262            [
1263                (("1".to_string(), "5627".to_string()), data1),
1264                (("2".to_string(), "5628".to_string()), data2),
1265            ]
1266        );
1267    }
1268
1269    #[test]
1270    #[cfg(feature = "iterator")]
1271    fn prefix_range_simple_key() {
1272        let mut store = MockStorage::new();
1273
1274        let indexes = DataCompositeMultiIndex {
1275            name_age: MultiIndex::new(
1276                |_pk, d| index_tuple(&d.name, d.age),
1277                "data",
1278                "data__name_age",
1279            ),
1280        };
1281        let map = IndexedMap::new("data", indexes);
1282
1283        // save data
1284        let data1 = Data {
1285            name: "Maria".to_string(),
1286            last_name: "".to_string(),
1287            age: 42,
1288        };
1289        let pk1 = ("1", "5627");
1290        map.save(&mut store, pk1, &data1).unwrap();
1291
1292        let data2 = Data {
1293            name: "Juan".to_string(),
1294            last_name: "Perez".to_string(),
1295            age: 13,
1296        };
1297        let pk2 = ("2", "5628");
1298        map.save(&mut store, pk2, &data2).unwrap();
1299
1300        let data3 = Data {
1301            name: "Maria".to_string(),
1302            last_name: "Young".to_string(),
1303            age: 24,
1304        };
1305        let pk3 = ("2", "5629");
1306        map.save(&mut store, pk3, &data3).unwrap();
1307
1308        let data4 = Data {
1309            name: "Maria Luisa".to_string(),
1310            last_name: "Bemberg".to_string(),
1311            age: 43,
1312        };
1313        let pk4 = ("3", "5630");
1314        map.save(&mut store, pk4, &data4).unwrap();
1315
1316        // let's prefix-range and iterate
1317        let result: StdResult<Vec<_>> = map
1318            .prefix_range(
1319                &store,
1320                Some(PrefixBound::inclusive("2")),
1321                None,
1322                Order::Ascending,
1323            )
1324            .collect();
1325        let result = result.unwrap();
1326        assert_eq!(
1327            result,
1328            [
1329                (("2".to_string(), "5628".to_string()), data2.clone()),
1330                (("2".to_string(), "5629".to_string()), data3.clone()),
1331                (("3".to_string(), "5630".to_string()), data4)
1332            ]
1333        );
1334
1335        // let's try to iterate over a more restrictive prefix-range!
1336        let result: StdResult<Vec<_>> = map
1337            .prefix_range(
1338                &store,
1339                Some(PrefixBound::inclusive("2")),
1340                Some(PrefixBound::exclusive("3")),
1341                Order::Ascending,
1342            )
1343            .collect();
1344        let result = result.unwrap();
1345        assert_eq!(
1346            result,
1347            [
1348                (("2".to_string(), "5628".to_string()), data2),
1349                (("2".to_string(), "5629".to_string()), data3),
1350            ]
1351        );
1352    }
1353
1354    #[test]
1355    #[cfg(feature = "iterator")]
1356    fn prefix_range_triple_key() {
1357        let mut store = MockStorage::new();
1358
1359        let indexes = DataCompositeMultiIndex {
1360            name_age: MultiIndex::new(
1361                |_pk, d| index_tuple(&d.name, d.age),
1362                "data",
1363                "data__name_age",
1364            ),
1365        };
1366        let map = IndexedMap::new("data", indexes);
1367
1368        // save data
1369        let data1 = Data {
1370            name: "Maria".to_string(),
1371            last_name: "".to_string(),
1372            age: 42,
1373        };
1374        let pk1 = ("1", "1", "5627");
1375        map.save(&mut store, pk1, &data1).unwrap();
1376
1377        let data2 = Data {
1378            name: "Juan".to_string(),
1379            last_name: "Perez".to_string(),
1380            age: 13,
1381        };
1382        let pk2 = ("1", "2", "5628");
1383        map.save(&mut store, pk2, &data2).unwrap();
1384
1385        let data3 = Data {
1386            name: "Maria".to_string(),
1387            last_name: "Young".to_string(),
1388            age: 24,
1389        };
1390        let pk3 = ("2", "1", "5629");
1391        map.save(&mut store, pk3, &data3).unwrap();
1392
1393        let data4 = Data {
1394            name: "Maria Luisa".to_string(),
1395            last_name: "Bemberg".to_string(),
1396            age: 43,
1397        };
1398        let pk4 = ("2", "2", "5630");
1399        map.save(&mut store, pk4, &data4).unwrap();
1400
1401        // let's prefix-range and iterate
1402        let result: StdResult<Vec<_>> = map
1403            .prefix_range(
1404                &store,
1405                Some(PrefixBound::inclusive(("1", "2"))),
1406                None,
1407                Order::Ascending,
1408            )
1409            .collect();
1410        let result = result.unwrap();
1411        assert_eq!(
1412            result,
1413            [
1414                (
1415                    ("1".to_string(), "2".to_string(), "5628".to_string()),
1416                    data2.clone()
1417                ),
1418                (
1419                    ("2".to_string(), "1".to_string(), "5629".to_string()),
1420                    data3.clone()
1421                ),
1422                (
1423                    ("2".to_string(), "2".to_string(), "5630".to_string()),
1424                    data4
1425                )
1426            ]
1427        );
1428
1429        // let's prefix-range over inclusive bounds on both sides
1430        let result: StdResult<Vec<_>> = map
1431            .prefix_range(
1432                &store,
1433                Some(PrefixBound::inclusive(("1", "2"))),
1434                Some(PrefixBound::inclusive(("2", "1"))),
1435                Order::Ascending,
1436            )
1437            .collect();
1438        let result = result.unwrap();
1439        assert_eq!(
1440            result,
1441            [
1442                (
1443                    ("1".to_string(), "2".to_string(), "5628".to_string()),
1444                    data2
1445                ),
1446                (
1447                    ("2".to_string(), "1".to_string(), "5629".to_string()),
1448                    data3
1449                ),
1450            ]
1451        );
1452    }
1453
1454    mod bounds_unique_index {
1455        use super::*;
1456
1457        struct Indexes<'a> {
1458            secondary: UniqueIndex<'a, u64, u64, ()>,
1459        }
1460
1461        impl IndexList<u64> for Indexes<'_> {
1462            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1463                let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1464                Box::new(v.into_iter())
1465            }
1466        }
1467
1468        #[test]
1469        #[cfg(feature = "iterator")]
1470        fn composite_key_query() {
1471            let indexes = Indexes {
1472                secondary: UniqueIndex::new(|secondary| *secondary, "test_map__secondary"),
1473            };
1474            let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1475            let mut store = MockStorage::new();
1476
1477            map.save(&mut store, "one", &1).unwrap();
1478            map.save(&mut store, "two", &2).unwrap();
1479            map.save(&mut store, "three", &3).unwrap();
1480
1481            // Inclusive bound
1482            let items: Vec<_> = map
1483                .idx
1484                .secondary
1485                .range_raw(&store, None, Some(Bound::inclusive(1u64)), Order::Ascending)
1486                .collect::<Result<_, _>>()
1487                .unwrap();
1488
1489            // Strip the index from values (for simpler comparison)
1490            let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1491
1492            assert_eq!(items, vec![1]);
1493
1494            // Exclusive bound
1495            let items: Vec<_> = map
1496                .idx
1497                .secondary
1498                .range(&store, Some(Bound::exclusive(2u64)), None, Order::Ascending)
1499                .collect::<Result<_, _>>()
1500                .unwrap();
1501
1502            assert_eq!(items, vec![((), 3)]);
1503        }
1504    }
1505
1506    mod bounds_multi_index {
1507        use super::*;
1508
1509        struct Indexes<'a> {
1510            // The last type param must match the `IndexedMap` primary key type, below
1511            secondary: MultiIndex<'a, u64, u64, &'a str>,
1512        }
1513
1514        impl IndexList<u64> for Indexes<'_> {
1515            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1516                let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1517                Box::new(v.into_iter())
1518            }
1519        }
1520
1521        #[test]
1522        #[cfg(feature = "iterator")]
1523        fn composite_key_query() {
1524            let indexes = Indexes {
1525                secondary: MultiIndex::new(
1526                    |_pk, secondary| *secondary,
1527                    "test_map",
1528                    "test_map__secondary",
1529                ),
1530            };
1531            let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1532            let mut store = MockStorage::new();
1533
1534            map.save(&mut store, "one", &1).unwrap();
1535            map.save(&mut store, "two", &2).unwrap();
1536            map.save(&mut store, "two2", &2).unwrap();
1537            map.save(&mut store, "three", &3).unwrap();
1538
1539            // Inclusive prefix-bound
1540            let items: Vec<_> = map
1541                .idx
1542                .secondary
1543                .prefix_range_raw(
1544                    &store,
1545                    None,
1546                    Some(PrefixBound::inclusive(1u64)),
1547                    Order::Ascending,
1548                )
1549                .collect::<Result<_, _>>()
1550                .unwrap();
1551
1552            // Strip the index from values (for simpler comparison)
1553            let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1554
1555            assert_eq!(items, vec![1]);
1556
1557            // Exclusive bound (used for pagination)
1558            // Range over the index specifying a primary key (multi-index key includes the pk)
1559            let items: Vec<_> = map
1560                .idx
1561                .secondary
1562                .range(
1563                    &store,
1564                    Some(Bound::exclusive((2u64, "two"))),
1565                    None,
1566                    Order::Ascending,
1567                )
1568                .collect::<Result<_, _>>()
1569                .unwrap();
1570
1571            assert_eq!(
1572                items,
1573                vec![("two2".to_string(), 2), ("three".to_string(), 3)]
1574            );
1575        }
1576    }
1577
1578    mod pk_multi_index {
1579        use super::*;
1580        use cosmwasm_std::{Addr, Uint128};
1581
1582        struct Indexes<'a> {
1583            // The last type param must match the `IndexedMap` primary key type below
1584            spender: MultiIndex<'a, Addr, Uint128, (Addr, Addr)>,
1585        }
1586
1587        impl IndexList<Uint128> for Indexes<'_> {
1588            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Uint128>> + '_> {
1589                let v: Vec<&dyn Index<Uint128>> = vec![&self.spender];
1590                Box::new(v.into_iter())
1591            }
1592        }
1593
1594        #[test]
1595        #[cfg(feature = "iterator")]
1596        fn pk_based_index() {
1597            fn pk_index(pk: &[u8]) -> Addr {
1598                let (_owner, spender) = <(Addr, Addr)>::from_slice(pk).unwrap(); // mustn't fail
1599                spender
1600            }
1601
1602            let indexes = Indexes {
1603                spender: MultiIndex::new(
1604                    |pk, _allow| pk_index(pk),
1605                    "allowances",
1606                    "allowances__spender",
1607                ),
1608            };
1609            let map = IndexedMap::<(&Addr, &Addr), Uint128, Indexes>::new("allowances", indexes);
1610            let mut store = MockStorage::new();
1611
1612            map.save(
1613                &mut store,
1614                (&Addr::unchecked("owner1"), &Addr::unchecked("spender1")),
1615                &Uint128::new(11),
1616            )
1617            .unwrap();
1618            map.save(
1619                &mut store,
1620                (&Addr::unchecked("owner1"), &Addr::unchecked("spender2")),
1621                &Uint128::new(12),
1622            )
1623            .unwrap();
1624            map.save(
1625                &mut store,
1626                (&Addr::unchecked("owner2"), &Addr::unchecked("spender1")),
1627                &Uint128::new(21),
1628            )
1629            .unwrap();
1630
1631            // Iterate over the main values
1632            let items: Vec<_> = map
1633                .range_raw(&store, None, None, Order::Ascending)
1634                .collect::<Result<_, _>>()
1635                .unwrap();
1636
1637            // Strip the index from values (for simpler comparison)
1638            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1639
1640            assert_eq!(items, vec![11, 12, 21]);
1641
1642            // Iterate over the indexed values
1643            let items: Vec<_> = map
1644                .idx
1645                .spender
1646                .range_raw(&store, None, None, Order::Ascending)
1647                .collect::<Result<_, _>>()
1648                .unwrap();
1649
1650            // Strip the index from values (for simpler comparison)
1651            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1652
1653            assert_eq!(items, vec![11, 21, 12]);
1654
1655            // Prefix over the main values
1656            let items: Vec<_> = map
1657                .prefix(&Addr::unchecked("owner1"))
1658                .range_raw(&store, None, None, Order::Ascending)
1659                .collect::<Result<_, _>>()
1660                .unwrap();
1661
1662            // Strip the index from values (for simpler comparison)
1663            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1664
1665            assert_eq!(items, vec![11, 12]);
1666
1667            // Prefix over the indexed values
1668            let items: Vec<_> = map
1669                .idx
1670                .spender
1671                .prefix(Addr::unchecked("spender1"))
1672                .range_raw(&store, None, None, Order::Ascending)
1673                .collect::<Result<_, _>>()
1674                .unwrap();
1675
1676            // Strip the index from values (for simpler comparison)
1677            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1678
1679            assert_eq!(items, vec![11, 21]);
1680
1681            // Prefix over the indexed values, and deserialize primary key as well
1682            let items: Vec<_> = map
1683                .idx
1684                .spender
1685                .prefix(Addr::unchecked("spender2"))
1686                .range(&store, None, None, Order::Ascending)
1687                .collect::<Result<_, _>>()
1688                .unwrap();
1689
1690            assert_eq!(
1691                items,
1692                vec![(
1693                    (Addr::unchecked("owner1"), Addr::unchecked("spender2")),
1694                    Uint128::new(12)
1695                )]
1696            );
1697        }
1698    }
1699
1700    #[test]
1701    fn clear_works() {
1702        let mut storage = MockStorage::new();
1703        let (pks, _) = save_data(&mut storage);
1704
1705        DATA.clear(&mut storage);
1706
1707        for key in pks {
1708            assert!(!DATA.has(&storage, key));
1709        }
1710    }
1711
1712    #[test]
1713    fn is_empty_works() {
1714        let mut storage = MockStorage::new();
1715
1716        assert!(DATA.is_empty(&storage));
1717
1718        save_data(&mut storage);
1719
1720        assert!(!DATA.is_empty(&storage));
1721    }
1722}