freenet_stdlib/contract_interface/
wrapped.rs

1//! Arc-wrapped versions of contract types for efficient sharing.
2//!
3//! This module provides `WrappedState` and `WrappedContract` which use `Arc`
4//! for efficient sharing of state and contract data across threads.
5
6use std::borrow::Borrow;
7use std::fmt::{Debug, Display};
8use std::ops::Deref;
9use std::sync::Arc;
10
11use serde::{Deserialize, Deserializer, Serialize};
12
13use crate::parameters::Parameters;
14
15use super::code::ContractCode;
16use super::key::ContractKey;
17use super::state::State;
18
19// TODO:  get rid of this when State is internally an Arc<[u8]>
20/// The state for a contract.
21#[derive(PartialEq, Eq, Clone, serde::Serialize, serde::Deserialize)]
22#[cfg_attr(feature = "testing", derive(arbitrary::Arbitrary))]
23pub struct WrappedState(
24    #[serde(
25        serialize_with = "WrappedState::ser_state",
26        deserialize_with = "WrappedState::deser_state"
27    )]
28    Arc<Vec<u8>>,
29);
30
31impl WrappedState {
32    pub fn new(bytes: Vec<u8>) -> Self {
33        WrappedState(Arc::new(bytes))
34    }
35
36    pub fn size(&self) -> usize {
37        self.0.len()
38    }
39
40    fn ser_state<S>(data: &Arc<Vec<u8>>, ser: S) -> Result<S::Ok, S::Error>
41    where
42        S: serde::Serializer,
43    {
44        serde_bytes::serialize(&**data, ser)
45    }
46
47    fn deser_state<'de, D>(deser: D) -> Result<Arc<Vec<u8>>, D::Error>
48    where
49        D: Deserializer<'de>,
50    {
51        let data: Vec<u8> = serde_bytes::deserialize(deser)?;
52        Ok(Arc::new(data))
53    }
54}
55
56impl From<Vec<u8>> for WrappedState {
57    fn from(bytes: Vec<u8>) -> Self {
58        Self::new(bytes)
59    }
60}
61
62impl From<&'_ [u8]> for WrappedState {
63    fn from(bytes: &[u8]) -> Self {
64        Self::new(bytes.to_owned())
65    }
66}
67
68impl AsRef<[u8]> for WrappedState {
69    fn as_ref(&self) -> &[u8] {
70        self.0.as_ref()
71    }
72}
73
74impl Deref for WrappedState {
75    type Target = [u8];
76
77    fn deref(&self) -> &Self::Target {
78        &self.0
79    }
80}
81
82impl Borrow<[u8]> for WrappedState {
83    fn borrow(&self) -> &[u8] {
84        &self.0
85    }
86}
87
88impl From<WrappedState> for State<'static> {
89    fn from(value: WrappedState) -> Self {
90        match Arc::try_unwrap(value.0) {
91            Ok(v) => State::from(v),
92            Err(v) => State::from(v.as_ref().to_vec()),
93        }
94    }
95}
96
97impl std::fmt::Display for WrappedState {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        write!(f, "ContractState(data: [0x")?;
100        for b in self.0.iter().take(8) {
101            write!(f, "{:02x}", b)?;
102        }
103        write!(f, "...])")
104    }
105}
106
107impl std::fmt::Debug for WrappedState {
108    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
109        <Self as Display>::fmt(self, f)
110    }
111}
112
113/// Just as `freenet_stdlib::Contract` but with some convenience impl.
114#[non_exhaustive]
115#[derive(Clone, Debug, Serialize, Deserialize)]
116pub struct WrappedContract {
117    #[serde(
118        serialize_with = "WrappedContract::ser_contract_data",
119        deserialize_with = "WrappedContract::deser_contract_data"
120    )]
121    pub data: Arc<ContractCode<'static>>,
122    #[serde(deserialize_with = "Parameters::deser_params")]
123    pub params: Parameters<'static>,
124    pub key: ContractKey,
125}
126
127impl PartialEq for WrappedContract {
128    fn eq(&self, other: &Self) -> bool {
129        self.key == other.key
130    }
131}
132
133impl Eq for WrappedContract {}
134
135impl WrappedContract {
136    pub fn new(data: Arc<ContractCode<'static>>, params: Parameters<'static>) -> WrappedContract {
137        let key = ContractKey::from_params_and_code(&params, &*data);
138        WrappedContract { data, params, key }
139    }
140
141    #[inline]
142    pub fn key(&self) -> &ContractKey {
143        &self.key
144    }
145
146    #[inline]
147    pub fn code(&self) -> &Arc<ContractCode<'static>> {
148        &self.data
149    }
150
151    #[inline]
152    pub fn params(&self) -> &Parameters<'static> {
153        &self.params
154    }
155
156    fn ser_contract_data<S>(data: &Arc<ContractCode<'_>>, ser: S) -> Result<S::Ok, S::Error>
157    where
158        S: serde::Serializer,
159    {
160        data.serialize(ser)
161    }
162
163    fn deser_contract_data<'de, D>(deser: D) -> Result<Arc<ContractCode<'static>>, D::Error>
164    where
165        D: Deserializer<'de>,
166    {
167        let data: ContractCode<'de> = Deserialize::deserialize(deser)?;
168        Ok(Arc::new(data.into_owned()))
169    }
170}
171
172impl TryInto<Vec<u8>> for WrappedContract {
173    type Error = ();
174    fn try_into(self) -> Result<Vec<u8>, Self::Error> {
175        Arc::try_unwrap(self.data)
176            .map(|r| r.into_bytes())
177            .map_err(|_| ())
178    }
179}
180
181impl Display for WrappedContract {
182    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
183        Display::fmt(&self.key, f)
184    }
185}
186
187#[cfg(feature = "testing")]
188impl<'a> arbitrary::Arbitrary<'a> for WrappedContract {
189    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
190        use arbitrary::Arbitrary;
191        let data = <ContractCode as Arbitrary>::arbitrary(u)?.into_owned();
192        let param_bytes: Vec<u8> = Arbitrary::arbitrary(u)?;
193        let params = Parameters::from(param_bytes);
194        let key = ContractKey::from_params_and_code(&params, &data);
195        Ok(Self {
196            data: Arc::new(data),
197            params,
198            key,
199        })
200    }
201}