everscale_types/models/
mod.rs

1//! Blockchain models.
2
3use std::marker::PhantomData;
4
5use crate::cell::{
6    Cell, CellBuilder, CellContext, CellSlice, DynCell, EquivalentRepr, Load, Size, Store,
7};
8use crate::error::Error;
9use crate::util::*;
10
11pub use account::*;
12pub use block::*;
13pub use config::*;
14pub use currency::*;
15pub use global_version::*;
16pub use message::*;
17pub use shard::*;
18pub use transaction::*;
19pub use vm::*;
20
21pub mod account;
22pub mod block;
23pub mod config;
24pub mod currency;
25pub mod global_version;
26pub mod message;
27pub mod shard;
28pub mod transaction;
29pub mod vm;
30
31#[cfg(feature = "sync")]
32#[doc(hidden)]
33mod __checks {
34    use super::*;
35
36    assert_impl_all!(Lazy<Message>: Send, Sync);
37    assert_impl_all!(Account: Send, Sync);
38    assert_impl_all!(Block: Send, Sync);
39    assert_impl_all!(Message: Send, Sync);
40    assert_impl_all!(Transaction: Send, Sync);
41}
42
43/// Lazy-loaded model.
44#[repr(transparent)]
45pub struct Lazy<T> {
46    cell: Cell,
47    _marker: PhantomData<T>,
48}
49
50impl<T> crate::cell::ExactSize for Lazy<T> {
51    #[inline]
52    fn exact_size(&self) -> Size {
53        Size { bits: 0, refs: 1 }
54    }
55}
56
57impl<T> std::fmt::Debug for Lazy<T> {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59        debug_tuple_field1_finish(f, "Lazy", &self.cell)
60    }
61}
62
63impl<T> Eq for Lazy<T> {}
64impl<T> PartialEq for Lazy<T> {
65    #[inline]
66    fn eq(&self, other: &Self) -> bool {
67        self.cell.as_ref().eq(other.cell.as_ref())
68    }
69}
70
71impl<T> Clone for Lazy<T> {
72    #[inline]
73    fn clone(&self) -> Self {
74        Self {
75            cell: self.cell.clone(),
76            _marker: PhantomData,
77        }
78    }
79}
80
81impl<T> Lazy<T> {
82    /// Wraps the cell in a typed wrapper.
83    #[inline]
84    pub fn from_raw(cell: Cell) -> Self {
85        Self {
86            cell,
87            _marker: PhantomData,
88        }
89    }
90
91    /// Converts into the underlying cell.
92    #[inline]
93    pub fn into_inner(self) -> Cell {
94        self.cell
95    }
96
97    /// Returns the underlying cell.
98    #[inline]
99    pub fn inner(&self) -> &Cell {
100        &self.cell
101    }
102
103    /// Converts into a lazy loader for an equivalent type.
104    pub fn cast_into<Q>(self) -> Lazy<Q>
105    where
106        Q: EquivalentRepr<T>,
107    {
108        Lazy {
109            cell: self.cell,
110            _marker: PhantomData,
111        }
112    }
113
114    /// Casts itself into a lazy loaded for an equivalent type.
115    pub fn cast_ref<Q>(&self) -> &Lazy<Q>
116    where
117        Q: EquivalentRepr<T>,
118    {
119        // SAFETY: Lazy is #[repr(transparent)]
120        unsafe { &*(self as *const Self as *const Lazy<Q>) }
121    }
122
123    /// Serializes only the root hash of the cell.
124    #[cfg(feature = "serde")]
125    pub fn serialize_repr_hash<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
126    where
127        S: serde::Serializer,
128    {
129        serde::Serialize::serialize(self.cell.repr_hash(), serializer)
130    }
131}
132
133impl<T> AsRef<DynCell> for Lazy<T> {
134    #[inline]
135    fn as_ref(&self) -> &DynCell {
136        self.cell.as_ref()
137    }
138}
139
140impl<T: Store> Lazy<T> {
141    /// Serializes the provided data and returns the typed wrapper around it.
142    pub fn new(data: &T) -> Result<Self, Error> {
143        Ok(Self::from_raw(ok!(CellBuilder::build_from(data))))
144    }
145
146    /// Updates the content with the provided data.
147    pub fn set(&mut self, data: &T) -> Result<(), Error> {
148        self.cell = ok!(CellBuilder::build_from(data));
149        Ok(())
150    }
151}
152
153impl<'a, T: Load<'a> + 'a> Lazy<T> {
154    /// Loads inner data from cell.
155    pub fn load(&'a self) -> Result<T, Error> {
156        self.cell.as_ref().parse::<T>()
157    }
158}
159
160impl<T> Store for Lazy<T> {
161    fn store_into(&self, builder: &mut CellBuilder, _: &mut dyn CellContext) -> Result<(), Error> {
162        builder.store_reference(self.cell.clone())
163    }
164}
165
166impl<'a, T> Load<'a> for Lazy<T> {
167    fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
168        match slice.load_reference_cloned() {
169            Ok(cell) => Ok(Self {
170                cell,
171                _marker: PhantomData,
172            }),
173            Err(e) => Err(e),
174        }
175    }
176}
177
178#[cfg(feature = "serde")]
179impl<T> serde::Serialize for Lazy<T>
180where
181    for<'a> T: serde::Serialize + Load<'a>,
182{
183    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
184    where
185        S: serde::Serializer,
186    {
187        if serializer.is_human_readable() {
188            let value = ok!(self.load().map_err(serde::ser::Error::custom));
189            value.serialize(serializer)
190        } else {
191            crate::boc::Boc::serialize(&self.cell, serializer)
192        }
193    }
194}
195
196#[cfg(feature = "serde")]
197impl<'de, T> serde::Deserialize<'de> for Lazy<T>
198where
199    T: serde::Deserialize<'de> + Store,
200{
201    fn deserialize<D>(deserializer: D) -> Result<Lazy<T>, D::Error>
202    where
203        D: serde::Deserializer<'de>,
204    {
205        if deserializer.is_human_readable() {
206            let value = T::deserialize(deserializer)?;
207            Lazy::new(&value).map_err(serde::de::Error::custom)
208        } else {
209            crate::boc::Boc::deserialize(deserializer).map(Lazy::from_raw)
210        }
211    }
212}