tw_storage_extra/cow/
indexed_map_ref.rs1use cosmwasm_std::{StdError, StdResult, Storage};
7use cw_storage_plus::{IndexList, Map, Path, Prefix, Prefixer, PrimaryKey};
8use serde::{de::DeserializeOwned, Serialize};
9
10pub struct IndexedMapRef<'a, K, T, I> {
11 pk_namespace: &'a [u8],
12 primary: Map<'a, K, T>,
13 idx: &'a I,
14}
15
16impl<'a, K, T, I> IndexedMapRef<'a, K, T, I> {
17 pub const fn new(pk_namespace: &'a str, indexes: &'a I) -> Self {
18 Self {
19 pk_namespace: pk_namespace.as_bytes(),
20 primary: Map::new(pk_namespace),
21 idx: indexes,
22 }
23 }
24}
25
26impl<'a, K, T, I> IndexedMapRef<'a, K, T, I>
27where
28 K: PrimaryKey<'a>,
29 T: Serialize + DeserializeOwned + Clone,
30 I: IndexList<T>,
31{
32 pub fn key(&self, k: K) -> Path<T> {
33 self.primary.key(k)
34 }
35
36 pub fn save(&self, store: &mut dyn Storage, key: K, data: &T) -> StdResult<()> {
37 let old_data = self.may_load(store, key.clone())?;
38 self.replace(store, key, Some(data), old_data.as_ref())
39 }
40
41 pub fn remove(&self, store: &mut dyn Storage, key: K) -> StdResult<()> {
42 let old_data = self.may_load(store, key.clone())?;
43 self.replace(store, key, None, old_data.as_ref())
44 }
45
46 pub fn replace(
47 &self,
48 store: &mut dyn Storage,
49 key: K,
50 data: Option<&T>,
51 old_data: Option<&T>,
52 ) -> StdResult<()> {
53 let pk = key.joined_key();
54 if let Some(old) = old_data {
55 for index in self.idx.get_indexes() {
56 index.remove(store, &pk, old)?;
57 }
58 }
59 if let Some(updated) = data {
60 for index in self.idx.get_indexes() {
61 index.save(store, &pk, updated)?;
62 }
63 self.primary.save(store, key, updated)?;
64 } else {
65 self.primary.remove(store, key);
66 }
67 Ok(())
68 }
69
70 pub fn update<A, E>(&self, store: &mut dyn Storage, key: K, action: A) -> Result<T, E>
71 where
72 A: FnOnce(Option<T>) -> Result<T, E>,
73 E: From<StdError>,
74 {
75 let input = self.may_load(store, key.clone())?;
76 let old_val = input.clone();
77 let output = action(input)?;
78 self.replace(store, key, Some(&output), old_val.as_ref())?;
79 Ok(output)
80 }
81
82 pub fn load(&self, store: &dyn Storage, key: K) -> StdResult<T> {
83 self.primary.load(store, key)
84 }
85
86 pub fn may_load(&self, store: &dyn Storage, key: K) -> StdResult<Option<T>> {
87 self.primary.may_load(store, key)
88 }
89
90 pub fn prefix(&self, p: K::Prefix) -> Prefix<T> {
91 Prefix::new(self.pk_namespace, &p.prefix())
92 }
93
94 pub fn sub_prefix(&self, p: K::SubPrefix) -> Prefix<T> {
95 Prefix::new(self.pk_namespace, &p.prefix())
96 }
97}