freenet_stdlib/contract_interface/
encoding.rs1use std::{
3 collections::{HashMap, HashSet},
4 marker::PhantomData,
5};
6
7use serde::{de::DeserializeOwned, Serialize};
8
9use super::*;
10use crate::parameters::Parameters;
11
12pub enum MergeResult {
13 Success,
14 RequestRelated(RelatedContractsContainer),
15 Error(ContractError),
16}
17
18#[derive(Default)]
19pub struct RelatedContractsContainer {
20 contracts: HashMap<ContractInstanceId, State<'static>>,
21 pending: HashSet<ContractInstanceId>,
22 not_found: HashSet<ContractInstanceId>,
23}
24
25impl From<RelatedContracts<'static>> for RelatedContractsContainer {
26 fn from(found: RelatedContracts<'static>) -> Self {
27 let mut not_found = HashSet::new();
28 let mut contracts = HashMap::new();
29 for (id, state) in found.states() {
30 match state {
31 Some(state) => {
32 contracts.insert(*id, state.clone());
33 }
34 None => {
35 not_found.insert(*id);
36 }
37 }
38 }
39 RelatedContractsContainer {
40 contracts,
41 pending: HashSet::new(),
42 not_found,
43 }
44 }
45}
46
47impl From<RelatedContractsContainer> for Vec<crate::contract_interface::RelatedContract> {
48 fn from(related: RelatedContractsContainer) -> Self {
49 related
50 .pending
51 .into_iter()
52 .map(|id| RelatedContract {
53 contract_instance_id: id,
54 mode: RelatedMode::StateOnce,
55 })
56 .collect()
57 }
58}
59
60impl From<Vec<UpdateData<'static>>> for RelatedContractsContainer {
61 fn from(updates: Vec<UpdateData<'static>>) -> Self {
62 let mut this = RelatedContractsContainer::default();
63 for update in updates {
64 match update {
65 UpdateData::RelatedState { related_to, state } => {
66 this.contracts.insert(related_to, state);
67 }
68 UpdateData::RelatedStateAndDelta {
69 related_to, state, ..
70 } => {
71 this.contracts.insert(related_to, state);
72 }
73 _ => {}
74 }
75 }
76 this
77 }
78}
79
80impl RelatedContractsContainer {
81 pub fn get<C: TypedContract>(
82 &self,
83 params: &C::Parameters,
84 ) -> Result<Related<C>, <<C as EncodingAdapter>::SelfEncoder as Encoder<C>>::Error> {
85 let id = <C as TypedContract>::instance_id(params);
86 if let Some(res) = self.contracts.get(&id) {
87 match <<C as EncodingAdapter>::SelfEncoder>::deserialize(res.as_ref()) {
88 Ok(state) => return Ok(Related::Found { state }),
89 Err(err) => return Err(err),
90 }
91 }
92 if self.pending.contains(&id) {
93 return Ok(Related::RequestPending);
94 }
95 if self.not_found.contains(&id) {
96 return Ok(Related::NotFound);
97 }
98 Ok(Related::NotRequested)
99 }
100
101 pub fn request<C: TypedContract>(&mut self, id: ContractInstanceId) {
102 self.pending.insert(id);
103 }
104
105 pub fn merge(&mut self, other: Self) {
106 let Self {
107 contracts,
108 pending,
109 not_found,
110 } = other;
111 self.pending.extend(pending);
112 self.not_found.extend(not_found);
113 self.contracts.extend(contracts);
114 }
115}
116
117pub enum Related<C: TypedContract> {
118 Found { state: C },
120 NotFound,
122 RequestPending,
124 NotRequested,
127}
128
129pub trait EncodingAdapter
132where
133 Self: Sized,
134{
135 type Parameters;
136 type Delta;
137 type Summary;
138
139 type SelfEncoder: Encoder<Self>;
140 type ParametersEncoder: Encoder<Self::Parameters>;
141 type DeltaEncoder: Encoder<Self::Delta>;
142 type SummaryEncoder: Encoder<Self::Summary>;
143}
144
145pub enum TypedUpdateData<T: EncodingAdapter> {
146 RelatedState { state: T },
147 RelatedDelta { delta: T::Delta },
148 RelatedStateAndDelta { state: T, delta: T::Delta },
149}
150
151impl<T: EncodingAdapter> TypedUpdateData<T> {
152 pub fn from_other<Parent>(value: &TypedUpdateData<Parent>) -> Self
153 where
154 Parent: EncodingAdapter,
155 T: for<'x> From<&'x Parent>,
156 T::Delta: for<'x> From<&'x Parent::Delta>,
157 {
158 match value {
159 TypedUpdateData::RelatedState { state } => {
160 let state = T::from(state);
161 TypedUpdateData::RelatedState { state }
162 }
163 TypedUpdateData::RelatedDelta { delta } => {
164 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
165 TypedUpdateData::RelatedDelta { delta }
166 }
167 TypedUpdateData::RelatedStateAndDelta { state, delta } => {
168 let state = T::from(state);
169 let delta: T::Delta = <T as EncodingAdapter>::Delta::from(delta);
170 TypedUpdateData::RelatedStateAndDelta { state, delta }
171 }
172 }
173 }
174}
175
176impl<T: EncodingAdapter> TryFrom<(Option<T>, Option<T::Delta>)> for TypedUpdateData<T> {
177 type Error = ContractError;
178 fn try_from((state, delta): (Option<T>, Option<T::Delta>)) -> Result<Self, Self::Error> {
179 match (state, delta) {
180 (None, None) => Err(ContractError::InvalidState),
181 (None, Some(delta)) => Ok(Self::RelatedDelta { delta }),
182 (Some(state), None) => Ok(Self::RelatedState { state }),
183 (Some(state), Some(delta)) => Ok(Self::RelatedStateAndDelta { state, delta }),
184 }
185 }
186}
187
188pub trait TypedContract: EncodingAdapter {
189 fn instance_id(params: &Self::Parameters) -> ContractInstanceId;
190
191 fn verify(
192 &self,
193 parameters: Self::Parameters,
194 related: RelatedContractsContainer,
195 ) -> Result<ValidateResult, ContractError>;
196
197 fn merge(
198 &mut self,
199 parameters: &Self::Parameters,
200 update: TypedUpdateData<Self>,
201 related: &RelatedContractsContainer,
202 ) -> MergeResult;
203
204 fn summarize(&self, parameters: Self::Parameters) -> Result<Self::Summary, ContractError>;
205
206 fn delta(
207 &self,
208 parameters: Self::Parameters,
209 summary: Self::Summary,
210 ) -> Result<Self::Delta, ContractError>;
211}
212
213pub trait Encoder<T> {
214 type Error: Into<ContractError>;
215 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error>;
216 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error>;
217}
218
219pub struct JsonEncoder<T>(PhantomData<T>);
220
221impl<T> Encoder<T> for JsonEncoder<T>
222where
223 T: DeserializeOwned + Serialize,
224{
225 type Error = serde_json::Error;
226
227 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
228 serde_json::from_slice(bytes)
229 }
230
231 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
232 serde_json::to_vec(value)
233 }
234}
235
236impl From<serde_json::Error> for ContractError {
237 fn from(value: serde_json::Error) -> Self {
238 ContractError::Deser(format!("{value}"))
239 }
240}
241
242pub struct BincodeEncoder<T>(PhantomData<T>);
243
244impl<T> Encoder<T> for BincodeEncoder<T>
245where
246 T: DeserializeOwned + Serialize,
247{
248 type Error = bincode::Error;
249
250 fn deserialize(bytes: &[u8]) -> Result<T, Self::Error> {
251 bincode::deserialize(bytes)
252 }
253
254 fn serialize(value: &T) -> Result<Vec<u8>, Self::Error> {
255 bincode::serialize(value)
256 }
257}
258
259impl From<bincode::Error> for ContractError {
260 fn from(value: bincode::Error) -> Self {
261 ContractError::Deser(format!("{value}"))
262 }
263}
264
265pub fn inner_validate_state<T>(
266 parameters: Parameters<'static>,
267 state: State<'static>,
268 related: RelatedContracts<'static>,
269) -> Result<ValidateResult, ContractError>
270where
271 T: EncodingAdapter + TypedContract,
272 ContractError: From<
273 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
274 <T as EncodingAdapter>::Parameters,
275 >>::Error,
276 >,
277 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
278{
279 let typed_params =
280 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
281 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
282 let related_container = RelatedContractsContainer::from(related);
283 typed_state.verify(typed_params, related_container)
284}
285
286pub fn inner_update_state<T>(
287 parameters: Parameters<'static>,
288 state: State<'static>,
289 data: Vec<UpdateData<'static>>,
290) -> Result<UpdateModification<'static>, ContractError>
291where
292 T: EncodingAdapter + TypedContract,
293 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
294 ContractError: From<
295 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
296 <T as EncodingAdapter>::Parameters,
297 >>::Error,
298 >,
299 ContractError: From<
300 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
301 >,
302{
303 let typed_params =
304 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
305 let mut typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
306 let self_updates = UpdateData::get_self_states(&data);
307 let related_container = RelatedContractsContainer::from(data);
308 for (state, delta) in self_updates {
309 let state = state
310 .map(|s| <<T as EncodingAdapter>::SelfEncoder>::deserialize(s.as_ref()))
311 .transpose()?;
312 let delta = delta
313 .map(|d| <<T as EncodingAdapter>::DeltaEncoder>::deserialize(d.as_ref()))
314 .transpose()?;
315 let typed_update = TypedUpdateData::try_from((state, delta))?;
316 match typed_state.merge(&typed_params, typed_update, &related_container) {
317 MergeResult::Success => {}
318 MergeResult::RequestRelated(req) => {
319 return UpdateModification::requires(req.into());
320 }
321 MergeResult::Error(err) => return Err(err),
322 }
323 }
324 let encoded = <<T as EncodingAdapter>::SelfEncoder>::serialize(&typed_state)?;
325 Ok(UpdateModification::valid(encoded.into()))
326}
327
328pub fn inner_summarize_state<T>(
329 parameters: Parameters<'static>,
330 state: State<'static>,
331) -> Result<StateSummary<'static>, ContractError>
332where
333 T: EncodingAdapter + TypedContract,
334 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
335 ContractError: From<
336 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
337 <T as EncodingAdapter>::Parameters,
338 >>::Error,
339 >,
340 ContractError: From<
341 <<T as EncodingAdapter>::SummaryEncoder as Encoder<<T as EncodingAdapter>::Summary>>::Error,
342 >,
343{
344 let typed_params =
345 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
346 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
347 let summary = typed_state.summarize(typed_params)?;
348 let encoded = <<T as EncodingAdapter>::SummaryEncoder>::serialize(&summary)?;
349 Ok(encoded.into())
350}
351
352pub fn inner_state_delta<T>(
353 parameters: Parameters<'static>,
354 state: State<'static>,
355 summary: StateSummary<'static>,
356) -> Result<StateDelta<'static>, ContractError>
357where
358 T: EncodingAdapter + TypedContract,
359 ContractError: From<<<T as EncodingAdapter>::SelfEncoder as Encoder<T>>::Error>,
360 ContractError: From<
361 <<T as EncodingAdapter>::ParametersEncoder as Encoder<
362 <T as EncodingAdapter>::Parameters,
363 >>::Error,
364 >,
365 ContractError: From<
366 <<T as EncodingAdapter>::SummaryEncoder as Encoder<<T as EncodingAdapter>::Summary>>::Error,
367 >,
368 ContractError: From<
369 <<T as EncodingAdapter>::DeltaEncoder as Encoder<<T as EncodingAdapter>::Delta>>::Error,
370 >,
371{
372 let typed_params =
373 <<T as EncodingAdapter>::ParametersEncoder>::deserialize(parameters.as_ref())?;
374 let typed_state = <<T as EncodingAdapter>::SelfEncoder>::deserialize(state.as_ref())?;
375 let typed_summary = <<T as EncodingAdapter>::SummaryEncoder>::deserialize(summary.as_ref())?;
376 let summary = typed_state.delta(typed_params, typed_summary)?;
377 let encoded = <<T as EncodingAdapter>::DeltaEncoder>::serialize(&summary)?;
378 Ok(encoded.into())
379}