secret_cosmwasm_std/
deps.rs

1use std::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<'a, C: CustomQuery> Copy for Deps<'a, 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
74#[cfg(test)]
75mod tests {
76    use super::*;
77    use crate::testing::{mock_dependencies, MockApi, MockQuerier, MockStorage};
78    use serde::{Deserialize, Serialize};
79
80    // ensure we can call these many times, eg. as sub-calls
81    fn execute(mut deps: DepsMut) {
82        execute2(deps.branch());
83        query(deps.as_ref());
84        execute2(deps.branch());
85    }
86    fn execute2(_deps: DepsMut) {}
87
88    fn query(deps: Deps) {
89        query2(deps);
90        query2(deps);
91    }
92    fn query2(_deps: Deps) {}
93
94    #[test]
95    fn ensure_easy_reuse() {
96        let mut deps = mock_dependencies();
97        execute(deps.as_mut());
98        query(deps.as_ref())
99    }
100
101    #[test]
102    fn deps_implements_copy() {
103        impl CustomQuery for u64 {}
104        #[derive(Clone, Serialize, Deserialize)]
105        struct MyQuery;
106        impl CustomQuery for MyQuery {}
107
108        // With C: Copy
109        let owned = OwnedDeps::<_, _, _, u64> {
110            storage: MockStorage::default(),
111            api: MockApi::default(),
112            querier: MockQuerier::<u64>::new(&[]),
113            custom_query_type: PhantomData,
114        };
115        let deps: Deps<u64> = owned.as_ref();
116        let _copy1 = deps;
117        let _copy2 = deps;
118
119        // Without C: Copy
120        let owned = OwnedDeps::<_, _, _, MyQuery> {
121            storage: MockStorage::default(),
122            api: MockApi::default(),
123            querier: MockQuerier::<MyQuery>::new(&[]),
124            custom_query_type: PhantomData,
125        };
126        let deps: Deps<MyQuery> = owned.as_ref();
127        let _copy1 = deps;
128        let _copy2 = deps;
129    }
130}