Skip to main content

tlb/ser/
as.rs

1use std::{borrow::Cow, rc::Rc, sync::Arc};
2
3use crate::{AsWrap, either::Either};
4
5use super::{CellBuilder, CellBuilderError, CellSerialize};
6
7/// Adapter to **ser**ialize `T` with args.
8///
9/// This approach is heavily inspired by
10/// [serde_with](https://docs.rs/serde_with/latest/serde_with).
11/// Please, read their docs for more usage examples.
12pub trait CellSerializeAs<T: ?Sized> {
13    type Args;
14
15    /// Stores the value with args using an adapter
16    fn store_as(
17        source: &T,
18        builder: &mut CellBuilder,
19        args: Self::Args,
20    ) -> Result<(), CellBuilderError>;
21}
22
23impl<'a, T, As> CellSerializeAs<&'a T> for &'a As
24where
25    T: ?Sized,
26    As: CellSerializeAs<T> + ?Sized,
27{
28    type Args = As::Args;
29
30    #[inline]
31    fn store_as(
32        source: &&'a T,
33        builder: &mut CellBuilder,
34        args: Self::Args,
35    ) -> Result<(), CellBuilderError> {
36        AsWrap::<&T, As>::new(source).store(builder, args)
37    }
38}
39
40impl<'a, T, As> CellSerializeAs<&'a mut T> for &'a mut As
41where
42    T: ?Sized,
43    As: CellSerializeAs<T> + ?Sized,
44{
45    type Args = As::Args;
46
47    #[inline]
48    fn store_as(
49        source: &&'a mut T,
50        builder: &mut CellBuilder,
51        args: Self::Args,
52    ) -> Result<(), CellBuilderError> {
53        AsWrap::<&T, As>::new(source).store(builder, args)
54    }
55}
56
57impl<T, As> CellSerializeAs<[T]> for [As]
58where
59    As: CellSerializeAs<T>,
60    As::Args: Clone,
61{
62    type Args = As::Args;
63
64    #[inline]
65    fn store_as(
66        source: &[T],
67        builder: &mut CellBuilder,
68        args: Self::Args,
69    ) -> Result<(), CellBuilderError> {
70        builder.store_many_as::<_, &As>(source, args)?;
71        Ok(())
72    }
73}
74
75impl<T, As, const N: usize> CellSerializeAs<[T; N]> for [As; N]
76where
77    As: CellSerializeAs<T>,
78    As::Args: Clone,
79{
80    type Args = As::Args;
81
82    #[inline]
83    fn store_as(
84        source: &[T; N],
85        builder: &mut CellBuilder,
86        args: Self::Args,
87    ) -> Result<(), CellBuilderError> {
88        <[As]>::store_as(source, builder, args)
89    }
90}
91
92macro_rules! impl_cell_serialize_as_for_tuple {
93    ($($n:tt:$t:ident as $a:ident),+) => {
94        impl<$($t, $a),+> CellSerializeAs<($($t,)+)> for ($($a,)+)
95        where $(
96            $a: CellSerializeAs<$t>,
97        )+
98        {
99            type Args = ($($a::Args,)+);
100
101            #[inline]
102            fn store_as(source: &($($t,)+), builder: &mut CellBuilder, args: Self::Args) -> Result<(), CellBuilderError> {
103                builder$(
104                    .store_as::<&$t, &$a>(&source.$n, args.$n)?)+;
105                Ok(())
106            }
107        }
108    };
109}
110impl_cell_serialize_as_for_tuple!(0:T0 as As0);
111impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1);
112impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2);
113impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3);
114impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4);
115impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5);
116impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6);
117impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7);
118impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7,8:T8 as As8);
119impl_cell_serialize_as_for_tuple!(0:T0 as As0,1:T1 as As1,2:T2 as As2,3:T3 as As3,4:T4 as As4,5:T5 as As5,6:T6 as As6,7:T7 as As7,8:T8 as As8,9:T9 as As9);
120
121impl<T, As> CellSerializeAs<Box<T>> for Box<As>
122where
123    As: CellSerializeAs<T> + ?Sized,
124{
125    type Args = As::Args;
126
127    #[inline]
128    fn store_as(
129        source: &Box<T>,
130        builder: &mut CellBuilder,
131        args: Self::Args,
132    ) -> Result<(), CellBuilderError> {
133        AsWrap::<&T, As>::new(source).store(builder, args)
134    }
135}
136
137impl<T, As> CellSerializeAs<Rc<T>> for Rc<As>
138where
139    As: CellSerializeAs<T> + ?Sized,
140{
141    type Args = As::Args;
142
143    #[inline]
144    fn store_as(
145        source: &Rc<T>,
146        builder: &mut CellBuilder,
147        args: Self::Args,
148    ) -> Result<(), CellBuilderError> {
149        AsWrap::<&T, As>::new(source).store(builder, args)
150    }
151}
152
153impl<T, As> CellSerializeAs<Arc<T>> for Arc<As>
154where
155    As: CellSerializeAs<T> + ?Sized,
156{
157    type Args = As::Args;
158
159    #[inline]
160    fn store_as(
161        source: &Arc<T>,
162        builder: &mut CellBuilder,
163        args: Self::Args,
164    ) -> Result<(), CellBuilderError> {
165        AsWrap::<&T, As>::new(source).store(builder, args)
166    }
167}
168
169impl<'a, T, As> CellSerializeAs<Cow<'a, T>> for Cow<'a, As>
170where
171    T: ToOwned + ?Sized,
172    As: ToOwned + CellSerializeAs<T> + ?Sized,
173{
174    type Args = As::Args;
175
176    #[inline]
177    fn store_as(
178        source: &Cow<'a, T>,
179        builder: &mut CellBuilder,
180        args: Self::Args,
181    ) -> Result<(), CellBuilderError> {
182        AsWrap::<&T, As>::new(source).store(builder, args)
183    }
184}
185
186/// Implementation of [`Either X Y`](https://docs.ton.org/develop/data-formats/tl-b-types#either):
187/// ```tlb
188/// left$0 {X:Type} {Y:Type} value:X = Either X Y;
189/// right$1 {X:Type} {Y:Type} value:Y = Either X Y;
190/// ```
191impl<Left, Right, AsLeft, AsRight> CellSerializeAs<Either<Left, Right>> for Either<AsLeft, AsRight>
192where
193    AsLeft: CellSerializeAs<Left>,
194    AsRight: CellSerializeAs<Right>,
195{
196    /// `(left_args, right_args)`
197    type Args = (AsLeft::Args, AsRight::Args);
198
199    #[inline]
200    fn store_as(
201        source: &Either<Left, Right>,
202        builder: &mut CellBuilder,
203        args: Self::Args,
204    ) -> Result<(), CellBuilderError> {
205        source
206            .as_ref()
207            .map_either(AsWrap::<&Left, AsLeft>::new, AsWrap::<&Right, AsRight>::new)
208            .store(builder, args)
209    }
210}
211
212impl<T, As> CellSerializeAs<Option<T>> for Either<(), As>
213where
214    As: CellSerializeAs<T>,
215{
216    type Args = As::Args;
217
218    #[inline]
219    fn store_as(
220        source: &Option<T>,
221        builder: &mut CellBuilder,
222        args: Self::Args,
223    ) -> Result<(), CellBuilderError> {
224        source
225            .as_ref()
226            .map(AsWrap::<&T, As>::new)
227            .map_or(Either::Left(()), Either::Right)
228            .store(builder, ((), args))
229    }
230}
231
232/// Implementation of [`Maybe X`](https://docs.ton.org/develop/data-formats/tl-b-types#maybe):
233/// ```tlb
234/// nothing$0 {X:Type} = Maybe X;
235/// just$1 {X:Type} value:X = Maybe X;
236/// ```
237impl<T, As> CellSerializeAs<Option<T>> for Option<As>
238where
239    As: CellSerializeAs<T>,
240{
241    type Args = As::Args;
242
243    #[inline]
244    fn store_as(
245        source: &Option<T>,
246        builder: &mut CellBuilder,
247        args: Self::Args,
248    ) -> Result<(), CellBuilderError> {
249        source
250            .as_ref()
251            .map(AsWrap::<_, As>::new)
252            .store(builder, args)
253    }
254}
255
256pub trait CellSerializeWrapAsExt {
257    #[inline]
258    fn wrap_as<As>(&self) -> AsWrap<&'_ Self, As>
259    where
260        As: CellSerializeAs<Self> + ?Sized,
261    {
262        AsWrap::new(self)
263    }
264}
265impl<T> CellSerializeWrapAsExt for T {}