Skip to main content

tlbits/as/
unary.rs

1use num_traits::{ConstZero, One, ToPrimitive, Unsigned};
2
3use crate::{
4    Error,
5    de::{BitReader, BitUnpackAs},
6    ser::{BitPackAs, BitWriter, BitWriterExt},
7};
8
9/// [`Unary ~n`](https://docs.ton.org/develop/data-formats/tl-b-types#unary)
10/// adapter
11/// ```tlb
12/// unary_zero$0 = Unary ~0;
13/// unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);
14/// ```
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
16pub struct Unary;
17
18impl<T> BitPackAs<T> for Unary
19where
20    T: ToPrimitive + Unsigned,
21{
22    type Args = ();
23
24    #[inline]
25    fn pack_as<W>(num: &T, writer: &mut W, _: Self::Args) -> Result<(), W::Error>
26    where
27        W: BitWriter + ?Sized,
28    {
29        writer
30            // unary_succ$1 {n:#} x:(Unary ~n) = Unary ~(n + 1);
31            .with_repeat_bit(
32                num.to_usize()
33                    .ok_or_else(|| Error::custom("cannot be represented as usize"))?,
34                true,
35            )?
36            // unary_zero$0 = Unary ~0;
37            .pack(false, ())?;
38        Ok(())
39    }
40}
41
42impl<'de, T> BitUnpackAs<'de, T> for Unary
43where
44    T: Unsigned + ConstZero + One,
45{
46    type Args = ();
47
48    #[inline]
49    fn unpack_as<R>(reader: &mut R, _: Self::Args) -> Result<T, R::Error>
50    where
51        R: BitReader<'de> + ?Sized,
52    {
53        let mut n = T::ZERO;
54        while reader.read_bit()?.ok_or_else(|| Error::custom("EOF"))? {
55            n = n + T::one();
56        }
57        Ok(n)
58    }
59}