1use cosmwasm_std::storage_keys::namespace_with_key;
2use serde::de::DeserializeOwned;
3use serde::Serialize;
4use std::marker::PhantomData;
5
6use crate::helpers::not_found_object_info;
7use cosmwasm_std::{from_json, to_json_vec, StdError, StdResult, Storage};
8use std::ops::Deref;
9
10#[derive(Debug, Clone)]
11pub struct Path<T>
12where
13 T: Serialize + DeserializeOwned,
14{
15 pub(crate) storage_key: Vec<u8>,
17 data: PhantomData<T>,
19}
20
21impl<T> Deref for Path<T>
22where
23 T: Serialize + DeserializeOwned,
24{
25 type Target = [u8];
26
27 fn deref(&self) -> &[u8] {
28 &self.storage_key
29 }
30}
31
32impl<T> Path<T>
33where
34 T: Serialize + DeserializeOwned,
35{
36 pub fn new(namespace: &[u8], keys: &[&[u8]]) -> Self {
37 let l = keys.len();
38
39 let calculated_len = 1 + keys.len() - 1;
42 let mut combined: Vec<&[u8]> = Vec::with_capacity(calculated_len);
43 combined.push(namespace);
44 combined.extend(keys[0..l - 1].iter());
45 debug_assert_eq!(calculated_len, combined.len()); let storage_key = namespace_with_key(&combined, keys[l - 1]);
47 Path {
48 storage_key,
49 data: PhantomData,
50 }
51 }
52
53 pub fn save(&self, store: &mut dyn Storage, data: &T) -> StdResult<()> {
55 store.set(&self.storage_key, &to_json_vec(data)?);
56 Ok(())
57 }
58
59 pub fn remove(&self, store: &mut dyn Storage) {
60 store.remove(&self.storage_key);
61 }
62
63 pub fn load(&self, store: &dyn Storage) -> StdResult<T> {
65 if let Some(value) = store.get(&self.storage_key) {
66 from_json(value)
67 } else {
68 let object_info = not_found_object_info::<T>(&self.storage_key);
69 Err(StdError::msg(format!("{object_info} not found")))
70 }
71 }
72
73 pub fn may_load(&self, store: &dyn Storage) -> StdResult<Option<T>> {
76 let value = store.get(&self.storage_key);
77 value.map(|v| from_json(v)).transpose()
78 }
79
80 pub fn has(&self, store: &dyn Storage) -> bool {
83 store.get(&self.storage_key).is_some()
84 }
85
86 pub fn update<A, E>(&self, store: &mut dyn Storage, action: A) -> Result<T, E>
91 where
92 A: FnOnce(Option<T>) -> Result<T, E>,
93 E: From<StdError>,
94 {
95 let input = self.may_load(store)?;
96 let output = action(input)?;
97 self.save(store, &output)?;
98 Ok(output)
99 }
100}