sml_rs/transport/
decoder_reader.rs

1//! module containing the `DecodeReader` and related implementation
2
3use core::fmt;
4
5use super::{DecodeErr, Decoder};
6use crate::util::{Buffer, ByteSource, ByteSourceErr};
7
8/// Error type used by the `DecoderReader`
9#[derive(Debug, PartialEq)]
10pub enum ReadDecodedError<IoErr> {
11    /// Error while decoding the data (e.g. checksum mismatch)
12    DecodeErr(DecodeErr),
13    /// Error while reading from the internal byte source
14    ///
15    /// (inner_error, num_discarded_bytes)
16    IoErr(IoErr, usize),
17}
18
19impl fmt::Display for ReadDecodedError<fmt::Error> {
20    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21        <Self as fmt::Debug>::fmt(self, f)
22    }
23}
24
25#[cfg(feature = "std")]
26impl std::error::Error for ReadDecodedError<fmt::Error> {}
27
28/// Decode transmissions read from a byte source
29pub struct DecoderReader<B, R>
30where
31    B: Buffer,
32    R: ByteSource,
33{
34    decoder: Decoder<B>,
35    reader: R,
36}
37
38impl<B, R> DecoderReader<B, R>
39where
40    B: Buffer,
41    R: ByteSource,
42{
43    /// Create a new decoder wrapping the provided reader.
44    pub fn new(reader: R) -> Self {
45        DecoderReader {
46            decoder: Default::default(),
47            reader,
48        }
49    }
50
51    /// Reads and decodes a transmission
52    ///
53    /// On success, returns the decoded transmission (`Ok(bytes)`). Otherwise, returns errors
54    /// (which can either be decoding errors or errors returned from the byte source).
55    ///
56    /// When reading from a finite data source (such as a file containing a certain
57    /// number of transmissions), it's easier to use [`next`](DecoderReader::next) instead,
58    /// which handles EOFs correctly.
59    ///
60    /// See also [`read_nb`](DecoderReader::read_nb), which provides a convenient API for
61    /// non-blocking byte sources.
62    pub fn read(&mut self) -> Result<&[u8], ReadDecodedError<R::ReadError>> {
63        loop {
64            match self.reader.read_byte() {
65                Ok(b) => match self.decoder._push_byte(b) {
66                    Ok(false) => continue,
67                    Ok(true) => return Ok(self.decoder.borrow_buf()),
68                    Err(e) => return Err(ReadDecodedError::DecodeErr(e)),
69                },
70                Err(e) => {
71                    assert!(!(e.is_eof() && e.is_would_block()));
72                    let discarded_bytes = if !e.is_would_block() {
73                        // reset the decoder
74                        self.decoder.reset()
75                    } else {
76                        0
77                    };
78                    // return the error
79                    return Err(ReadDecodedError::IoErr(e, discarded_bytes));
80                }
81            }
82        }
83    }
84
85    /// Tries to read and decode a transmission
86    ///
87    /// On success, returns the decoded transmission (`Some(Ok(bytes))`). Returns
88    /// `None` if the reader returns EOF immediately. Otherwise, returns errors
89    /// (which can either be decoding errors or errors returned from the byte source).
90    ///
91    /// When reading from a data source that will provide data infinitely (such
92    /// as from a serial port), it's easier to use [`read`](DecoderReader::read) instead.
93    ///
94    /// See also [`next_nb`](DecoderReader::next_nb), which provides a convenient API for
95    /// non-blocking byte sources.
96    #[allow(clippy::should_implement_trait)]
97    pub fn next(&mut self) -> Option<Result<&[u8], ReadDecodedError<R::ReadError>>> {
98        match self.read() {
99            Err(ReadDecodedError::IoErr(e, 0)) if e.is_eof() => None,
100            x => Some(x),
101        }
102    }
103
104    /// Reads and decodes a transmission (non-blocking)
105    ///
106    /// Same as [`read`](DecoderReader::read) except that it returns `nb::Result`.
107    /// If reading from the byte source indicates that data isn't available yet,
108    /// this method returns `Err(nb::Error::WouldBlock)`.
109    ///
110    /// Using `nb::Result` allows this method to be awaited using the `nb::block!` macro.
111    ///
112    /// *This function is available only if sml-rs is built with the `"nb"` or `"embedded_hal"` features.*
113    #[cfg(feature = "nb")]
114    pub fn read_nb(&mut self) -> nb::Result<&[u8], ReadDecodedError<R::ReadError>> {
115        self.read().map_err(|e| match e {
116            ReadDecodedError::IoErr(io_err, _) if io_err.is_would_block() => nb::Error::WouldBlock,
117            other => nb::Error::Other(other),
118        })
119    }
120
121    /// Tries to read and decode a transmission (non-blocking)
122    ///
123    /// Same as [`next`](DecoderReader::next) except that it returns `nb::Result`.
124    /// If reading from the byte source indicates that data isn't available yet,
125    /// this method returns `Err(nb::Error::WouldBlock)`.
126    ///
127    /// Using `nb::Result` allows this method to be awaited using the `nb::block!` macro.
128    ///
129    /// *This function is available only if sml-rs is built with the `"nb"` or `"embedded_hal"` features.*
130    #[cfg(feature = "nb")]
131    pub fn next_nb(&mut self) -> nb::Result<Option<&[u8]>, ReadDecodedError<R::ReadError>> {
132        match self.read_nb() {
133            Err(nb::Error::Other(ReadDecodedError::IoErr(e, 0))) if e.is_eof() => Ok(None),
134            Err(e) => Err(e),
135            Ok(x) => Ok(Some(x)),
136        }
137    }
138}
139
140#[cfg(test)]
141mod decoder_reader_tests {
142    use core::iter::once;
143
144    use crate::util::ArrayBuf;
145
146    use super::*;
147    use hex_literal::hex;
148
149    struct TestReader<I>
150    where
151        I: Iterator<Item = Result<u8, TestReaderErr>>,
152    {
153        iter: I,
154    }
155
156    impl<I> ByteSource for TestReader<I>
157    where
158        I: Iterator<Item = Result<u8, TestReaderErr>>,
159    {
160        type ReadError = TestReaderErr;
161
162        fn read_byte(&mut self) -> Result<u8, Self::ReadError> {
163            self.iter.next().unwrap_or(Err(TestReaderErr::Eof))
164        }
165    }
166
167    impl<I> crate::util::private::Sealed for TestReader<I> where
168        I: Iterator<Item = Result<u8, TestReaderErr>>
169    {
170    }
171
172    #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
173    enum TestReaderErr {
174        Eof,
175        Other,
176        WouldBlock,
177    }
178
179    impl ByteSourceErr for TestReaderErr {
180        fn is_eof(&self) -> bool {
181            matches!(self, TestReaderErr::Eof)
182        }
183
184        fn is_would_block(&self) -> bool {
185            matches!(self, TestReaderErr::WouldBlock)
186        }
187    }
188
189    impl crate::util::private::Sealed for TestReaderErr {}
190
191    fn decoder_from<I>(iter: I) -> DecoderReader<ArrayBuf<1024>, TestReader<I>>
192    where
193        I: Iterator<Item = Result<u8, TestReaderErr>>,
194    {
195        DecoderReader {
196            decoder: Default::default(),
197            reader: TestReader { iter },
198        }
199    }
200
201    #[test]
202    fn successful_read_then_eof() {
203        let data = hex!("1b1b1b1b 01010101 12345678 1b1b1b1b 1a00b87b");
204        let mut dr = decoder_from(data.into_iter().map(Ok));
205        assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
206        assert_eq!(dr.next(), None);
207    }
208
209    #[test]
210    fn eof_while_parsing() {
211        let data = hex!("1b1b1b1b 01010101 12");
212        let mut dr = decoder_from(data.into_iter().map(Ok));
213        assert_eq!(
214            dr.next(),
215            Some(Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 9)))
216        );
217        assert_eq!(dr.next(), None);
218        assert_eq!(dr.next(), None);
219    }
220
221    #[test]
222    fn err_while_parsing_ok_afterwards() {
223        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
224        let data2 = hex!("1b1b1b1b 01010101 12345678 1b1b1b1b 1a00b87b")
225            .into_iter()
226            .map(Ok);
227        let all_data = data.chain(once(Err(TestReaderErr::Other))).chain(data2);
228        let mut dr = decoder_from(all_data);
229        assert_eq!(
230            dr.next(),
231            Some(Err(ReadDecodedError::IoErr(TestReaderErr::Other, 9)))
232        );
233        assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
234        assert_eq!(dr.next(), None);
235        assert_eq!(dr.next(), None);
236    }
237
238    #[test]
239    fn would_block_while_parsing() {
240        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
241        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
242        let all_data = data
243            .chain(once(Err(TestReaderErr::WouldBlock)))
244            .chain(data2);
245        let mut dr = decoder_from(all_data);
246        assert_eq!(
247            dr.next(),
248            Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
249        );
250        assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
251        assert_eq!(dr.next(), None);
252        assert_eq!(dr.next(), None);
253    }
254
255    #[test]
256    fn would_block_before_parsing() {
257        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
258        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
259        let all_data = once(Err(TestReaderErr::WouldBlock))
260            .chain(data)
261            .chain(once(Err(TestReaderErr::WouldBlock)))
262            .chain(data2);
263        let mut dr = decoder_from(all_data);
264        assert_eq!(
265            dr.next(),
266            Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
267        );
268        assert_eq!(
269            dr.next(),
270            Some(Err(ReadDecodedError::IoErr(TestReaderErr::WouldBlock, 0)))
271        );
272        assert_eq!(dr.next(), Some(Ok(hex!("12345678").as_slice())));
273        assert_eq!(dr.next(), None);
274        assert_eq!(dr.next(), None);
275    }
276
277    #[test]
278    fn immediate_err() {
279        let all_data = once(Err(TestReaderErr::Other));
280        let mut dr = decoder_from(all_data);
281        assert_eq!(
282            dr.next(),
283            Some(Err(ReadDecodedError::IoErr(TestReaderErr::Other, 0)))
284        );
285        assert_eq!(dr.next(), None);
286        assert_eq!(dr.next(), None);
287    }
288
289    #[test]
290    #[cfg(feature = "nb")]
291    fn read_nb() {
292        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
293        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
294        let all_data = once(Err(TestReaderErr::WouldBlock))
295            .chain(data)
296            .chain(once(Err(TestReaderErr::WouldBlock)))
297            .chain(data2);
298        let mut dr = decoder_from(all_data);
299        assert_eq!(dr.read_nb(), Err(nb::Error::WouldBlock));
300        assert_eq!(dr.read_nb(), Err(nb::Error::WouldBlock));
301        assert_eq!(dr.read_nb(), Ok(hex!("12345678").as_slice()));
302        assert_eq!(
303            dr.read_nb(),
304            Err(nb::Error::Other(ReadDecodedError::IoErr(
305                TestReaderErr::Eof,
306                0
307            )))
308        );
309        assert_eq!(
310            dr.read_nb(),
311            Err(nb::Error::Other(ReadDecodedError::IoErr(
312                TestReaderErr::Eof,
313                0
314            )))
315        );
316    }
317
318    #[test]
319    #[cfg(feature = "nb")]
320    fn next_nb() {
321        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
322        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
323        let all_data = once(Err(TestReaderErr::WouldBlock))
324            .chain(data)
325            .chain(once(Err(TestReaderErr::WouldBlock)))
326            .chain(data2);
327        let mut dr = decoder_from(all_data);
328        assert_eq!(dr.next_nb(), Err(nb::Error::WouldBlock));
329        assert_eq!(dr.next_nb(), Err(nb::Error::WouldBlock));
330        assert_eq!(dr.next_nb(), Ok(Some(hex!("12345678").as_slice())));
331        assert_eq!(dr.next_nb(), Ok(None));
332        assert_eq!(dr.next_nb(), Ok(None));
333    }
334
335    #[test]
336    #[cfg(feature = "nb")]
337    fn nb_block_next_nb() {
338        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
339        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
340        let all_data = once(Err(TestReaderErr::WouldBlock))
341            .chain(data)
342            .chain(once(Err(TestReaderErr::WouldBlock)))
343            .chain(data2);
344        let mut dr = decoder_from(all_data);
345        assert_eq!(
346            nb::block!(dr.next_nb()),
347            Ok(Some(hex!("12345678").as_slice()))
348        );
349        assert_eq!(nb::block!(dr.next_nb()), Ok(None));
350        assert_eq!(nb::block!(dr.next_nb()), Ok(None));
351    }
352
353    #[test]
354    #[cfg(feature = "nb")]
355    fn nb_block_read_nb() {
356        let data = hex!("1b1b1b1b 01010101 12").into_iter().map(Ok);
357        let data2 = hex!("345678 1b1b1b1b 1a00b87b").into_iter().map(Ok);
358        let all_data = once(Err(TestReaderErr::WouldBlock))
359            .chain(data)
360            .chain(once(Err(TestReaderErr::WouldBlock)))
361            .chain(data2);
362        let mut dr = decoder_from(all_data);
363        assert_eq!(nb::block!(dr.read_nb()), Ok(hex!("12345678").as_slice()));
364        assert_eq!(
365            nb::block!(dr.read_nb()),
366            Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 0))
367        );
368        assert_eq!(
369            nb::block!(dr.read_nb()),
370            Err(ReadDecodedError::IoErr(TestReaderErr::Eof, 0))
371        );
372    }
373}