sml_rs/
lib.rs

1//! Smart Message Language (SML) parser written in Rust.
2//!
3//! Modern German power meters periodically send SML-encoded data via an optical interface.
4//! The main use-case of this library is to decode that data.
5//!
6//! See the [`transport`] module for encoding / decoding the SML transport protocol v1 and the
7//! [`parser`] module for parsing decoded data into SML data structures.
8//!
9//! Complete examples of how to use the library can be found on github in the [`examples`](https://github.com/felixwrt/sml-rs/tree/main/examples) folder.
10//!
11//! # Feature flags
12//! - **`std`** (default) — Remove this feature to make the library `no_std` compatible.
13//! - **`alloc`** (default) — Implementations using allocations (`alloc::Vec` et al.).
14//! - **`embedded_hal`** — Allows using pins implementing `embedded_hal::serial::Read` in [`SmlReader`](SmlReader::from_eh_reader).
15//! - **`nb`** - Enables non-blocking APIs using the `nb` crate.
16//!
17#![cfg_attr(not(feature = "std"), no_std)]
18#![cfg_attr(docsrs, feature(doc_auto_cfg))]
19#![deny(unsafe_code)]
20#![warn(missing_docs)]
21
22use core::fmt;
23use core::{borrow::Borrow, marker::PhantomData};
24
25#[cfg(feature = "alloc")]
26use parser::complete::{parse, File};
27use parser::streaming::Parser;
28use parser::ParseError;
29use transport::{DecodeErr, DecoderReader, ReadDecodedError};
30use util::{ArrayBuf, Buffer};
31
32#[cfg(feature = "alloc")]
33extern crate alloc;
34
35pub mod parser;
36pub mod transport;
37pub mod util;
38
39use util::ByteSource;
40
41/// Error returned by functions parsing sml data read from a reader
42#[derive(Debug)]
43pub enum ReadParsedError<ReadErr>
44where
45    ReadErr: core::fmt::Debug,
46{
47    /// Error while parsing
48    ParseErr(ParseError),
49    /// Error while decoding the data (e.g. checksum mismatch)
50    DecodeErr(DecodeErr),
51    /// Error while reading from the internal byte source
52    ///
53    /// (inner_error, num_discarded_bytes)
54    IoErr(ReadErr, usize),
55}
56
57impl<ReadErr> From<ReadDecodedError<ReadErr>> for ReadParsedError<ReadErr>
58where
59    ReadErr: core::fmt::Debug,
60{
61    fn from(value: ReadDecodedError<ReadErr>) -> Self {
62        match value {
63            ReadDecodedError::DecodeErr(x) => ReadParsedError::DecodeErr(x),
64            ReadDecodedError::IoErr(x, num_discarded) => ReadParsedError::IoErr(x, num_discarded),
65        }
66    }
67}
68
69impl<ReadErr> From<ParseError> for ReadParsedError<ReadErr>
70where
71    ReadErr: core::fmt::Debug,
72{
73    fn from(value: ParseError) -> Self {
74        ReadParsedError::ParseErr(value)
75    }
76}
77
78impl<ReadErr> fmt::Display for ReadParsedError<ReadErr>
79where
80    ReadErr: core::fmt::Debug,
81{
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        <Self as fmt::Debug>::fmt(self, f)
84    }
85}
86
87#[cfg(feature = "std")]
88impl<ReadErr> std::error::Error for ReadParsedError<ReadErr> where ReadErr: core::fmt::Debug {}
89
90// ===========================================================================
91// ===========================================================================
92//      `SmlReader` + impls
93// ===========================================================================
94// ===========================================================================
95
96/// Main API of `sml-rs`
97///
98/// `SmlReader` is used to read sml data. It allows reading from various data
99/// sources and can produce different output depending on the use-case.
100///
101/// ## Example
102///
103/// The following example shows how to parse an sml data set from a file:
104///
105/// ```
106/// # #[cfg(feature = "std")] {
107/// # use sml_rs::{parser::complete::File, SmlReader};
108/// use std::fs;
109/// let f = fs::File::open("sample.bin").unwrap();
110/// let mut reader = SmlReader::from_reader(f);
111/// match reader.read::<File>() {
112///     Ok(x) => println!("Got result: {:#?}", x),
113///     Err(e) => println!("Error: {:?}", e),
114/// }
115/// # }
116/// ```
117/// ### Data Source
118///
119/// The `SmlReader` struct can be used with several kinds of data providers:
120///
121/// | Constructor (`SmlReader::...`)          | Expected data type | Usage examples |
122/// |-----------------------------------------------------|-----------|------------|
123/// |[`from_reader`](SmlReader::from_reader) **¹**             | `impl std::io::Read` | files, sockets, serial ports (see `serialport-rs` crate) |
124/// |[`from_eh_reader`](SmlReader::from_eh_reader) **²** | `impl embedded_hal::serial::Read<u8>` | microcontroller pins |
125/// |[`from_slice`](SmlReader::from_slice)                | `&[u8]` | arrays, vectors, ... |
126/// |[`from_iterator`](SmlReader::from_iterator)                  | `impl IntoIterator<Item = impl Borrow<u8>>)` | anything that can be turned into an iterator over bytes |
127///
128/// ***¹** requires feature `std` (on by default); **²** requires optional feature `embedded_hal`*
129///
130/// ### Internal Buffer
131///
132/// `SmlReader` reads sml messages into an internal buffer. By default, a static
133/// buffer with a size of 8 KiB is used, which should be more than enough for
134/// typical messages.
135///
136/// It is possible to use a different static buffer size or use a dynamically
137/// allocated buffer that can grow as necessary. `SmlReader` provides two associated
138/// functions for this purpose:
139///
140/// - [`SmlReader::with_static_buffer<N>()`](SmlReader::with_static_buffer)
141/// - [`SmlReader::with_vec_buffer()`](SmlReader::with_vec_buffer) *(requires feature `alloc` (on by default))*
142///
143/// These functions return a builder object ([`SmlReaderBuilder`]) that provides methods to create an [`SmlReader`]
144/// from the different data sources shown above.
145///
146/// **Examples**
147///
148/// Creating a reader with a static 1KiB buffer from a slice:
149///
150/// ```
151/// # use sml_rs::SmlReader;
152/// let data = [1, 2, 3, 4, 5];
153/// let reader = SmlReader::with_static_buffer::<1024>().from_slice(&data);
154/// ```
155///
156/// Creating a reader with a dynamically-sized buffer from an iterable:
157///
158/// ```
159/// # #[cfg(feature = "alloc")] {
160/// # use sml_rs::SmlReader;
161/// let data = [1, 2, 3, 4, 5];
162/// let reader_2 = SmlReader::with_vec_buffer().from_iterator(&data);
163/// # }
164/// ```
165///
166/// ### Reading transmissions
167///
168/// Once a `SmlReader` is instantiated, it can be used to read, decode and parse SML messages. `SmlReader`
169/// provides two functions for this, [`read<T>`](DecoderReader::read) and [`next<T>`](DecoderReader::next).
170///
171/// ```
172/// # use sml_rs::{SmlReader, DecodedBytes};
173/// let data = include_bytes!("../sample.bin");
174/// let mut reader = SmlReader::from_slice(data.as_slice());
175///
176/// let bytes = reader.read::<DecodedBytes>();
177/// assert!(matches!(bytes, Ok(bytes)));
178/// let bytes = reader.read::<DecodedBytes>();
179/// assert!(matches!(bytes, Err(_)));
180///
181/// let mut reader = SmlReader::from_slice(data.as_slice());
182///
183/// let bytes = reader.next::<DecodedBytes>();
184/// assert!(matches!(bytes, Some(Ok(bytes))));
185/// let bytes = reader.next::<DecodedBytes>();
186/// assert!(matches!(bytes, None));
187/// ```
188///
189/// ### Target Type
190///
191/// [`read<T>`](DecoderReader::read) and [`next<T>`](DecoderReader::next) can be used to parse sml
192/// transmissions into several different representations:
193///
194/// - [`DecodedBytes`]: a slice of bytes containing the decoded message. No parsing is done.
195/// - [`File`]: a struct containing completely parsed sml data. (requires feature `"alloc"`)
196/// - [`Parser`]: an streaming parser for sml data.
197///
198/// **Examples**
199///
200/// ```
201/// # use sml_rs::{SmlReader, DecodedBytes, parser::streaming::Parser};
202/// # #[cfg(feature = "alloc")]
203/// # use sml_rs::parser::complete::File;
204/// let data = include_bytes!("../sample.bin");
205/// let mut reader = SmlReader::from_slice(data.as_slice());
206///
207/// let bytes = reader.read::<DecodedBytes>();
208/// # #[cfg(feature = "alloc")] {
209/// let file = reader.read::<File>();
210/// # }
211/// let parser = reader.read::<Parser>();
212/// ```
213pub struct SmlReader<R, Buf>
214where
215    R: ByteSource,
216    Buf: Buffer,
217{
218    decoder: DecoderReader<Buf, R>,
219}
220
221pub(crate) type DummySmlReader = SmlReader<util::SliceReader<'static>, ArrayBuf<0>>;
222
223impl DummySmlReader {
224    /// Returns a builder with a static internal buffer of size `N`.
225    ///
226    /// Use the `from_*` methods on the builder to create an `SmlReader`.
227    ///
228    /// # Examples
229    ///
230    /// ```
231    /// # use sml_rs::SmlReader;
232    /// let data = [1, 2, 3];
233    /// let reader = SmlReader::with_static_buffer::<1024>().from_slice(&data);
234    /// ```
235    pub fn with_static_buffer<const N: usize>() -> SmlReaderBuilder<ArrayBuf<N>> {
236        SmlReaderBuilder { buf: PhantomData }
237    }
238
239    /// Returns a builder with a dynamically-sized internal buffer.
240    ///
241    /// Use the `from_*` methods on the builder to create an `SmlReader`.
242    ///
243    /// *This function is available only if sml-rs is built with the `"alloc"` feature.*
244    ///
245    /// # Examples
246    ///
247    /// ```
248    /// # use sml_rs::SmlReader;
249    /// let data = [1, 2, 3];
250    /// let reader = SmlReader::with_vec_buffer().from_slice(&data);
251    /// ```
252    #[cfg(feature = "alloc")]
253    pub fn with_vec_buffer() -> SmlReaderBuilder<alloc::vec::Vec<u8>> {
254        SmlReaderBuilder { buf: PhantomData }
255    }
256
257    /// Build an `SmlReader` from a type implementing `std::io::Read`.
258    ///
259    /// *This function is available only if sml-rs is built with the `"std"` feature.*
260    ///
261    /// # Examples
262    ///
263    /// ```
264    /// # use sml_rs::SmlReader;
265    /// let data = [1, 2, 3];
266    /// let cursor = std::io::Cursor::new(data);  // implements std::io::Read
267    /// let reader = SmlReader::from_reader(cursor);
268    /// ```
269    #[cfg(feature = "std")]
270    pub fn from_reader<R>(reader: R) -> SmlReader<util::IoReader<R>, DefaultBuffer>
271    where
272        R: std::io::Read,
273    {
274        SmlReader {
275            decoder: DecoderReader::new(util::IoReader::new(reader)),
276        }
277    }
278
279    /// Build an `SmlReader` from a type implementing `embedded_hal::serial::Read<u8>`.
280    ///
281    /// *This function is available only if sml-rs is built with the `"embedded-hal"` feature.*
282    ///
283    /// # Examples
284    ///
285    /// ```
286    /// # use sml_rs::SmlReader;
287    /// // usually provided by hardware abstraction layers (HALs) for specific chips
288    /// // let pin = ...;
289    /// # struct Pin;
290    /// # impl embedded_hal::serial::Read<u8> for Pin {
291    /// #     type Error = ();
292    /// #     fn read(&mut self) -> nb::Result<u8, Self::Error> { Ok(123) }
293    /// # }
294    /// # let pin = Pin;
295    ///
296    /// let reader = SmlReader::from_eh_reader(pin);
297    /// ```
298    #[cfg(feature = "embedded_hal")]
299    pub fn from_eh_reader<R, E>(reader: R) -> SmlReader<util::EhReader<R, E>, DefaultBuffer>
300    where
301        R: embedded_hal::serial::Read<u8, Error = E>,
302    {
303        SmlReader {
304            decoder: DecoderReader::new(util::EhReader::new(reader)),
305        }
306    }
307
308    /// Build an `SmlReader` from a slice of bytes.
309    ///
310    /// # Examples
311    ///
312    /// ```
313    /// # use sml_rs::SmlReader;
314    /// let data: &[u8] = &[1, 2, 3];
315    /// let reader = SmlReader::from_slice(data);
316    /// ```
317    pub fn from_slice(reader: &[u8]) -> SmlReader<util::SliceReader<'_>, DefaultBuffer> {
318        SmlReader {
319            decoder: DecoderReader::new(util::SliceReader::new(reader)),
320        }
321    }
322
323    /// Build an `SmlReader` from a type that can be turned into a byte iterator.
324    ///
325    /// # Examples
326    ///
327    /// ```
328    /// # use sml_rs::SmlReader;
329    /// let data: [u8; 3] = [1, 2, 3];
330    /// let reader = SmlReader::from_iterator(data.clone());      // [u8; 3]
331    /// let reader = SmlReader::from_iterator(&data);             // &[u8; 3]
332    /// let reader = SmlReader::from_iterator(data.as_slice());   // &[u8]
333    /// let reader = SmlReader::from_iterator(data.iter());       // impl Iterator<Item = &u8>
334    /// let reader = SmlReader::from_iterator(data.into_iter());  // impl Iterator<Item = u8>
335    /// ```
336    pub fn from_iterator<B, I>(
337        iter: I,
338    ) -> SmlReader<util::IterReader<I::IntoIter, B>, DefaultBuffer>
339    where
340        I: IntoIterator<Item = B>,
341        B: Borrow<u8>,
342    {
343        SmlReader {
344            decoder: DecoderReader::new(util::IterReader::new(iter.into_iter())),
345        }
346    }
347}
348
349impl<R, ReadErr, Buf> SmlReader<R, Buf>
350where
351    R: ByteSource<ReadError = ReadErr>,
352    ReadErr: core::fmt::Debug,
353    Buf: Buffer,
354{
355    /// Reads, decodes and possibly parses sml data.
356    ///
357    /// ```
358    /// # use sml_rs::{SmlReader, DecodedBytes};
359    /// let data = include_bytes!("../sample.bin");
360    /// let mut reader = SmlReader::from_slice(data.as_slice());
361    ///
362    /// let bytes = reader.read::<DecodedBytes>();
363    /// assert!(matches!(bytes, Ok(bytes)));
364    /// let bytes = reader.read::<DecodedBytes>();
365    /// assert!(matches!(bytes, Err(_)));
366    /// ```
367    ///
368    /// This method can be used to parse sml data into several representations.
369    /// See the module documentation for more information.
370    ///
371    /// When reading from a finite data source (such as a file containing a certain
372    /// number of transmissions), it's easier to use [`next`](SmlReader::next) instead,
373    /// which returns `None` when an EOF is read when trying to read the next transmission.
374    ///
375    /// See also [`read_nb`](DecoderReader::read_nb), which provides a convenient API for
376    /// non-blocking byte sources.
377    pub fn read<'i, T>(&'i mut self) -> Result<T, T::Error>
378    where
379        T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
380    {
381        T::parse_from(self.decoder.read())
382    }
383
384    /// Tries to read, decode and possibly parse sml data.
385    ///
386    /// ```
387    /// # use sml_rs::{SmlReader, DecodedBytes};
388    /// let data = include_bytes!("../sample.bin");
389    /// let mut reader = SmlReader::from_slice(data.as_slice());
390    ///
391    /// let bytes = reader.next::<DecodedBytes>();
392    /// assert!(matches!(bytes, Some(Ok(bytes))));
393    /// let bytes = reader.next::<DecodedBytes>();
394    /// assert!(matches!(bytes, None));
395    /// ```
396    ///
397    /// This method can be used to parse sml data into several representations.
398    /// See the module documentation for more information.
399    ///
400    /// When reading from a data source that will provide data infinitely (such
401    /// as from a serial port), it's easier to use [`read`](SmlReader::read) instead.
402    ///
403    /// See also [`next_nb`](SmlReader::next_nb), which provides a convenient API for
404    /// non-blocking byte sources.
405    pub fn next<'i, T>(&'i mut self) -> Option<Result<T, T::Error>>
406    where
407        T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
408    {
409        Some(T::parse_from(self.decoder.next()?))
410    }
411
412    /// Reads, decodes and possibly parses sml data (non-blocking).
413    ///
414    /// ```
415    /// # use sml_rs::{SmlReader, DecodedBytes};
416    /// let data = include_bytes!("../sample.bin");
417    /// let mut reader = SmlReader::from_slice(data.as_slice());
418    ///
419    /// let bytes = nb::block!(reader.read_nb::<DecodedBytes>());
420    /// assert!(matches!(bytes, Ok(bytes)));
421    /// let bytes = nb::block!(reader.read_nb::<DecodedBytes>());
422    /// assert!(matches!(bytes, Err(_)));
423    /// ```
424    ///
425    /// Same as [`read`](SmlReader::read) except that it returns `nb::Result`.
426    /// If reading from the byte source indicates that data isn't available yet,
427    /// this method returns `Err(nb::Error::WouldBlock)`.
428    ///
429    /// Using `nb::Result` allows this method to be awaited using the `nb::block!` macro.
430    ///
431    /// *This function is available only if sml-rs is built with the `"nb"` or `"embedded_hal"` features.*
432    #[cfg(feature = "nb")]
433    pub fn read_nb<'i, T>(&'i mut self) -> nb::Result<T, T::Error>
434    where
435        T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
436    {
437        // TODO: this could probably be written better
438        let res = match self.decoder.read_nb() {
439            Ok(x) => Ok(x),
440            Err(nb::Error::WouldBlock) => return Err(nb::Error::WouldBlock),
441            Err(nb::Error::Other(e)) => Err(e),
442        };
443        T::parse_from(res).map_err(nb::Error::Other)
444    }
445
446    /// Tries to read, decode and possibly parse sml data (non-blocking).
447    ///
448    /// ```
449    /// # use sml_rs::{SmlReader, DecodedBytes};
450    /// let data = include_bytes!("../sample.bin");
451    /// let mut reader = SmlReader::from_slice(data.as_slice());
452    ///
453    /// let bytes = nb::block!(reader.next_nb::<DecodedBytes>());
454    /// assert!(matches!(bytes, Ok(Some(bytes))));
455    /// let bytes = nb::block!(reader.next_nb::<DecodedBytes>());
456    /// assert!(matches!(bytes, Ok(None)));
457    /// ```
458    ///
459    /// Same as [`next`](SmlReader::next) except that it returns `nb::Result`.
460    /// If reading from the byte source indicates that data isn't available yet,
461    /// this method returns `Err(nb::Error::WouldBlock)`.
462    ///
463    /// Using `nb::Result` allows this method to be awaited using the `nb::block!` macro.
464    ///
465    /// *This function is available only if sml-rs is built with the `"nb"` or `"embedded_hal"` features.*
466    #[cfg(feature = "nb")]
467    pub fn next_nb<'i, T>(&'i mut self) -> nb::Result<Option<T>, T::Error>
468    where
469        T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
470    {
471        // TODO: this could probably be written better
472        let res = match self.decoder.next_nb() {
473            Ok(None) => return Ok(None),
474            Ok(Some(x)) => Ok(x),
475            Err(nb::Error::WouldBlock) => return Err(nb::Error::WouldBlock),
476            Err(nb::Error::Other(e)) => Err(e),
477        };
478        T::parse_from(res).map(Some).map_err(nb::Error::Other)
479    }
480}
481
482type DefaultBuffer = ArrayBuf<{ 8 * 1024 }>;
483
484/// Builder struct for `SmlReader` that allows configuring the internal buffer type.
485///
486/// See [here](SmlReader#internal-buffer) for an explanation of the different internal
487/// buffer types and how to use the builder to customize them.
488pub struct SmlReaderBuilder<Buf: Buffer> {
489    buf: PhantomData<Buf>,
490}
491
492impl<Buf: Buffer> Clone for SmlReaderBuilder<Buf> {
493    fn clone(&self) -> Self {
494        Self { buf: PhantomData }
495    }
496}
497
498impl<Buf: Buffer> SmlReaderBuilder<Buf> {
499    /// Build an `SmlReader` from a type implementing `std::io::Read`.
500    ///
501    /// *This function is available only if sml-rs is built with the `"std"` feature.*
502    ///
503    /// # Examples
504    ///
505    /// ```
506    /// # use sml_rs::SmlReader;
507    /// let data = [1, 2, 3];
508    /// let cursor = std::io::Cursor::new(data);  // implements std::io::Read
509    /// let reader = SmlReader::with_static_buffer::<1024>().from_reader(cursor);
510    /// ```
511    #[cfg(feature = "std")]
512    pub fn from_reader<R: std::io::Read>(self, reader: R) -> SmlReader<util::IoReader<R>, Buf> {
513        SmlReader {
514            decoder: DecoderReader::new(util::IoReader::new(reader)),
515        }
516    }
517
518    /// Build an `SmlReader` from a type implementing `embedded_hal::serial::Read<u8>`.
519    ///
520    /// *This function is available only if sml-rs is built with the `"embedded-hal"` feature.*
521    ///
522    /// # Examples
523    ///
524    /// ```
525    /// # use sml_rs::SmlReader;
526    /// // usually provided by hardware abstraction layers (HALs) for specific chips
527    /// // let pin = ...;
528    /// # struct Pin;
529    /// # impl embedded_hal::serial::Read<u8> for Pin {
530    /// #     type Error = ();
531    /// #     fn read(&mut self) -> nb::Result<u8, Self::Error> { Ok(123) }
532    /// # }
533    /// # let pin = Pin;
534    ///
535    /// let reader = SmlReader::with_static_buffer::<1024>().from_eh_reader(pin);
536    /// ```
537    #[cfg(feature = "embedded_hal")]
538    pub fn from_eh_reader<R: embedded_hal::serial::Read<u8, Error = E>, E>(
539        self,
540        reader: R,
541    ) -> SmlReader<util::EhReader<R, E>, Buf> {
542        SmlReader {
543            decoder: DecoderReader::new(util::EhReader::new(reader)),
544        }
545    }
546
547    /// Build an `SmlReader` from a slice of bytes.
548    ///
549    /// # Examples
550    ///
551    /// ```
552    /// # use sml_rs::SmlReader;
553    /// let data: &[u8] = &[1, 2, 3];
554    /// let reader = SmlReader::with_static_buffer::<1024>().from_slice(data);
555    /// ```
556    pub fn from_slice(self, reader: &[u8]) -> SmlReader<util::SliceReader<'_>, Buf> {
557        SmlReader {
558            decoder: DecoderReader::new(util::SliceReader::new(reader)),
559        }
560    }
561
562    /// Build an `SmlReader` from a type that can be turned into a byte iterator.
563    ///
564    /// # Examples
565    ///
566    /// ```
567    /// # use sml_rs::SmlReader;
568    /// let data: [u8; 3] = [1, 2, 3];
569    /// let builder = SmlReader::with_static_buffer::<1024>();
570    /// let reader = builder.clone().from_iterator(data.clone());      // [u8; 3]
571    /// let reader = builder.clone().from_iterator(&data);             // &[u8; 3]
572    /// let reader = builder.clone().from_iterator(data.as_slice());   // &[u8]
573    /// let reader = builder.clone().from_iterator(data.iter());       // impl Iterator<Item = &u8>
574    /// let reader = builder.clone().from_iterator(data.into_iter());  // impl Iterator<Item = u8>
575    /// ```
576    pub fn from_iterator<B, I>(self, iter: I) -> SmlReader<util::IterReader<I::IntoIter, B>, Buf>
577    where
578        I: IntoIterator<Item = B>,
579        B: Borrow<u8>,
580    {
581        SmlReader {
582            decoder: DecoderReader::new(util::IterReader::new(iter.into_iter())),
583        }
584    }
585}
586
587/// Helper trait implemented for types that can be built from decoded bytes.
588pub trait SmlParse<'i, T>: Sized + util::private::Sealed {
589    /// The error produced if parsing fails or the input contained an error.
590    type Error;
591
592    /// Takes the result of decoding and parses it into the resulting type.
593    fn parse_from(value: T) -> Result<Self, Self::Error>;
594}
595
596/// Type alias for decoded bytes.
597pub type DecodedBytes<'i> = &'i [u8];
598
599type ReadDecodedRes<'i, ReadErr> = Result<&'i [u8], ReadDecodedError<ReadErr>>;
600
601impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for DecodedBytes<'i>
602where
603    ReadErr: core::fmt::Debug,
604{
605    type Error = ReadDecodedError<ReadErr>;
606
607    fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
608        value
609    }
610}
611
612impl<'i> SmlParse<'i, &'i [u8]> for DecodedBytes<'i> {
613    type Error = core::convert::Infallible;
614
615    fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
616        Ok(value)
617    }
618}
619
620impl<'i> util::private::Sealed for DecodedBytes<'i> {}
621
622#[cfg(feature = "alloc")]
623impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for File<'i>
624where
625    ReadErr: core::fmt::Debug,
626{
627    type Error = ReadParsedError<ReadErr>;
628
629    fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
630        Ok(parse(value?)?)
631    }
632}
633
634#[cfg(feature = "alloc")]
635impl<'i> SmlParse<'i, &'i [u8]> for File<'i> {
636    type Error = ParseError;
637
638    fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
639        parse(value)
640    }
641}
642
643#[cfg(feature = "alloc")]
644impl<'i> util::private::Sealed for File<'i> {}
645
646impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for Parser<'i>
647where
648    ReadErr: core::fmt::Debug,
649{
650    type Error = ReadDecodedError<ReadErr>;
651
652    fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
653        Ok(Parser::new(value?))
654    }
655}
656
657impl<'i> SmlParse<'i, &'i [u8]> for Parser<'i> {
658    type Error = core::convert::Infallible;
659
660    fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
661        Ok(Parser::new(value))
662    }
663}
664
665impl<'i> util::private::Sealed for Parser<'i> {}
666
667#[test]
668fn test_smlreader_construction() {
669    let arr = [1, 2, 3, 4, 5];
670
671    // no deps
672
673    // using default buffer
674    SmlReader::from_slice(&arr);
675    SmlReader::from_iterator(&arr);
676    SmlReader::from_iterator(arr.iter().map(|x| x + 1));
677    #[cfg(feature = "std")]
678    SmlReader::from_reader(std::io::Cursor::new(&arr));
679
680    // using static buffer
681    SmlReader::with_static_buffer::<1234>().from_slice(&arr);
682    SmlReader::with_static_buffer::<1234>().from_iterator(arr.iter().map(|x| x + 1));
683    #[cfg(feature = "std")]
684    SmlReader::with_static_buffer::<1234>().from_reader(std::io::Cursor::new(&arr));
685
686    // using dynamic buffer
687    #[cfg(feature = "alloc")]
688    SmlReader::with_vec_buffer().from_slice(&arr);
689    #[cfg(feature = "alloc")]
690    SmlReader::with_vec_buffer().from_iterator(arr.iter().map(|x| x + 1));
691    #[cfg(feature = "std")]
692    SmlReader::with_vec_buffer().from_reader(std::io::Cursor::new(&arr));
693}
694
695#[test]
696#[cfg(feature = "embedded_hal")]
697fn test_smlreader_eh_construction() {
698    // dummy struct implementing `Read`
699    struct Pin;
700    impl embedded_hal::serial::Read<u8> for Pin {
701        type Error = i16;
702
703        fn read(&mut self) -> nb::Result<u8, Self::Error> {
704            Ok(123)
705        }
706    }
707
708    // using default buffer
709    SmlReader::from_eh_reader(Pin);
710
711    // using static buffer
712    SmlReader::with_static_buffer::<1234>().from_eh_reader(Pin);
713
714    // using dynamic buffer
715    #[cfg(feature = "alloc")]
716    SmlReader::with_vec_buffer().from_eh_reader(Pin);
717}
718
719mod read_tests {
720    #[test]
721    fn test_smlreader_reading() {
722        // check that different types can be used with read and next
723        #[cfg(feature = "alloc")]
724        use super::File;
725        use super::{DecodedBytes, Parser, SmlReader};
726
727        let bytes = [1, 2, 3, 4];
728        let mut reader = SmlReader::from_slice(&bytes);
729
730        let _ = reader.read::<DecodedBytes>();
731        let _: Result<DecodedBytes, _> = reader.read();
732
733        #[cfg(feature = "alloc")]
734        let _ = reader.read::<File>();
735        let _ = reader.read::<Parser>();
736
737        let _ = reader.next::<DecodedBytes>();
738        #[cfg(feature = "alloc")]
739        let _ = reader.next::<File>();
740        let _ = reader.next::<Parser>();
741    }
742
743    #[test]
744    #[cfg(feature = "nb")]
745    fn test_smlreader_reading_nb() {
746        // check that different types can be used with read_nb and next_nb
747        #[cfg(feature = "alloc")]
748        use super::File;
749        use super::{DecodedBytes, Parser, SmlReader};
750
751        let bytes = [1, 2, 3, 4];
752        let mut reader = SmlReader::from_slice(&bytes);
753
754        let _ = reader.next_nb::<DecodedBytes>();
755        #[cfg(feature = "alloc")]
756        let _ = reader.next_nb::<File>();
757        let _ = reader.next_nb::<Parser>();
758
759        let _ = reader.read_nb::<DecodedBytes>();
760        #[cfg(feature = "alloc")]
761        let _ = reader.read_nb::<File>();
762        let _ = reader.read_nb::<Parser>();
763    }
764}