cosmwasm_std/
deps.rs

1use core::marker::PhantomData;
2
3use crate::query::CustomQuery;
4use crate::results::Empty;
5use crate::traits::{Api, Querier, Storage};
6use crate::QuerierWrapper;
7
8/// Holds all external dependencies of the contract.
9/// Designed to allow easy dependency injection at runtime.
10/// This cannot be copied or cloned since it would behave differently
11/// for mock storages and a bridge storage in the VM.
12pub struct OwnedDeps<S: Storage, A: Api, Q: Querier, C: CustomQuery = Empty> {
13    pub storage: S,
14    pub api: A,
15    pub querier: Q,
16    pub custom_query_type: PhantomData<C>,
17}
18
19pub struct DepsMut<'a, C: CustomQuery = Empty> {
20    pub storage: &'a mut dyn Storage,
21    pub api: &'a dyn Api,
22    pub querier: QuerierWrapper<'a, C>,
23}
24
25#[derive(Clone)]
26pub struct Deps<'a, C: CustomQuery = Empty> {
27    pub storage: &'a dyn Storage,
28    pub api: &'a dyn Api,
29    pub querier: QuerierWrapper<'a, C>,
30}
31
32// Use custom implementation on order to implement Copy in case `C` is not `Copy`.
33// See "There is a small difference between the two: the derive strategy will also
34// place a Copy bound on type parameters, which isn’t always desired."
35// https://doc.rust-lang.org/std/marker/trait.Copy.html
36impl<C: CustomQuery> Copy for Deps<'_, C> {}
37
38impl<S: Storage, A: Api, Q: Querier, C: CustomQuery> OwnedDeps<S, A, Q, C> {
39    pub fn as_ref(&'_ self) -> Deps<'_, C> {
40        Deps {
41            storage: &self.storage,
42            api: &self.api,
43            querier: QuerierWrapper::new(&self.querier),
44        }
45    }
46
47    pub fn as_mut(&'_ mut self) -> DepsMut<'_, C> {
48        DepsMut {
49            storage: &mut self.storage,
50            api: &self.api,
51            querier: QuerierWrapper::new(&self.querier),
52        }
53    }
54}
55
56impl<'a, C: CustomQuery> DepsMut<'a, C> {
57    pub fn as_ref(&'_ self) -> Deps<'_, C> {
58        Deps {
59            storage: self.storage,
60            api: self.api,
61            querier: self.querier,
62        }
63    }
64
65    pub fn branch(&'_ mut self) -> DepsMut<'_, C> {
66        DepsMut {
67            storage: self.storage,
68            api: self.api,
69            querier: self.querier,
70        }
71    }
72
73    /// This allows to convert any `DepsMut` into one generic over `Empty` custom
74    /// query type.
75    pub fn into_empty(self) -> DepsMut<'a, Empty> {
76        DepsMut {
77            storage: self.storage,
78            api: self.api,
79            querier: self.querier.into_empty(),
80        }
81    }
82}
83
84impl<'a, C: CustomQuery> Deps<'a, C> {
85    /// This allows to convert any `Deps` into one generic over `Empty` custom
86    /// query type.
87    pub fn into_empty(self) -> Deps<'a, Empty> {
88        Deps {
89            storage: self.storage,
90            api: self.api,
91            querier: self.querier.into_empty(),
92        }
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99    use crate::testing::{mock_dependencies, MockApi, MockQuerier, MockStorage};
100    use serde::{Deserialize, Serialize};
101
102    // ensure we can call these many times, eg. as sub-calls
103    fn execute(mut deps: DepsMut) {
104        execute2(deps.branch());
105        query(deps.as_ref());
106        execute2(deps.branch());
107    }
108    fn execute2(_deps: DepsMut) {}
109
110    fn query(deps: Deps) {
111        query2(deps);
112        query2(deps);
113    }
114    fn query2(_deps: Deps) {}
115
116    #[test]
117    fn ensure_easy_reuse() {
118        let mut deps = mock_dependencies();
119        execute(deps.as_mut());
120        query(deps.as_ref())
121    }
122
123    #[derive(Clone, Serialize, Deserialize)]
124    struct MyQuery;
125    impl CustomQuery for MyQuery {}
126    impl CustomQuery for u64 {}
127
128    #[test]
129    fn deps_implements_copy() {
130        // With C: Copy
131        let owned = OwnedDeps::<_, _, _, u64> {
132            storage: MockStorage::default(),
133            api: MockApi::default(),
134            querier: MockQuerier::<u64>::new(&[]),
135            custom_query_type: PhantomData,
136        };
137        let deps: Deps<u64> = owned.as_ref();
138        let _copy1 = deps;
139        let _copy2 = deps;
140
141        // Without C: Copy
142        let owned = OwnedDeps::<_, _, _, MyQuery> {
143            storage: MockStorage::default(),
144            api: MockApi::default(),
145            querier: MockQuerier::<MyQuery>::new(&[]),
146            custom_query_type: PhantomData,
147        };
148        let deps: Deps<MyQuery> = owned.as_ref();
149        let _copy1 = deps;
150        let _copy2 = deps;
151    }
152
153    #[test]
154    fn deps_to_empty() {
155        let mut owned = OwnedDeps::<_, _, _, MyQuery> {
156            storage: MockStorage::default(),
157            api: MockApi::default(),
158            querier: MockQuerier::<u64>::new(&[]),
159            custom_query_type: PhantomData,
160        };
161
162        let deps_mut: DepsMut<MyQuery> = owned.as_mut();
163        let _: DepsMut<Empty> = deps_mut.into_empty();
164
165        let deps: Deps<MyQuery> = owned.as_ref();
166        let _: Deps<Empty> = deps.into_empty();
167    }
168}