Skip to main content

tlbits/de/
as.rs

1use std::{
2    borrow::Cow,
3    collections::{BTreeMap, BTreeSet, HashMap, HashSet, LinkedList, VecDeque},
4    hash::Hash,
5    rc::Rc,
6    sync::Arc,
7};
8
9use bitvec::{order::Msb0, slice::BitSlice};
10use either::Either;
11
12use crate::{
13    Context, Error, StringError,
14    r#as::{AsWrap, Same},
15    de::BitUnpack,
16};
17
18use super::{BitReader, BitReaderExt};
19
20/// Adapter to **de**serialize `T` with args.
21///
22/// This approach is heavily inspired by
23/// [serde_with](https://docs.rs/serde_with/latest/serde_with).
24/// Please, read their docs for more usage examples.
25pub trait BitUnpackAs<'de, T> {
26    type Args;
27
28    /// Unpacks value with args using an adapter
29    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<T, R::Error>
30    where
31        R: BitReader<'de> + ?Sized;
32}
33/// **De**serialize value from [`BitSlice`] with args using an adapter
34#[inline]
35pub fn unpack_as<'de, T, As>(
36    mut bits: &'de BitSlice<u8, Msb0>,
37    args: As::Args,
38) -> Result<T, StringError>
39where
40    As: BitUnpackAs<'de, T>,
41{
42    bits.unpack_as::<_, As>(args)
43}
44
45/// **De**serialize value from bytes slice using an adapter
46#[inline]
47pub fn unpack_bytes_as<'de, T, As>(bytes: &'de [u8], args: As::Args) -> Result<T, StringError>
48where
49    As: BitUnpackAs<'de, T>,
50{
51    unpack_as::<_, As>(BitSlice::from_slice(bytes), args)
52}
53
54/// **De**serialize value from [`BitSlice`] using an adapter
55/// and ensure that no more data left.
56#[inline]
57pub fn unpack_fully_as<'de, T, As>(
58    mut bits: &'de BitSlice<u8, Msb0>,
59    args: As::Args,
60) -> Result<T, StringError>
61where
62    As: BitUnpackAs<'de, T>,
63{
64    let v = bits.unpack_as::<T, As>(args)?;
65    if !bits.is_empty() {
66        return Err(Error::custom("more data left"));
67    }
68    Ok(v)
69}
70
71/// **De**serialize value from bytes slice using an adapter
72/// and ensure that no more data left.
73#[inline]
74pub fn unpack_bytes_fully_as<'de, T, As>(bytes: &'de [u8], args: As::Args) -> Result<T, StringError>
75where
76    As: BitUnpackAs<'de, T>,
77{
78    unpack_fully_as::<_, As>(BitSlice::from_slice(bytes), args)
79}
80
81impl<'de, T, As, const N: usize> BitUnpackAs<'de, [T; N]> for [As; N]
82where
83    As: BitUnpackAs<'de, T>,
84    As::Args: Clone,
85{
86    type Args = As::Args;
87
88    #[inline]
89    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<[T; N], R::Error>
90    where
91        R: BitReader<'de> + ?Sized,
92    {
93        // TODO: replace with [`core::array::try_from_fn`](https://github.com/rust-lang/rust/issues/89379) when stabilized
94        array_util::try_from_fn(|i| {
95            As::unpack_as(reader, args.clone()).with_context(|| format!("[{i}]"))
96        })
97    }
98}
99
100macro_rules! impl_bit_unpack_as_for_tuple {
101    ($($ts:ident as $as:ident:$ns:tt),*) => {
102        impl<'de, $($ts, $as),*> BitUnpackAs<'de, ($($ts,)*)> for ($($as,)*)
103        where $(
104            $as: BitUnpackAs<'de, $ts>,
105        )*
106        {
107            type Args = ($($as::Args,)*);
108
109            #[inline]
110            #[allow(unused_variables)]
111            fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<($($ts,)*), R::Error>
112            where
113                R: BitReader<'de> + ?Sized,
114            {
115                Ok(($(
116                    $as::unpack_as(reader, args.$ns)
117                        .context(concat!(".", stringify!($ns)))?,
118                )*))
119            }
120        }
121    };
122}
123impl_bit_unpack_as_for_tuple!();
124impl_bit_unpack_as_for_tuple!(T0 as As0:0);
125impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1);
126impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2);
127impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3);
128impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4);
129impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5);
130impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6);
131impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7);
132impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7,T8 as As8:8);
133impl_bit_unpack_as_for_tuple!(T0 as As0:0,T1 as As1:1,T2 as As2:2,T3 as As3:3,T4 as As4:4,T5 as As5:5,T6 as As6:6,T7 as As7:7,T8 as As8:8,T9 as As9:9);
134
135impl<'de, T, As> BitUnpackAs<'de, Box<T>> for Box<As>
136where
137    As: BitUnpackAs<'de, T> + ?Sized,
138{
139    type Args = As::Args;
140
141    #[inline]
142    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Box<T>, R::Error>
143    where
144        R: BitReader<'de> + ?Sized,
145    {
146        AsWrap::<T, As>::unpack(reader, args)
147            .map(AsWrap::into_inner)
148            .map(Into::into)
149    }
150}
151
152impl<'de, T, As> BitUnpackAs<'de, Rc<T>> for Rc<As>
153where
154    As: BitUnpackAs<'de, T> + ?Sized,
155{
156    type Args = As::Args;
157
158    #[inline]
159    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Rc<T>, R::Error>
160    where
161        R: BitReader<'de> + ?Sized,
162    {
163        AsWrap::<T, As>::unpack(reader, args)
164            .map(AsWrap::into_inner)
165            .map(Into::into)
166    }
167}
168
169impl<'de, T, As> BitUnpackAs<'de, Arc<T>> for Arc<As>
170where
171    As: BitUnpackAs<'de, T> + ?Sized,
172{
173    type Args = As::Args;
174
175    #[inline]
176    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Arc<T>, R::Error>
177    where
178        R: BitReader<'de> + ?Sized,
179    {
180        AsWrap::<T, As>::unpack(reader, args)
181            .map(AsWrap::into_inner)
182            .map(Into::into)
183    }
184}
185
186/// Always unpacks as [`Cow::Owned`]
187impl<'de, 'a, T, As> BitUnpackAs<'de, Cow<'a, T>> for Cow<'a, As>
188where
189    T: ToOwned + ?Sized,
190    As: ToOwned + ?Sized,
191    As::Owned: BitUnpackAs<'de, T::Owned>,
192{
193    type Args = <As::Owned as BitUnpackAs<'de, T::Owned>>::Args;
194
195    #[inline]
196    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Cow<'a, T>, R::Error>
197    where
198        R: BitReader<'de> + ?Sized,
199    {
200        AsWrap::<T::Owned, As::Owned>::unpack(reader, args)
201            .map(AsWrap::into_inner)
202            .map(Cow::Owned)
203    }
204}
205/// Implementation of [`Either X Y`](https://docs.ton.org/develop/data-formats/tl-b-types#either):
206/// ```tlb
207/// left$0 {X:Type} {Y:Type} value:X = Either X Y;
208/// right$1 {X:Type} {Y:Type} value:Y = Either X Y;
209/// ```
210impl<'de, Left, Right, AsLeft, AsRight> BitUnpackAs<'de, Either<Left, Right>>
211    for Either<AsLeft, AsRight>
212where
213    AsLeft: BitUnpackAs<'de, Left>,
214    AsRight: BitUnpackAs<'de, Right>,
215{
216    type Args = (AsLeft::Args, AsRight::Args);
217
218    #[inline]
219    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Either<Left, Right>, R::Error>
220    where
221        R: BitReader<'de> + ?Sized,
222    {
223        Ok(
224            Either::<AsWrap<Left, AsLeft>, AsWrap<Right, AsRight>>::unpack(reader, args)?
225                .map_either(AsWrap::into_inner, AsWrap::into_inner),
226        )
227    }
228}
229
230impl<'de, T, As> BitUnpackAs<'de, Option<T>> for Either<(), As>
231where
232    As: BitUnpackAs<'de, T>,
233{
234    type Args = As::Args;
235
236    #[inline]
237    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Option<T>, R::Error>
238    where
239        R: BitReader<'de> + ?Sized,
240    {
241        Ok(reader
242            .unpack_as::<Either<(), T>, Either<Same, As>>(((), args))?
243            .right())
244    }
245}
246
247/// Implementation of [`Maybe X`](https://docs.ton.org/develop/data-formats/tl-b-types#maybe):
248/// ```tlb
249/// nothing$0 {X:Type} = Maybe X;
250/// just$1 {X:Type} value:X = Maybe X;
251/// ```
252impl<'de, T, As> BitUnpackAs<'de, Option<T>> for Option<As>
253where
254    As: BitUnpackAs<'de, T>,
255{
256    type Args = As::Args;
257
258    #[inline]
259    fn unpack_as<R>(reader: &mut R, args: Self::Args) -> Result<Option<T>, R::Error>
260    where
261        R: BitReader<'de> + ?Sized,
262    {
263        Ok(Option::<AsWrap<T, As>>::unpack(reader, args)?.map(AsWrap::into_inner))
264    }
265}
266
267impl<'de, T, As> BitUnpackAs<'de, Vec<T>> for Vec<As>
268where
269    As: BitUnpackAs<'de, T>,
270    As::Args: Clone,
271{
272    /// `(len, item_args)`
273    type Args = (usize, As::Args);
274
275    #[inline]
276    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<Vec<T>, R::Error>
277    where
278        R: BitReader<'de> + ?Sized,
279    {
280        reader.unpack_iter_as::<_, As>(args).take(len).collect()
281    }
282}
283
284impl<'de, T, As> BitUnpackAs<'de, VecDeque<T>> for VecDeque<As>
285where
286    As: BitUnpackAs<'de, T>,
287    As::Args: Clone,
288{
289    /// `(len, item_args)`
290    type Args = (usize, As::Args);
291
292    #[inline]
293    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<VecDeque<T>, R::Error>
294    where
295        R: BitReader<'de> + ?Sized,
296    {
297        reader.unpack_iter_as::<_, As>(args).take(len).collect()
298    }
299}
300
301impl<'de, T, As> BitUnpackAs<'de, LinkedList<T>> for LinkedList<As>
302where
303    As: BitUnpackAs<'de, T>,
304    As::Args: Clone,
305{
306    /// `(len, item_args)`
307    type Args = (usize, As::Args);
308
309    #[inline]
310    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<LinkedList<T>, R::Error>
311    where
312        R: BitReader<'de> + ?Sized,
313    {
314        reader.unpack_iter_as::<_, As>(args).take(len).collect()
315    }
316}
317
318impl<'de, T, As> BitUnpackAs<'de, BTreeSet<T>> for BTreeSet<As>
319where
320    T: Ord + Eq,
321    As: BitUnpackAs<'de, T>,
322    As::Args: Clone,
323{
324    /// `(len, item_args)`
325    type Args = (usize, As::Args);
326
327    #[inline]
328    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<BTreeSet<T>, R::Error>
329    where
330        R: BitReader<'de> + ?Sized,
331    {
332        reader.unpack_iter_as::<_, As>(args).take(len).collect()
333    }
334}
335
336impl<'de, K, V, KAs, VAs> BitUnpackAs<'de, BTreeMap<K, V>> for BTreeMap<KAs, VAs>
337where
338    K: Ord + Eq,
339    KAs: BitUnpackAs<'de, K>,
340    KAs::Args: Clone,
341    VAs: BitUnpackAs<'de, V>,
342    VAs::Args: Clone,
343{
344    /// `(len, (key_args, value_args))`
345    type Args = (usize, (KAs::Args, VAs::Args));
346
347    #[inline]
348    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<BTreeMap<K, V>, R::Error>
349    where
350        R: BitReader<'de> + ?Sized,
351    {
352        reader
353            .unpack_iter_as::<_, (KAs, VAs)>(args)
354            .take(len)
355            .collect()
356    }
357}
358
359impl<'de, T, As> BitUnpackAs<'de, HashSet<T>> for HashSet<As>
360where
361    T: Hash + Eq,
362    As: BitUnpackAs<'de, T>,
363    As::Args: Clone,
364{
365    /// `(len, item_args)`
366    type Args = (usize, As::Args);
367
368    #[inline]
369    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<HashSet<T>, R::Error>
370    where
371        R: BitReader<'de> + ?Sized,
372    {
373        reader.unpack_iter_as::<_, As>(args).take(len).collect()
374    }
375}
376
377impl<'de, K, V, KAs, VAs> BitUnpackAs<'de, HashMap<K, V>> for HashMap<KAs, VAs>
378where
379    K: Hash + Eq,
380    KAs: BitUnpackAs<'de, K>,
381    KAs::Args: Clone,
382    VAs: BitUnpackAs<'de, V>,
383    VAs::Args: Clone,
384{
385    /// `(len, (key_args, value_args))`
386    type Args = (usize, (KAs::Args, VAs::Args));
387
388    #[inline]
389    fn unpack_as<R>(reader: &mut R, (len, args): Self::Args) -> Result<HashMap<K, V>, R::Error>
390    where
391        R: BitReader<'de> + ?Sized,
392    {
393        reader
394            .unpack_iter_as::<_, (KAs, VAs)>(args)
395            .take(len)
396            .collect()
397    }
398}