Add clear and is_empty to IndexedMap
@@ -139,6 +139,34 @@ where
fn no_prefix_raw(&self) -> Prefix<Vec<u8>, T, K> {
Prefix::new(self.pk_namespace, &[])
}
+
+ /// Clears the map, removing all elements.
+ pub fn clear(&self, store: &mut dyn Storage) {
+ const TAKE: usize = 10;
+ let mut cleared = false;
+
+ while !cleared {
+ let paths = self
+ .no_prefix_raw()
+ .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
+ .map(|raw_key| Path::<T>::new(self.pk_namespace, &[raw_key.as_slice()]))
+ // Take just TAKE elements to prevent possible heap overflow if the Map is big.
+ .take(TAKE)
+ .collect::<Vec<_>>();
+
+ paths.iter().for_each(|path| store.remove(path));
+
+ cleared = paths.len() < TAKE;
+ }
+ }
+
+ /// Returns `true` if the map is empty.
+ pub fn is_empty(&self, store: &dyn Storage) -> bool {
+ self.no_prefix_raw()
+ .keys_raw(store, None, None, cosmwasm_std::Order::Ascending)
+ .next()
+ .is_none()
+ }
}
#[cfg(feature = "iterator")]
@@ -1679,4 +1707,29 @@ mod test {
);
}
}
+
+ #[test]
+ fn clear_works() {
+ let mut storage = MockStorage::new();
+ let map = build_map();
+ let (pks, _) = save_data(&mut storage, &map);
+
+ map.clear(&mut storage);
+
+ for key in pks {
+ assert!(!map.has(&storage, key));
+ }
+ }
+
+ #[test]
+ fn is_empty_works() {
+ let mut storage = MockStorage::new();
+ let map = build_map();
+
+ assert!(map.is_empty(&storage));
+
+ save_data(&mut storage, &map);
+
+ assert!(!map.is_empty(&storage));
+ }
}
