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    use super::*;
315
316    use crate::indexes::test::{index_string_tuple, index_tuple};
317    use crate::{MultiIndex, UniqueIndex};
318    use cosmwasm_std::testing::MockStorage;
319    use cosmwasm_std::{MemoryStorage, Order};
320    use serde::{Deserialize, Serialize};
321
322    #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]
323    struct Data {
324        pub name: String,
325        pub last_name: String,
326        pub age: u32,
327    }
328
329    struct DataIndexes<'a> {
330        // Last type parameters are for signaling pk deserialization
331        pub name: MultiIndex<'a, String, Data, String>,
332        pub age: UniqueIndex<'a, u32, Data, String>,
333        pub name_lastname: UniqueIndex<'a, (Vec<u8>, Vec<u8>), Data, String>,
334    }
335
336    // Future Note: this can likely be macro-derived
337    impl<'a> IndexList<Data> for DataIndexes<'a> {
338        fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
339            let v: Vec<&dyn Index<Data>> = vec![&self.name, &self.age, &self.name_lastname];
340            Box::new(v.into_iter())
341        }
342    }
343
344    // For composite multi index tests
345    struct DataCompositeMultiIndex<'a> {
346        // Last type parameter is for signaling pk deserialization
347        pub name_age: MultiIndex<'a, (Vec<u8>, u32), Data, String>,
348    }
349
350    // Future Note: this can likely be macro-derived
351    impl<'a> IndexList<Data> for DataCompositeMultiIndex<'a> {
352        fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Data>> + '_> {
353            let v: Vec<&dyn Index<Data>> = vec![&self.name_age];
354            Box::new(v.into_iter())
355        }
356    }
357
358    const DATA: IndexedMap<&str, Data, DataIndexes> = IndexedMap::new(
359        "data",
360        DataIndexes {
361            name: MultiIndex::new(|_pk, d| d.name.clone(), "data", "data__name"),
362            age: UniqueIndex::new(|d| d.age, "data__age"),
363            name_lastname: UniqueIndex::new(
364                |d| index_string_tuple(&d.name, &d.last_name),
365                "data__name_lastname",
366            ),
367        },
368    );
369
370    fn save_data<'a>(store: &mut MockStorage) -> (Vec<&'a str>, Vec<Data>) {
371        let mut pks = vec![];
372        let mut datas = vec![];
373        let data = Data {
374            name: "Maria".to_string(),
375            last_name: "Doe".to_string(),
376            age: 42,
377        };
378        let pk = "1";
379        DATA.save(store, pk, &data).unwrap();
380        pks.push(pk);
381        datas.push(data);
382
383        // same name (multi-index), different last name, different age => ok
384        let data = Data {
385            name: "Maria".to_string(),
386            last_name: "Williams".to_string(),
387            age: 23,
388        };
389        let pk = "2";
390        DATA.save(store, pk, &data).unwrap();
391        pks.push(pk);
392        datas.push(data);
393
394        // different name, different last name, different age => ok
395        let data = Data {
396            name: "John".to_string(),
397            last_name: "Wayne".to_string(),
398            age: 32,
399        };
400        let pk = "3";
401        DATA.save(store, pk, &data).unwrap();
402        pks.push(pk);
403        datas.push(data);
404
405        let data = Data {
406            name: "Maria Luisa".to_string(),
407            last_name: "Rodriguez".to_string(),
408            age: 12,
409        };
410        let pk = "4";
411        DATA.save(store, pk, &data).unwrap();
412        pks.push(pk);
413        datas.push(data);
414
415        let data = Data {
416            name: "Marta".to_string(),
417            last_name: "After".to_string(),
418            age: 90,
419        };
420        let pk = "5";
421        DATA.save(store, pk, &data).unwrap();
422        pks.push(pk);
423        datas.push(data);
424
425        (pks, datas)
426    }
427
428    #[test]
429    fn store_and_load_by_index() {
430        let mut store = MockStorage::new();
431
432        // save data
433        let (pks, datas) = save_data(&mut store);
434        let pk = pks[0];
435        let data = &datas[0];
436
437        // load it properly
438        let loaded = DATA.load(&store, pk).unwrap();
439        assert_eq!(*data, loaded);
440
441        let count = DATA
442            .idx
443            .name
444            .prefix("Maria".to_string())
445            .range_raw(&store, None, None, Order::Ascending)
446            .count();
447        assert_eq!(2, count);
448
449        // load it by secondary index
450        let marias: Vec<_> = DATA
451            .idx
452            .name
453            .prefix("Maria".to_string())
454            .range_raw(&store, None, None, Order::Ascending)
455            .collect::<StdResult<_>>()
456            .unwrap();
457        assert_eq!(2, marias.len());
458        let (k, v) = &marias[0];
459        assert_eq!(pk, String::from_slice(k).unwrap());
460        assert_eq!(data, v);
461
462        // other index doesn't match (1 byte after)
463        let count = DATA
464            .idx
465            .name
466            .prefix("Marib".to_string())
467            .range_raw(&store, None, None, Order::Ascending)
468            .count();
469        assert_eq!(0, count);
470
471        // other index doesn't match (1 byte before)
472        let count = DATA
473            .idx
474            .name
475            .prefix("Mari`".to_string())
476            .range_raw(&store, None, None, Order::Ascending)
477            .count();
478        assert_eq!(0, count);
479
480        // other index doesn't match (longer)
481        let count = DATA
482            .idx
483            .name
484            .prefix("Maria5".to_string())
485            .range_raw(&store, None, None, Order::Ascending)
486            .count();
487        assert_eq!(0, count);
488
489        // In a MultiIndex, the index key is composed by the index and the primary key.
490        // Primary key may be empty (so that to iterate over all elements that match just the index)
491        let key = ("Maria".to_string(), "".to_string());
492        // Iterate using an inclusive bound over the key
493        let marias = DATA
494            .idx
495            .name
496            .range_raw(&store, Some(Bound::inclusive(key)), None, Order::Ascending)
497            .collect::<StdResult<Vec<_>>>()
498            .unwrap();
499        // gets from the first "Maria" until the end
500        assert_eq!(4, marias.len());
501
502        // This is equivalent to using prefix_range
503        let key = "Maria".to_string();
504        let marias2 = DATA
505            .idx
506            .name
507            .prefix_range_raw(
508                &store,
509                Some(PrefixBound::inclusive(key)),
510                None,
511                Order::Ascending,
512            )
513            .collect::<StdResult<Vec<_>>>()
514            .unwrap();
515        assert_eq!(4, marias2.len());
516        assert_eq!(marias, marias2);
517
518        // Build key including a non-empty pk
519        let key = ("Maria".to_string(), "1".to_string());
520        // Iterate using a (exclusive) bound over the key.
521        // (Useful for pagination / continuation contexts).
522        let count = DATA
523            .idx
524            .name
525            .range_raw(&store, Some(Bound::exclusive(key)), None, Order::Ascending)
526            .count();
527        // gets from the 2nd "Maria" until the end
528        assert_eq!(3, count);
529
530        // index_key() over UniqueIndex works.
531        let age_key = 23u32;
532        // Iterate using a (inclusive) bound over the key.
533        let count = DATA
534            .idx
535            .age
536            .range_raw(
537                &store,
538                Some(Bound::inclusive(age_key)),
539                None,
540                Order::Ascending,
541            )
542            .count();
543        // gets all the greater than or equal to 23 years old people
544        assert_eq!(4, count);
545
546        // match on proper age
547        let proper = 42u32;
548        let aged = DATA.idx.age.item(&store, proper).unwrap().unwrap();
549        assert_eq!(pk, String::from_vec(aged.0).unwrap());
550        assert_eq!(*data, aged.1);
551
552        // no match on wrong age
553        let too_old = 43u32;
554        let aged = DATA.idx.age.item(&store, too_old).unwrap();
555        assert_eq!(None, aged);
556    }
557
558    #[test]
559    fn existence() {
560        let mut store = MockStorage::new();
561        let (pks, _) = save_data(&mut store);
562
563        assert!(DATA.has(&store, pks[0]));
564        assert!(!DATA.has(&store, "6"));
565    }
566
567    #[test]
568    fn range_raw_simple_key_by_multi_index() {
569        let mut store = MockStorage::new();
570
571        // save data
572        let data1 = Data {
573            name: "Maria".to_string(),
574            last_name: "".to_string(),
575            age: 42,
576        };
577        let pk = "5627";
578        DATA.save(&mut store, pk, &data1).unwrap();
579
580        let data2 = Data {
581            name: "Juan".to_string(),
582            last_name: "Perez".to_string(),
583            age: 13,
584        };
585        let pk = "5628";
586        DATA.save(&mut store, pk, &data2).unwrap();
587
588        let data3 = Data {
589            name: "Maria".to_string(),
590            last_name: "Williams".to_string(),
591            age: 24,
592        };
593        let pk = "5629";
594        DATA.save(&mut store, pk, &data3).unwrap();
595
596        let data4 = Data {
597            name: "Maria Luisa".to_string(),
598            last_name: "Bemberg".to_string(),
599            age: 12,
600        };
601        let pk = "5630";
602        DATA.save(&mut store, pk, &data4).unwrap();
603
604        let marias: Vec<_> = DATA
605            .idx
606            .name
607            .prefix("Maria".to_string())
608            .range_raw(&store, None, None, Order::Descending)
609            .collect::<StdResult<_>>()
610            .unwrap();
611        let count = marias.len();
612        assert_eq!(2, count);
613
614        // Pks, sorted by (descending) pk
615        assert_eq!(marias[0].0, b"5629");
616        assert_eq!(marias[1].0, b"5627");
617        // Data is correct
618        assert_eq!(marias[0].1, data3);
619        assert_eq!(marias[1].1, data1);
620    }
621
622    #[test]
623    fn range_simple_key_by_multi_index() {
624        let mut store = MockStorage::new();
625
626        // save data
627        let data1 = Data {
628            name: "Maria".to_string(),
629            last_name: "".to_string(),
630            age: 42,
631        };
632        let pk = "5627";
633        DATA.save(&mut store, pk, &data1).unwrap();
634
635        let data2 = Data {
636            name: "Juan".to_string(),
637            last_name: "Perez".to_string(),
638            age: 13,
639        };
640        let pk = "5628";
641        DATA.save(&mut store, pk, &data2).unwrap();
642
643        let data3 = Data {
644            name: "Maria".to_string(),
645            last_name: "Williams".to_string(),
646            age: 24,
647        };
648        let pk = "5629";
649        DATA.save(&mut store, pk, &data3).unwrap();
650
651        let data4 = Data {
652            name: "Maria Luisa".to_string(),
653            last_name: "Bemberg".to_string(),
654            age: 12,
655        };
656        let pk = "5630";
657        DATA.save(&mut store, pk, &data4).unwrap();
658
659        let marias: Vec<_> = DATA
660            .idx
661            .name
662            .prefix("Maria".to_string())
663            .range(&store, None, None, Order::Descending)
664            .collect::<StdResult<_>>()
665            .unwrap();
666        let count = marias.len();
667        assert_eq!(2, count);
668
669        // Pks, sorted by (descending) pk
670        assert_eq!(marias[0].0, "5629");
671        assert_eq!(marias[1].0, "5627");
672        // Data is correct
673        assert_eq!(marias[0].1, data3);
674        assert_eq!(marias[1].1, data1);
675    }
676
677    #[test]
678    fn range_raw_composite_key_by_multi_index() {
679        let mut store = MockStorage::new();
680
681        let indexes = DataCompositeMultiIndex {
682            name_age: MultiIndex::new(
683                |_pk, d| index_tuple(&d.name, d.age),
684                "data",
685                "data__name_age",
686            ),
687        };
688        let map = IndexedMap::new("data", indexes);
689
690        // save data
691        let data1 = Data {
692            name: "Maria".to_string(),
693            last_name: "".to_string(),
694            age: 42,
695        };
696        let pk1: &[u8] = b"5627";
697        map.save(&mut store, pk1, &data1).unwrap();
698
699        let data2 = Data {
700            name: "Juan".to_string(),
701            last_name: "Perez".to_string(),
702            age: 13,
703        };
704        let pk2: &[u8] = b"5628";
705        map.save(&mut store, pk2, &data2).unwrap();
706
707        let data3 = Data {
708            name: "Maria".to_string(),
709            last_name: "Young".to_string(),
710            age: 24,
711        };
712        let pk3: &[u8] = b"5629";
713        map.save(&mut store, pk3, &data3).unwrap();
714
715        let data4 = Data {
716            name: "Maria Luisa".to_string(),
717            last_name: "Bemberg".to_string(),
718            age: 43,
719        };
720        let pk4: &[u8] = b"5630";
721        map.save(&mut store, pk4, &data4).unwrap();
722
723        let marias: Vec<_> = map
724            .idx
725            .name_age
726            .sub_prefix(b"Maria".to_vec())
727            .range_raw(&store, None, None, Order::Descending)
728            .collect::<StdResult<_>>()
729            .unwrap();
730        let count = marias.len();
731        assert_eq!(2, count);
732
733        // Pks, sorted by (descending) age
734        assert_eq!(pk1, marias[0].0);
735        assert_eq!(pk3, marias[1].0);
736
737        // Data
738        assert_eq!(data1, marias[0].1);
739        assert_eq!(data3, marias[1].1);
740    }
741
742    #[test]
743    fn range_composite_key_by_multi_index() {
744        let mut store = MockStorage::new();
745
746        let indexes = DataCompositeMultiIndex {
747            name_age: MultiIndex::new(
748                |_pk, d| index_tuple(&d.name, d.age),
749                "data",
750                "data__name_age",
751            ),
752        };
753        let map = IndexedMap::new("data", indexes);
754
755        // save data
756        let data1 = Data {
757            name: "Maria".to_string(),
758            last_name: "".to_string(),
759            age: 42,
760        };
761        let pk1 = "5627";
762        map.save(&mut store, pk1, &data1).unwrap();
763
764        let data2 = Data {
765            name: "Juan".to_string(),
766            last_name: "Perez".to_string(),
767            age: 13,
768        };
769        let pk2 = "5628";
770        map.save(&mut store, pk2, &data2).unwrap();
771
772        let data3 = Data {
773            name: "Maria".to_string(),
774            last_name: "Young".to_string(),
775            age: 24,
776        };
777        let pk3 = "5629";
778        map.save(&mut store, pk3, &data3).unwrap();
779
780        let data4 = Data {
781            name: "Maria Luisa".to_string(),
782            last_name: "Bemberg".to_string(),
783            age: 43,
784        };
785        let pk4 = "5630";
786        map.save(&mut store, pk4, &data4).unwrap();
787
788        let marias: Vec<_> = map
789            .idx
790            .name_age
791            .sub_prefix(b"Maria".to_vec())
792            .range(&store, None, None, Order::Descending)
793            .collect::<StdResult<_>>()
794            .unwrap();
795        let count = marias.len();
796        assert_eq!(2, count);
797
798        // Pks, sorted by (descending) age
799        assert_eq!(pk1, marias[0].0);
800        assert_eq!(pk3, marias[1].0);
801
802        // Data
803        assert_eq!(data1, marias[0].1);
804        assert_eq!(data3, marias[1].1);
805    }
806
807    #[test]
808    fn unique_index_enforced() {
809        let mut store = MockStorage::new();
810
811        // save data
812        let (pks, datas) = save_data(&mut store);
813
814        // different name, different last name, same age => error
815        let data5 = Data {
816            name: "Marcel".to_string(),
817            last_name: "Laurens".to_string(),
818            age: 42,
819        };
820        let pk5 = "4";
821
822        // enforce this returns some error
823        DATA.save(&mut store, pk5, &data5).unwrap_err();
824
825        // query by unique key
826        // match on proper age
827        let age42 = 42u32;
828        let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
829        assert_eq!(String::from_vec(k).unwrap(), pks[0]);
830        assert_eq!(v.name, datas[0].name);
831        assert_eq!(v.age, datas[0].age);
832
833        // match on other age
834        let age23 = 23u32;
835        let (k, v) = DATA.idx.age.item(&store, age23).unwrap().unwrap();
836        assert_eq!(String::from_vec(k).unwrap(), pks[1]);
837        assert_eq!(v.name, datas[1].name);
838        assert_eq!(v.age, datas[1].age);
839
840        // if we delete the first one, we can add the blocked one
841        DATA.remove(&mut store, pks[0]).unwrap();
842        DATA.save(&mut store, pk5, &data5).unwrap();
843        // now 42 is the new owner
844        let (k, v) = DATA.idx.age.item(&store, age42).unwrap().unwrap();
845        assert_eq!(String::from_vec(k).unwrap(), pk5);
846        assert_eq!(v.name, data5.name);
847        assert_eq!(v.age, data5.age);
848    }
849
850    #[test]
851    fn unique_index_enforced_composite_key() {
852        let mut store = MockStorage::new();
853
854        // save data
855        save_data(&mut store);
856
857        // same name, same lastname => error
858        let data5 = Data {
859            name: "Maria".to_string(),
860            last_name: "Doe".to_string(),
861            age: 24,
862        };
863        let pk5 = "5";
864        // enforce this returns some error
865        DATA.save(&mut store, pk5, &data5).unwrap_err();
866    }
867
868    #[test]
869    fn remove_and_update_reflected_on_indexes() {
870        let mut store = MockStorage::new();
871
872        let name_count = |store: &MemoryStorage, name: &str| -> usize {
873            DATA.idx
874                .name
875                .prefix(name.to_string())
876                .keys_raw(store, None, None, Order::Ascending)
877                .count()
878        };
879
880        // save data
881        let (pks, _) = save_data(&mut store);
882
883        // find 2 Marias, 1 John, and no Mary
884        assert_eq!(name_count(&store, "Maria"), 2);
885        assert_eq!(name_count(&store, "John"), 1);
886        assert_eq!(name_count(&store, "Maria Luisa"), 1);
887        assert_eq!(name_count(&store, "Mary"), 0);
888
889        // remove maria 2
890        DATA.remove(&mut store, pks[1]).unwrap();
891
892        // change john to mary
893        DATA.update(&mut store, pks[2], |d| -> StdResult<_> {
894            let mut x = d.unwrap();
895            assert_eq!(&x.name, "John");
896            x.name = "Mary".to_string();
897            Ok(x)
898        })
899        .unwrap();
900
901        // find 1 maria, 1 maria luisa, no john, and 1 mary
902        assert_eq!(name_count(&store, "Maria"), 1);
903        assert_eq!(name_count(&store, "Maria Luisa"), 1);
904        assert_eq!(name_count(&store, "John"), 0);
905        assert_eq!(name_count(&store, "Mary"), 1);
906    }
907
908    #[test]
909    fn range_raw_simple_key_by_unique_index() {
910        let mut store = MockStorage::new();
911
912        // save data
913        let (pks, datas) = save_data(&mut store);
914
915        let res: StdResult<Vec<_>> = DATA
916            .idx
917            .age
918            .range_raw(&store, None, None, Order::Ascending)
919            .collect();
920        let ages = res.unwrap();
921
922        let count = ages.len();
923        assert_eq!(5, count);
924
925        // The pks, sorted by age ascending
926        assert_eq!(pks[3], String::from_slice(&ages[0].0).unwrap()); // 12
927        assert_eq!(pks[1], String::from_slice(&ages[1].0).unwrap()); // 23
928        assert_eq!(pks[2], String::from_slice(&ages[2].0).unwrap()); // 32
929        assert_eq!(pks[0], String::from_slice(&ages[3].0).unwrap()); // 42
930        assert_eq!(pks[4], String::from_slice(&ages[4].0).unwrap()); // 90
931
932        // The associated data
933        assert_eq!(datas[3], ages[0].1);
934        assert_eq!(datas[1], ages[1].1);
935        assert_eq!(datas[2], ages[2].1);
936        assert_eq!(datas[0], ages[3].1);
937        assert_eq!(datas[4], ages[4].1);
938    }
939
940    #[test]
941    fn range_simple_key_by_unique_index() {
942        let mut store = MockStorage::new();
943
944        // save data
945        let (pks, datas) = save_data(&mut store);
946
947        let res: StdResult<Vec<_>> = DATA
948            .idx
949            .age
950            .range(&store, None, None, Order::Ascending)
951            .collect();
952        let ages = res.unwrap();
953
954        let count = ages.len();
955        assert_eq!(5, count);
956
957        // The pks, sorted by age ascending
958        assert_eq!(pks[3], ages[0].0);
959        assert_eq!(pks[1], ages[1].0);
960        assert_eq!(pks[2], ages[2].0);
961        assert_eq!(pks[0], ages[3].0);
962        assert_eq!(pks[4], ages[4].0);
963
964        // The associated data
965        assert_eq!(datas[3], ages[0].1);
966        assert_eq!(datas[1], ages[1].1);
967        assert_eq!(datas[2], ages[2].1);
968        assert_eq!(datas[0], ages[3].1);
969        assert_eq!(datas[4], ages[4].1);
970    }
971
972    #[test]
973    fn range_raw_composite_key_by_unique_index() {
974        let mut store = MockStorage::new();
975
976        // save data
977        let (pks, datas) = save_data(&mut store);
978
979        let res: StdResult<Vec<_>> = DATA
980            .idx
981            .name_lastname
982            .prefix(b"Maria".to_vec())
983            .range_raw(&store, None, None, Order::Ascending)
984            .collect();
985        let marias = res.unwrap();
986
987        // Only two people are called "Maria"
988        let count = marias.len();
989        assert_eq!(2, count);
990
991        // The pks
992        assert_eq!(pks[0], String::from_slice(&marias[0].0).unwrap());
993        assert_eq!(pks[1], String::from_slice(&marias[1].0).unwrap());
994
995        // The associated data
996        assert_eq!(datas[0], marias[0].1);
997        assert_eq!(datas[1], marias[1].1);
998    }
999
1000    #[test]
1001    fn range_composite_key_by_unique_index() {
1002        let mut store = MockStorage::new();
1003
1004        // save data
1005        let (pks, datas) = save_data(&mut store);
1006
1007        let res: StdResult<Vec<_>> = DATA
1008            .idx
1009            .name_lastname
1010            .prefix(b"Maria".to_vec())
1011            .range(&store, None, None, Order::Ascending)
1012            .collect();
1013        let marias = res.unwrap();
1014
1015        // Only two people are called "Maria"
1016        let count = marias.len();
1017        assert_eq!(2, count);
1018
1019        // The pks
1020        assert_eq!(pks[0], marias[0].0);
1021        assert_eq!(pks[1], marias[1].0);
1022
1023        // The associated data
1024        assert_eq!(datas[0], marias[0].1);
1025        assert_eq!(datas[1], marias[1].1);
1026    }
1027
1028    #[test]
1029    #[cfg(feature = "iterator")]
1030    fn range_simple_string_key() {
1031        let mut store = MockStorage::new();
1032
1033        // save data
1034        let (pks, datas) = save_data(&mut store);
1035
1036        // let's try to iterate!
1037        let all: StdResult<Vec<_>> = DATA.range(&store, None, None, Order::Ascending).collect();
1038        let all = all.unwrap();
1039        assert_eq!(
1040            all,
1041            pks.clone()
1042                .into_iter()
1043                .map(str::to_string)
1044                .zip(datas.clone().into_iter())
1045                .collect::<Vec<_>>()
1046        );
1047
1048        // let's try to iterate over a range
1049        let all: StdResult<Vec<_>> = DATA
1050            .range(&store, Some(Bound::inclusive("3")), None, Order::Ascending)
1051            .collect();
1052        let all = all.unwrap();
1053        assert_eq!(
1054            all,
1055            pks.into_iter()
1056                .map(str::to_string)
1057                .zip(datas.into_iter())
1058                .rev()
1059                .take(3)
1060                .rev()
1061                .collect::<Vec<_>>()
1062        );
1063    }
1064
1065    #[test]
1066    #[cfg(feature = "iterator")]
1067    fn prefix_simple_string_key() {
1068        let mut store = MockStorage::new();
1069
1070        // save data
1071        let (pks, datas) = save_data(&mut store);
1072
1073        // Let's prefix and iterate.
1074        // This is similar to calling range() directly, but added here for completeness / prefix
1075        // type checks
1076        let all: StdResult<Vec<_>> = DATA
1077            .prefix(())
1078            .range(&store, None, None, Order::Ascending)
1079            .collect();
1080        let all = all.unwrap();
1081        assert_eq!(
1082            all,
1083            pks.clone()
1084                .into_iter()
1085                .map(str::to_string)
1086                .zip(datas.into_iter())
1087                .collect::<Vec<_>>()
1088        );
1089    }
1090
1091    #[test]
1092    #[cfg(feature = "iterator")]
1093    fn prefix_composite_key() {
1094        let mut store = MockStorage::new();
1095
1096        let indexes = DataCompositeMultiIndex {
1097            name_age: MultiIndex::new(
1098                |_pk, d| index_tuple(&d.name, d.age),
1099                "data",
1100                "data__name_age",
1101            ),
1102        };
1103        let map = IndexedMap::new("data", indexes);
1104
1105        // save data
1106        let data1 = Data {
1107            name: "Maria".to_string(),
1108            last_name: "".to_string(),
1109            age: 42,
1110        };
1111        let pk1 = ("1", "5627");
1112        map.save(&mut store, pk1, &data1).unwrap();
1113
1114        let data2 = Data {
1115            name: "Juan".to_string(),
1116            last_name: "Perez".to_string(),
1117            age: 13,
1118        };
1119        let pk2 = ("2", "5628");
1120        map.save(&mut store, pk2, &data2).unwrap();
1121
1122        let data3 = Data {
1123            name: "Maria".to_string(),
1124            last_name: "Young".to_string(),
1125            age: 24,
1126        };
1127        let pk3 = ("2", "5629");
1128        map.save(&mut store, pk3, &data3).unwrap();
1129
1130        let data4 = Data {
1131            name: "Maria Luisa".to_string(),
1132            last_name: "Bemberg".to_string(),
1133            age: 43,
1134        };
1135        let pk4 = ("3", "5630");
1136        map.save(&mut store, pk4, &data4).unwrap();
1137
1138        // let's prefix and iterate
1139        let result: StdResult<Vec<_>> = map
1140            .prefix("2")
1141            .range(&store, None, None, Order::Ascending)
1142            .collect();
1143        let result = result.unwrap();
1144        assert_eq!(
1145            result,
1146            [("5628".to_string(), data2), ("5629".to_string(), data3),]
1147        );
1148    }
1149
1150    #[test]
1151    #[cfg(feature = "iterator")]
1152    fn prefix_triple_key() {
1153        let mut store = MockStorage::new();
1154
1155        let indexes = DataCompositeMultiIndex {
1156            name_age: MultiIndex::new(
1157                |_pk, d| index_tuple(&d.name, d.age),
1158                "data",
1159                "data__name_age",
1160            ),
1161        };
1162        let map = IndexedMap::new("data", indexes);
1163
1164        // save data
1165        let data1 = Data {
1166            name: "Maria".to_string(),
1167            last_name: "".to_string(),
1168            age: 42,
1169        };
1170        let pk1 = ("1", "1", "5627");
1171        map.save(&mut store, pk1, &data1).unwrap();
1172
1173        let data2 = Data {
1174            name: "Juan".to_string(),
1175            last_name: "Perez".to_string(),
1176            age: 13,
1177        };
1178        let pk2 = ("1", "2", "5628");
1179        map.save(&mut store, pk2, &data2).unwrap();
1180
1181        let data3 = Data {
1182            name: "Maria".to_string(),
1183            last_name: "Young".to_string(),
1184            age: 24,
1185        };
1186        let pk3 = ("2", "1", "5629");
1187        map.save(&mut store, pk3, &data3).unwrap();
1188
1189        let data4 = Data {
1190            name: "Maria Luisa".to_string(),
1191            last_name: "Bemberg".to_string(),
1192            age: 43,
1193        };
1194        let pk4 = ("2", "2", "5630");
1195        map.save(&mut store, pk4, &data4).unwrap();
1196
1197        // let's prefix and iterate
1198        let result: StdResult<Vec<_>> = map
1199            .prefix(("1", "2"))
1200            .range(&store, None, None, Order::Ascending)
1201            .collect();
1202        let result = result.unwrap();
1203        assert_eq!(result, [("5628".to_string(), data2),]);
1204    }
1205
1206    #[test]
1207    #[cfg(feature = "iterator")]
1208    fn sub_prefix_triple_key() {
1209        let mut store = MockStorage::new();
1210
1211        let indexes = DataCompositeMultiIndex {
1212            name_age: MultiIndex::new(
1213                |_pk, d| index_tuple(&d.name, d.age),
1214                "data",
1215                "data__name_age",
1216            ),
1217        };
1218        let map = IndexedMap::new("data", indexes);
1219
1220        // save data
1221        let data1 = Data {
1222            name: "Maria".to_string(),
1223            last_name: "".to_string(),
1224            age: 42,
1225        };
1226        let pk1 = ("1", "1", "5627");
1227        map.save(&mut store, pk1, &data1).unwrap();
1228
1229        let data2 = Data {
1230            name: "Juan".to_string(),
1231            last_name: "Perez".to_string(),
1232            age: 13,
1233        };
1234        let pk2 = ("1", "2", "5628");
1235        map.save(&mut store, pk2, &data2).unwrap();
1236
1237        let data3 = Data {
1238            name: "Maria".to_string(),
1239            last_name: "Young".to_string(),
1240            age: 24,
1241        };
1242        let pk3 = ("2", "1", "5629");
1243        map.save(&mut store, pk3, &data3).unwrap();
1244
1245        let data4 = Data {
1246            name: "Maria Luisa".to_string(),
1247            last_name: "Bemberg".to_string(),
1248            age: 43,
1249        };
1250        let pk4 = ("2", "2", "5630");
1251        map.save(&mut store, pk4, &data4).unwrap();
1252
1253        // let's sub-prefix and iterate
1254        let result: StdResult<Vec<_>> = map
1255            .sub_prefix("1")
1256            .range(&store, None, None, Order::Ascending)
1257            .collect();
1258        let result = result.unwrap();
1259        assert_eq!(
1260            result,
1261            [
1262                (("1".to_string(), "5627".to_string()), data1),
1263                (("2".to_string(), "5628".to_string()), data2),
1264            ]
1265        );
1266    }
1267
1268    #[test]
1269    #[cfg(feature = "iterator")]
1270    fn prefix_range_simple_key() {
1271        let mut store = MockStorage::new();
1272
1273        let indexes = DataCompositeMultiIndex {
1274            name_age: MultiIndex::new(
1275                |_pk, d| index_tuple(&d.name, d.age),
1276                "data",
1277                "data__name_age",
1278            ),
1279        };
1280        let map = IndexedMap::new("data", indexes);
1281
1282        // save data
1283        let data1 = Data {
1284            name: "Maria".to_string(),
1285            last_name: "".to_string(),
1286            age: 42,
1287        };
1288        let pk1 = ("1", "5627");
1289        map.save(&mut store, pk1, &data1).unwrap();
1290
1291        let data2 = Data {
1292            name: "Juan".to_string(),
1293            last_name: "Perez".to_string(),
1294            age: 13,
1295        };
1296        let pk2 = ("2", "5628");
1297        map.save(&mut store, pk2, &data2).unwrap();
1298
1299        let data3 = Data {
1300            name: "Maria".to_string(),
1301            last_name: "Young".to_string(),
1302            age: 24,
1303        };
1304        let pk3 = ("2", "5629");
1305        map.save(&mut store, pk3, &data3).unwrap();
1306
1307        let data4 = Data {
1308            name: "Maria Luisa".to_string(),
1309            last_name: "Bemberg".to_string(),
1310            age: 43,
1311        };
1312        let pk4 = ("3", "5630");
1313        map.save(&mut store, pk4, &data4).unwrap();
1314
1315        // let's prefix-range and iterate
1316        let result: StdResult<Vec<_>> = map
1317            .prefix_range(
1318                &store,
1319                Some(PrefixBound::inclusive("2")),
1320                None,
1321                Order::Ascending,
1322            )
1323            .collect();
1324        let result = result.unwrap();
1325        assert_eq!(
1326            result,
1327            [
1328                (("2".to_string(), "5628".to_string()), data2.clone()),
1329                (("2".to_string(), "5629".to_string()), data3.clone()),
1330                (("3".to_string(), "5630".to_string()), data4)
1331            ]
1332        );
1333
1334        // let's try to iterate over a more restrictive prefix-range!
1335        let result: StdResult<Vec<_>> = map
1336            .prefix_range(
1337                &store,
1338                Some(PrefixBound::inclusive("2")),
1339                Some(PrefixBound::exclusive("3")),
1340                Order::Ascending,
1341            )
1342            .collect();
1343        let result = result.unwrap();
1344        assert_eq!(
1345            result,
1346            [
1347                (("2".to_string(), "5628".to_string()), data2),
1348                (("2".to_string(), "5629".to_string()), data3),
1349            ]
1350        );
1351    }
1352
1353    #[test]
1354    #[cfg(feature = "iterator")]
1355    fn prefix_range_triple_key() {
1356        let mut store = MockStorage::new();
1357
1358        let indexes = DataCompositeMultiIndex {
1359            name_age: MultiIndex::new(
1360                |_pk, d| index_tuple(&d.name, d.age),
1361                "data",
1362                "data__name_age",
1363            ),
1364        };
1365        let map = IndexedMap::new("data", indexes);
1366
1367        // save data
1368        let data1 = Data {
1369            name: "Maria".to_string(),
1370            last_name: "".to_string(),
1371            age: 42,
1372        };
1373        let pk1 = ("1", "1", "5627");
1374        map.save(&mut store, pk1, &data1).unwrap();
1375
1376        let data2 = Data {
1377            name: "Juan".to_string(),
1378            last_name: "Perez".to_string(),
1379            age: 13,
1380        };
1381        let pk2 = ("1", "2", "5628");
1382        map.save(&mut store, pk2, &data2).unwrap();
1383
1384        let data3 = Data {
1385            name: "Maria".to_string(),
1386            last_name: "Young".to_string(),
1387            age: 24,
1388        };
1389        let pk3 = ("2", "1", "5629");
1390        map.save(&mut store, pk3, &data3).unwrap();
1391
1392        let data4 = Data {
1393            name: "Maria Luisa".to_string(),
1394            last_name: "Bemberg".to_string(),
1395            age: 43,
1396        };
1397        let pk4 = ("2", "2", "5630");
1398        map.save(&mut store, pk4, &data4).unwrap();
1399
1400        // let's prefix-range and iterate
1401        let result: StdResult<Vec<_>> = map
1402            .prefix_range(
1403                &store,
1404                Some(PrefixBound::inclusive(("1", "2"))),
1405                None,
1406                Order::Ascending,
1407            )
1408            .collect();
1409        let result = result.unwrap();
1410        assert_eq!(
1411            result,
1412            [
1413                (
1414                    ("1".to_string(), "2".to_string(), "5628".to_string()),
1415                    data2.clone()
1416                ),
1417                (
1418                    ("2".to_string(), "1".to_string(), "5629".to_string()),
1419                    data3.clone()
1420                ),
1421                (
1422                    ("2".to_string(), "2".to_string(), "5630".to_string()),
1423                    data4
1424                )
1425            ]
1426        );
1427
1428        // let's prefix-range over inclusive bounds on both sides
1429        let result: StdResult<Vec<_>> = map
1430            .prefix_range(
1431                &store,
1432                Some(PrefixBound::inclusive(("1", "2"))),
1433                Some(PrefixBound::inclusive(("2", "1"))),
1434                Order::Ascending,
1435            )
1436            .collect();
1437        let result = result.unwrap();
1438        assert_eq!(
1439            result,
1440            [
1441                (
1442                    ("1".to_string(), "2".to_string(), "5628".to_string()),
1443                    data2
1444                ),
1445                (
1446                    ("2".to_string(), "1".to_string(), "5629".to_string()),
1447                    data3
1448                ),
1449            ]
1450        );
1451    }
1452
1453    mod bounds_unique_index {
1454        use super::*;
1455
1456        struct Indexes<'a> {
1457            secondary: UniqueIndex<'a, u64, u64, ()>,
1458        }
1459
1460        impl<'a> IndexList<u64> for Indexes<'a> {
1461            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1462                let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1463                Box::new(v.into_iter())
1464            }
1465        }
1466
1467        #[test]
1468        #[cfg(feature = "iterator")]
1469        fn composite_key_query() {
1470            let indexes = Indexes {
1471                secondary: UniqueIndex::new(|secondary| *secondary, "test_map__secondary"),
1472            };
1473            let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1474            let mut store = MockStorage::new();
1475
1476            map.save(&mut store, "one", &1).unwrap();
1477            map.save(&mut store, "two", &2).unwrap();
1478            map.save(&mut store, "three", &3).unwrap();
1479
1480            // Inclusive bound
1481            let items: Vec<_> = map
1482                .idx
1483                .secondary
1484                .range_raw(&store, None, Some(Bound::inclusive(1u64)), Order::Ascending)
1485                .collect::<Result<_, _>>()
1486                .unwrap();
1487
1488            // Strip the index from values (for simpler comparison)
1489            let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1490
1491            assert_eq!(items, vec![1]);
1492
1493            // Exclusive bound
1494            let items: Vec<_> = map
1495                .idx
1496                .secondary
1497                .range(&store, Some(Bound::exclusive(2u64)), None, Order::Ascending)
1498                .collect::<Result<_, _>>()
1499                .unwrap();
1500
1501            assert_eq!(items, vec![((), 3)]);
1502        }
1503    }
1504
1505    mod bounds_multi_index {
1506        use super::*;
1507
1508        struct Indexes<'a> {
1509            // The last type param must match the `IndexedMap` primary key type, below
1510            secondary: MultiIndex<'a, u64, u64, &'a str>,
1511        }
1512
1513        impl<'a> IndexList<u64> for Indexes<'a> {
1514            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<u64>> + '_> {
1515                let v: Vec<&dyn Index<u64>> = vec![&self.secondary];
1516                Box::new(v.into_iter())
1517            }
1518        }
1519
1520        #[test]
1521        #[cfg(feature = "iterator")]
1522        fn composite_key_query() {
1523            let indexes = Indexes {
1524                secondary: MultiIndex::new(
1525                    |_pk, secondary| *secondary,
1526                    "test_map",
1527                    "test_map__secondary",
1528                ),
1529            };
1530            let map = IndexedMap::<&str, u64, Indexes>::new("test_map", indexes);
1531            let mut store = MockStorage::new();
1532
1533            map.save(&mut store, "one", &1).unwrap();
1534            map.save(&mut store, "two", &2).unwrap();
1535            map.save(&mut store, "two2", &2).unwrap();
1536            map.save(&mut store, "three", &3).unwrap();
1537
1538            // Inclusive prefix-bound
1539            let items: Vec<_> = map
1540                .idx
1541                .secondary
1542                .prefix_range_raw(
1543                    &store,
1544                    None,
1545                    Some(PrefixBound::inclusive(1u64)),
1546                    Order::Ascending,
1547                )
1548                .collect::<Result<_, _>>()
1549                .unwrap();
1550
1551            // Strip the index from values (for simpler comparison)
1552            let items: Vec<_> = items.into_iter().map(|(_, v)| v).collect();
1553
1554            assert_eq!(items, vec![1]);
1555
1556            // Exclusive bound (used for pagination)
1557            // Range over the index specifying a primary key (multi-index key includes the pk)
1558            let items: Vec<_> = map
1559                .idx
1560                .secondary
1561                .range(
1562                    &store,
1563                    Some(Bound::exclusive((2u64, "two"))),
1564                    None,
1565                    Order::Ascending,
1566                )
1567                .collect::<Result<_, _>>()
1568                .unwrap();
1569
1570            assert_eq!(
1571                items,
1572                vec![("two2".to_string(), 2), ("three".to_string(), 3)]
1573            );
1574        }
1575    }
1576
1577    mod pk_multi_index {
1578        use super::*;
1579        use cosmwasm_std::{Addr, Uint128};
1580
1581        struct Indexes<'a> {
1582            // The last type param must match the `IndexedMap` primary key type below
1583            spender: MultiIndex<'a, Addr, Uint128, (Addr, Addr)>,
1584        }
1585
1586        impl<'a> IndexList<Uint128> for Indexes<'a> {
1587            fn get_indexes(&'_ self) -> Box<dyn Iterator<Item = &'_ dyn Index<Uint128>> + '_> {
1588                let v: Vec<&dyn Index<Uint128>> = vec![&self.spender];
1589                Box::new(v.into_iter())
1590            }
1591        }
1592
1593        #[test]
1594        #[cfg(feature = "iterator")]
1595        fn pk_based_index() {
1596            fn pk_index(pk: &[u8]) -> Addr {
1597                let (_owner, spender) = <(Addr, Addr)>::from_slice(pk).unwrap(); // mustn't fail
1598                spender
1599            }
1600
1601            let indexes = Indexes {
1602                spender: MultiIndex::new(
1603                    |pk, _allow| pk_index(pk),
1604                    "allowances",
1605                    "allowances__spender",
1606                ),
1607            };
1608            let map = IndexedMap::<(&Addr, &Addr), Uint128, Indexes>::new("allowances", indexes);
1609            let mut store = MockStorage::new();
1610
1611            map.save(
1612                &mut store,
1613                (&Addr::unchecked("owner1"), &Addr::unchecked("spender1")),
1614                &Uint128::new(11),
1615            )
1616            .unwrap();
1617            map.save(
1618                &mut store,
1619                (&Addr::unchecked("owner1"), &Addr::unchecked("spender2")),
1620                &Uint128::new(12),
1621            )
1622            .unwrap();
1623            map.save(
1624                &mut store,
1625                (&Addr::unchecked("owner2"), &Addr::unchecked("spender1")),
1626                &Uint128::new(21),
1627            )
1628            .unwrap();
1629
1630            // Iterate over the main values
1631            let items: Vec<_> = map
1632                .range_raw(&store, None, None, Order::Ascending)
1633                .collect::<Result<_, _>>()
1634                .unwrap();
1635
1636            // Strip the index from values (for simpler comparison)
1637            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1638
1639            assert_eq!(items, vec![11, 12, 21]);
1640
1641            // Iterate over the indexed values
1642            let items: Vec<_> = map
1643                .idx
1644                .spender
1645                .range_raw(&store, None, None, Order::Ascending)
1646                .collect::<Result<_, _>>()
1647                .unwrap();
1648
1649            // Strip the index from values (for simpler comparison)
1650            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1651
1652            assert_eq!(items, vec![11, 21, 12]);
1653
1654            // Prefix over the main values
1655            let items: Vec<_> = map
1656                .prefix(&Addr::unchecked("owner1"))
1657                .range_raw(&store, None, None, Order::Ascending)
1658                .collect::<Result<_, _>>()
1659                .unwrap();
1660
1661            // Strip the index from values (for simpler comparison)
1662            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1663
1664            assert_eq!(items, vec![11, 12]);
1665
1666            // Prefix over the indexed values
1667            let items: Vec<_> = map
1668                .idx
1669                .spender
1670                .prefix(Addr::unchecked("spender1"))
1671                .range_raw(&store, None, None, Order::Ascending)
1672                .collect::<Result<_, _>>()
1673                .unwrap();
1674
1675            // Strip the index from values (for simpler comparison)
1676            let items: Vec<_> = items.into_iter().map(|(_, v)| v.u128()).collect();
1677
1678            assert_eq!(items, vec![11, 21]);
1679
1680            // Prefix over the indexed values, and deserialize primary key as well
1681            let items: Vec<_> = map
1682                .idx
1683                .spender
1684                .prefix(Addr::unchecked("spender2"))
1685                .range(&store, None, None, Order::Ascending)
1686                .collect::<Result<_, _>>()
1687                .unwrap();
1688
1689            assert_eq!(
1690                items,
1691                vec![(
1692                    (Addr::unchecked("owner1"), Addr::unchecked("spender2")),
1693                    Uint128::new(12)
1694                )]
1695            );
1696        }
1697    }
1698
1699    #[test]
1700    fn clear_works() {
1701        let mut storage = MockStorage::new();
1702        let (pks, _) = save_data(&mut storage);
1703
1704        DATA.clear(&mut storage);
1705
1706        for key in pks {
1707            assert!(!DATA.has(&storage, key));
1708        }
1709    }
1710
1711    #[test]
1712    fn is_empty_works() {
1713        let mut storage = MockStorage::new();
1714
1715        assert!(DATA.is_empty(&storage));
1716
1717        save_data(&mut storage);
1718
1719        assert!(!DATA.is_empty(&storage));
1720    }
1721}