Skip to main content

tlb/de/
parser.rs

1use core::{iter, mem};
2use std::{borrow::Cow, sync::Arc};
3
4use tlbits::Context;
5
6use crate::{
7    Cell, Error,
8    bits::{
9        bitvec::{order::Msb0, slice::BitSlice},
10        de::BitReader,
11    },
12};
13
14use super::{CellDeserialize, CellDeserializeAs};
15
16/// [`Error`] for [`CellParser`]
17pub type CellParserError<'de> = <CellParser<'de> as BitReader<'de>>::Error;
18
19/// Cell parser created with [`Cell::parser()`].
20#[derive(Clone)]
21pub struct CellParser<'de> {
22    pub(super) is_exotic: bool,
23    pub(super) data: &'de BitSlice<u8, Msb0>,
24    pub(super) references: &'de [Arc<Cell>],
25}
26
27impl<'de> CellParser<'de> {
28    #[inline]
29    pub(crate) const fn new(
30        is_exotic: bool,
31        data: &'de BitSlice<u8, Msb0>,
32        references: &'de [Arc<Cell>],
33    ) -> Self {
34        Self {
35            is_exotic,
36            data,
37            references,
38        }
39    }
40
41    /// Parse the value with args using its [`CellDeserialize`]
42    /// implementation.
43    #[inline]
44    pub fn parse<T>(&mut self, args: T::Args) -> Result<T, CellParserError<'de>>
45    where
46        T: CellDeserialize<'de>,
47    {
48        T::parse(self, args)
49    }
50
51    /// Return iterator that parses values with args using
52    /// [`CellDeserialize`] implementation.
53    #[inline]
54    pub fn parse_iter<'a: 'de, T>(
55        &mut self,
56        args: T::Args,
57    ) -> impl Iterator<Item = Result<T, CellParserError<'de>>> + '_
58    where
59        T: CellDeserialize<'de>,
60        T::Args: Clone + 'a,
61    {
62        iter::repeat_with(move || self.parse(args.clone()))
63            .enumerate()
64            .map(|(i, v)| v.with_context(|| format!("[{i}]")))
65    }
66
67    /// Parse value with args using an adapter.  
68    ///
69    /// This approach is heavily inspired by
70    /// [serde_with](https://docs.rs/serde_with/latest/serde_with).
71    /// Please, read their docs for more usage examples.
72    #[inline]
73    pub fn parse_as<T, As>(&mut self, args: As::Args) -> Result<T, CellParserError<'de>>
74    where
75        As: CellDeserializeAs<'de, T> + ?Sized,
76    {
77        As::parse_as(self, args)
78    }
79
80    /// Returns iterator that parses values with args using an adapter.  
81    ///
82    /// This approach is heavily inspired by
83    /// [serde_with](https://docs.rs/serde_with/latest/serde_with).
84    /// Please, read their docs for more usage examples.
85    #[inline]
86    pub fn parse_iter_as<'a: 'de, T, As>(
87        &mut self,
88        args: As::Args,
89    ) -> impl Iterator<Item = Result<T, CellParserError<'de>>> + '_
90    where
91        As: CellDeserializeAs<'de, T> + ?Sized,
92        As::Args: Clone + 'a,
93    {
94        iter::repeat_with(move || self.parse_as::<_, As>(args.clone()))
95            .enumerate()
96            .map(|(i, v)| v.with_context(|| format!("[{i}]")))
97    }
98
99    #[inline]
100    fn pop_reference(&mut self) -> Result<&'de Arc<Cell>, CellParserError<'de>> {
101        let (first, rest) = self
102            .references
103            .split_first()
104            .ok_or_else(|| Error::custom("no more references left"))?;
105        self.references = rest;
106        Ok(first)
107    }
108
109    #[inline]
110    pub(crate) fn parse_reference_as<T, As>(
111        &mut self,
112        args: As::Args,
113    ) -> Result<T, CellParserError<'de>>
114    where
115        As: CellDeserializeAs<'de, T> + ?Sized,
116    {
117        self.pop_reference()?.parse_fully_as::<T, As>(args)
118    }
119
120    #[inline]
121    pub fn bits_left(&self) -> usize {
122        self.data.len()
123    }
124
125    #[inline]
126    pub fn no_bits_left(&self) -> bool {
127        self.bits_left() == 0
128    }
129
130    #[inline]
131    pub const fn references_left(&self) -> usize {
132        self.references.len()
133    }
134
135    #[inline]
136    pub const fn no_references_left(&self) -> bool {
137        self.references_left() == 0
138    }
139
140    /// Returns whether this parser has no more data and references.
141    #[inline]
142    pub fn is_empty(&self) -> bool {
143        self.no_bits_left() && self.no_references_left()
144    }
145
146    /// Returns an error if this parser has more data or references.
147    #[inline]
148    pub fn ensure_empty(&self) -> Result<(), CellParserError<'de>> {
149        if !self.is_empty() {
150            return Err(Error::custom(format!(
151                "more data left: {} bits, {} references",
152                self.data.len(),
153                self.references.len(),
154            )));
155        }
156        Ok(())
157    }
158
159    /// Returns whether this parsed cell is exotic.
160    #[inline]
161    pub const fn is_exotic(&self) -> bool {
162        self.is_exotic
163    }
164
165    /// Returns an error if this parsed cell is not exotic.
166    #[inline]
167    pub fn ensure_exotic(&self) -> Result<(), CellParserError<'de>> {
168        if !self.is_exotic() {
169            return Err(Error::custom("cell is not exotic"));
170        }
171        Ok(())
172    }
173
174    /// Returns an error if this parsed cell is not ordinary.
175    #[inline]
176    pub fn ensure_ordinary(&self) -> Result<(), CellParserError<'de>> {
177        if self.is_exotic() {
178            return Err(Error::custom("cell is not ordinary"));
179        }
180        Ok(())
181    }
182}
183
184impl<'de> BitReader<'de> for CellParser<'de> {
185    type Error = <&'de BitSlice<u8, Msb0> as BitReader<'de>>::Error;
186
187    #[inline]
188    fn bits_left(&self) -> usize {
189        self.data.len()
190    }
191
192    #[inline]
193    fn read_bit(&mut self) -> Result<Option<bool>, Self::Error> {
194        self.data.read_bit()
195    }
196
197    #[inline]
198    fn read_bits_into(&mut self, dst: &mut BitSlice<u8, Msb0>) -> Result<usize, Self::Error> {
199        self.data.read_bits_into(dst)
200    }
201
202    #[inline]
203    fn read_bits(&mut self, n: usize) -> Result<Cow<'de, BitSlice<u8, Msb0>>, Self::Error> {
204        self.data.read_bits(n)
205    }
206
207    #[inline]
208    fn skip(&mut self, n: usize) -> Result<usize, Self::Error> {
209        self.data.skip(n)
210    }
211}
212
213impl<'de> CellDeserialize<'de> for CellParser<'de> {
214    type Args = ();
215
216    #[inline]
217    fn parse(parser: &mut Self, (): Self::Args) -> Result<Self, CellParserError<'de>> {
218        Ok(Self {
219            is_exotic: parser.is_exotic,
220            data: mem::take(&mut parser.data),
221            references: mem::take(&mut parser.references),
222        })
223    }
224}