Struct SmlReader

Source
pub struct SmlReader<R, Buf>
where R: ByteSource, Buf: Buffer,
{ /* private fields */ }
Expand description

Main API of sml-rs

SmlReader is used to read sml data. It allows reading from various data sources and can produce different output depending on the use-case.

§Example

The following example shows how to parse an sml data set from a file:

use std::fs;
let f = fs::File::open("sample.bin").unwrap();
let mut reader = SmlReader::from_reader(f);
match reader.read::<File>() {
    Ok(x) => println!("Got result: {:#?}", x),
    Err(e) => println!("Error: {:?}", e),
}

§Data Source

The SmlReader struct can be used with several kinds of data providers:

Constructor (SmlReader::...)Expected data typeUsage examples
from_reader ¹impl std::io::Readfiles, sockets, serial ports (see serialport-rs crate)
from_eh_reader ²impl embedded_hal::serial::Read<u8>microcontroller pins
from_slice&[u8]arrays, vectors, …
from_iteratorimpl IntoIterator<Item = impl Borrow<u8>>)anything that can be turned into an iterator over bytes

¹ requires feature std (on by default); ² requires optional feature embedded_hal

§Internal Buffer

SmlReader reads sml messages into an internal buffer. By default, a static buffer with a size of 8 KiB is used, which should be more than enough for typical messages.

It is possible to use a different static buffer size or use a dynamically allocated buffer that can grow as necessary. SmlReader provides two associated functions for this purpose:

These functions return a builder object (SmlReaderBuilder) that provides methods to create an SmlReader from the different data sources shown above.

Examples

Creating a reader with a static 1KiB buffer from a slice:

let data = [1, 2, 3, 4, 5];
let reader = SmlReader::with_static_buffer::<1024>().from_slice(&data);

Creating a reader with a dynamically-sized buffer from an iterable:

let data = [1, 2, 3, 4, 5];
let reader_2 = SmlReader::with_vec_buffer().from_iterator(&data);

§Reading transmissions

Once a SmlReader is instantiated, it can be used to read, decode and parse SML messages. SmlReader provides two functions for this, read<T> and next<T>.

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = reader.read::<DecodedBytes>();
assert!(matches!(bytes, Ok(bytes)));
let bytes = reader.read::<DecodedBytes>();
assert!(matches!(bytes, Err(_)));

let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = reader.next::<DecodedBytes>();
assert!(matches!(bytes, Some(Ok(bytes))));
let bytes = reader.next::<DecodedBytes>();
assert!(matches!(bytes, None));

§Target Type

read<T> and next<T> can be used to parse sml transmissions into several different representations:

  • DecodedBytes: a slice of bytes containing the decoded message. No parsing is done.
  • File: a struct containing completely parsed sml data. (requires feature "alloc")
  • Parser: an streaming parser for sml data.

Examples

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = reader.read::<DecodedBytes>();
let file = reader.read::<File>();
let parser = reader.read::<Parser>();

Implementations§

Source§

impl SmlReader<SliceReader<'static>, ArrayBuf<0>>

Source

pub fn with_static_buffer<const N: usize>() -> SmlReaderBuilder<ArrayBuf<N>>

Returns a builder with a static internal buffer of size N.

Use the from_* methods on the builder to create an SmlReader.

§Examples
let data = [1, 2, 3];
let reader = SmlReader::with_static_buffer::<1024>().from_slice(&data);
Source

pub fn with_vec_buffer() -> SmlReaderBuilder<Vec<u8>>

Available on crate feature alloc only.

Returns a builder with a dynamically-sized internal buffer.

Use the from_* methods on the builder to create an SmlReader.

This function is available only if sml-rs is built with the "alloc" feature.

§Examples
let data = [1, 2, 3];
let reader = SmlReader::with_vec_buffer().from_slice(&data);
Source

pub fn from_reader<R>(reader: R) -> SmlReader<IoReader<R>, ArrayBuf<{ _ }>>
where R: Read,

Available on crate feature std only.

Build an SmlReader from a type implementing std::io::Read.

This function is available only if sml-rs is built with the "std" feature.

§Examples
let data = [1, 2, 3];
let cursor = std::io::Cursor::new(data);  // implements std::io::Read
let reader = SmlReader::from_reader(cursor);
Source

pub fn from_eh_reader<R, E>( reader: R, ) -> SmlReader<EhReader<R, E>, ArrayBuf<{ _ }>>
where R: Read<u8, Error = E>,

Available on crate feature embedded_hal only.

Build an SmlReader from a type implementing embedded_hal::serial::Read<u8>.

This function is available only if sml-rs is built with the "embedded-hal" feature.

§Examples
// usually provided by hardware abstraction layers (HALs) for specific chips
// let pin = ...;

let reader = SmlReader::from_eh_reader(pin);
Source

pub fn from_slice(reader: &[u8]) -> SmlReader<SliceReader<'_>, ArrayBuf<{ _ }>>

Build an SmlReader from a slice of bytes.

§Examples
let data: &[u8] = &[1, 2, 3];
let reader = SmlReader::from_slice(data);
Source

pub fn from_iterator<B, I>( iter: I, ) -> SmlReader<IterReader<I::IntoIter, B>, ArrayBuf<{ _ }>>
where I: IntoIterator<Item = B>, B: Borrow<u8>,

Build an SmlReader from a type that can be turned into a byte iterator.

§Examples
let data: [u8; 3] = [1, 2, 3];
let reader = SmlReader::from_iterator(data.clone());      // [u8; 3]
let reader = SmlReader::from_iterator(&data);             // &[u8; 3]
let reader = SmlReader::from_iterator(data.as_slice());   // &[u8]
let reader = SmlReader::from_iterator(data.iter());       // impl Iterator<Item = &u8>
let reader = SmlReader::from_iterator(data.into_iter());  // impl Iterator<Item = u8>
Source§

impl<R, ReadErr, Buf> SmlReader<R, Buf>
where R: ByteSource<ReadError = ReadErr>, ReadErr: Debug, Buf: Buffer,

Source

pub fn read<'i, T>(&'i mut self) -> Result<T, T::Error>
where T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,

Reads, decodes and possibly parses sml data.

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = reader.read::<DecodedBytes>();
assert!(matches!(bytes, Ok(bytes)));
let bytes = reader.read::<DecodedBytes>();
assert!(matches!(bytes, Err(_)));

This method can be used to parse sml data into several representations. See the module documentation for more information.

When reading from a finite data source (such as a file containing a certain number of transmissions), it’s easier to use next instead, which returns None when an EOF is read when trying to read the next transmission.

See also read_nb, which provides a convenient API for non-blocking byte sources.

Source

pub fn next<'i, T>(&'i mut self) -> Option<Result<T, T::Error>>
where T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,

Tries to read, decode and possibly parse sml data.

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = reader.next::<DecodedBytes>();
assert!(matches!(bytes, Some(Ok(bytes))));
let bytes = reader.next::<DecodedBytes>();
assert!(matches!(bytes, None));

This method can be used to parse sml data into several representations. See the module documentation for more information.

When reading from a data source that will provide data infinitely (such as from a serial port), it’s easier to use read instead.

See also next_nb, which provides a convenient API for non-blocking byte sources.

Source

pub fn read_nb<'i, T>(&'i mut self) -> Result<T, T::Error>
where T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,

Available on crate feature nb only.

Reads, decodes and possibly parses sml data (non-blocking).

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = nb::block!(reader.read_nb::<DecodedBytes>());
assert!(matches!(bytes, Ok(bytes)));
let bytes = nb::block!(reader.read_nb::<DecodedBytes>());
assert!(matches!(bytes, Err(_)));

Same as read except that it returns nb::Result. If reading from the byte source indicates that data isn’t available yet, this method returns Err(nb::Error::WouldBlock).

Using nb::Result allows this method to be awaited using the nb::block! macro.

This function is available only if sml-rs is built with the "nb" or "embedded_hal" features.

Source

pub fn next_nb<'i, T>(&'i mut self) -> Result<Option<T>, T::Error>
where T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,

Available on crate feature nb only.

Tries to read, decode and possibly parse sml data (non-blocking).

let data = include_bytes!("../sample.bin");
let mut reader = SmlReader::from_slice(data.as_slice());

let bytes = nb::block!(reader.next_nb::<DecodedBytes>());
assert!(matches!(bytes, Ok(Some(bytes))));
let bytes = nb::block!(reader.next_nb::<DecodedBytes>());
assert!(matches!(bytes, Ok(None)));

Same as next except that it returns nb::Result. If reading from the byte source indicates that data isn’t available yet, this method returns Err(nb::Error::WouldBlock).

Using nb::Result allows this method to be awaited using the nb::block! macro.

This function is available only if sml-rs is built with the "nb" or "embedded_hal" features.

Auto Trait Implementations§

§

impl<R, Buf> Freeze for SmlReader<R, Buf>
where R: Freeze, Buf: Freeze,

§

impl<R, Buf> RefUnwindSafe for SmlReader<R, Buf>

§

impl<R, Buf> Send for SmlReader<R, Buf>
where R: Send, Buf: Send,

§

impl<R, Buf> Sync for SmlReader<R, Buf>
where R: Sync, Buf: Sync,

§

impl<R, Buf> Unpin for SmlReader<R, Buf>
where R: Unpin, Buf: Unpin,

§

impl<R, Buf> UnwindSafe for SmlReader<R, Buf>
where R: UnwindSafe, Buf: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.