tlbits/de/args/
mod.rs

1pub mod r#as;
2
3use std::{borrow::Cow, rc::Rc, sync::Arc};
4
5use bitvec::{order::Msb0, slice::BitSlice, vec::BitVec};
6use either::Either;
7
8use crate::{
9    Context,
10    r#as::{BorrowCow, FromInto, Same},
11};
12
13use super::{BitReader, BitReaderExt};
14
15/// A type that can be bitwise-**de**serialized from any [`BitReader`].  
16/// In contrast with [`BitUnpack`](super::BitUnpack) it allows to pass
17/// [`Args`](BitUnpackWithArgs::Args) and these arguments can be
18/// calculated dynamically in runtime.
19pub trait BitUnpackWithArgs<'de>: Sized {
20    type Args;
21
22    /// Unpacks the value with args
23    fn unpack_with<R>(reader: R, args: Self::Args) -> Result<Self, R::Error>
24    where
25        R: BitReader<'de>;
26}
27
28impl<'de, T, const N: usize> BitUnpackWithArgs<'de> for [T; N]
29where
30    T: BitUnpackWithArgs<'de>,
31    T::Args: Clone,
32{
33    type Args = T::Args;
34
35    #[inline]
36    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
37    where
38        R: BitReader<'de>,
39    {
40        // TODO: replace with [`core::array::try_from_fn`](https://github.com/rust-lang/rust/issues/89379) when stabilized
41        array_util::try_from_fn(|i| {
42            T::unpack_with(&mut reader, args.clone()).with_context(|| format!("[{i}]"))
43        })
44    }
45}
46
47macro_rules! impl_bit_unpack_with_args_for_tuple {
48    ($($n:tt:$t:ident),+) => {
49        impl<'de, $($t),+> BitUnpackWithArgs<'de> for ($($t,)+)
50        where $(
51            $t: BitUnpackWithArgs<'de>,
52        )+
53        {
54            type Args = ($($t::Args,)+);
55
56            #[inline]
57            fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
58            where
59                R: BitReader<'de>,
60            {
61                Ok(($(
62                    $t::unpack_with(&mut reader, args.$n).context(concat!(".", stringify!($n)))?,
63                )+))
64            }
65        }
66    };
67}
68impl_bit_unpack_with_args_for_tuple!(0:T0);
69impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1);
70impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2);
71impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3);
72impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4);
73impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5);
74impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6);
75impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7);
76impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7,8:T8);
77impl_bit_unpack_with_args_for_tuple!(0:T0,1:T1,2:T2,3:T3,4:T4,5:T5,6:T6,7:T7,8:T8,9:T9);
78
79impl<'de, T> BitUnpackWithArgs<'de> for Vec<T>
80where
81    T: BitUnpackWithArgs<'de>,
82    T::Args: Clone,
83{
84    /// (len, T::Args)
85    type Args = (usize, T::Args);
86
87    #[inline]
88    fn unpack_with<R>(mut reader: R, (len, args): Self::Args) -> Result<Self, R::Error>
89    where
90        R: BitReader<'de>,
91    {
92        reader.unpack_iter_with(args).take(len).collect()
93    }
94}
95
96impl<'de, T> BitUnpackWithArgs<'de> for Box<T>
97where
98    T: BitUnpackWithArgs<'de>,
99{
100    type Args = T::Args;
101
102    #[inline]
103    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
104    where
105        R: BitReader<'de>,
106    {
107        reader.unpack_as_with::<_, FromInto<T>>(args)
108    }
109}
110
111impl<'de, T> BitUnpackWithArgs<'de> for Rc<T>
112where
113    T: BitUnpackWithArgs<'de>,
114{
115    type Args = T::Args;
116
117    #[inline]
118    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
119    where
120        R: BitReader<'de>,
121    {
122        reader.unpack_as_with::<_, FromInto<T>>(args)
123    }
124}
125
126impl<'de, T> BitUnpackWithArgs<'de> for Arc<T>
127where
128    T: BitUnpackWithArgs<'de>,
129{
130    type Args = T::Args;
131
132    #[inline]
133    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
134    where
135        R: BitReader<'de>,
136    {
137        reader.unpack_as_with::<_, FromInto<T>>(args)
138    }
139}
140
141/// Always unpacks as [`Cow::Owned`]
142impl<'de, T> BitUnpackWithArgs<'de> for Cow<'_, T>
143where
144    T: ToOwned + ?Sized,
145    T::Owned: BitUnpackWithArgs<'de>,
146{
147    type Args = <T::Owned as BitUnpackWithArgs<'de>>::Args;
148
149    #[inline]
150    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
151    where
152        R: BitReader<'de>,
153    {
154        reader.unpack_with::<T::Owned>(args).map(Self::Owned)
155    }
156}
157
158/// Implementation of [`Either X Y`](https://docs.ton.org/develop/data-formats/tl-b-types#either):
159/// ```tlb
160/// left$0 {X:Type} {Y:Type} value:X = Either X Y;
161/// right$1 {X:Type} {Y:Type} value:Y = Either X Y;
162/// ```
163impl<'de, Left, Right> BitUnpackWithArgs<'de> for Either<Left, Right>
164where
165    Left: BitUnpackWithArgs<'de>,
166    Right: BitUnpackWithArgs<'de, Args = Left::Args>,
167{
168    type Args = Left::Args;
169
170    #[inline]
171    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
172    where
173        R: BitReader<'de>,
174    {
175        match reader.unpack().context("tag")? {
176            false => reader.unpack_with(args).map(Either::Left).context("left"),
177            true => reader.unpack_with(args).map(Either::Right).context("right"),
178        }
179    }
180}
181
182/// Implementation of [`Maybe X`](https://docs.ton.org/develop/data-formats/tl-b-types#maybe):
183/// ```tlb
184/// nothing$0 {X:Type} = Maybe X;
185/// just$1 {X:Type} value:X = Maybe X;
186/// ```
187impl<'de, T> BitUnpackWithArgs<'de> for Option<T>
188where
189    T: BitUnpackWithArgs<'de>,
190{
191    type Args = T::Args;
192
193    #[inline]
194    fn unpack_with<R>(mut reader: R, args: Self::Args) -> Result<Self, R::Error>
195    where
196        R: BitReader<'de>,
197    {
198        reader.unpack_as_with::<_, Either<(), Same>>(args)
199    }
200}
201
202impl<'de> BitUnpackWithArgs<'de> for BitVec<u8, Msb0> {
203    /// length in bits
204    type Args = usize;
205
206    #[inline]
207    fn unpack_with<R>(mut reader: R, len: Self::Args) -> Result<Self, R::Error>
208    where
209        R: BitReader<'de>,
210    {
211        reader
212            .unpack_as_with::<Cow<BitSlice<u8, Msb0>>, BorrowCow>(len)
213            .map(Cow::into_owned)
214    }
215}
216
217impl<'de> BitUnpackWithArgs<'de> for Vec<u8> {
218    /// length in bytes
219    type Args = usize;
220
221    #[inline]
222    fn unpack_with<R>(mut reader: R, len: Self::Args) -> Result<Self, R::Error>
223    where
224        R: BitReader<'de>,
225    {
226        reader
227            .unpack_as_with::<Cow<[u8]>, BorrowCow>(len)
228            .map(Cow::into_owned)
229    }
230}