Skip to main content

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