#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
#![deny(unsafe_code)]
#![warn(missing_docs)]
use core::fmt;
use core::{borrow::Borrow, marker::PhantomData};
#[cfg(feature = "alloc")]
use parser::complete::{parse, File};
use parser::streaming::Parser;
use parser::ParseError;
use transport::{DecodeErr, DecoderReader, ReadDecodedError};
use util::{ArrayBuf, Buffer};
#[cfg(feature = "alloc")]
extern crate alloc;
pub mod parser;
pub mod transport;
pub mod util;
use util::ByteSource;
#[derive(Debug)]
pub enum ReadParsedError<ReadErr>
where
ReadErr: core::fmt::Debug,
{
ParseErr(ParseError),
DecodeErr(DecodeErr),
IoErr(ReadErr, usize),
}
impl<ReadErr> From<ReadDecodedError<ReadErr>> for ReadParsedError<ReadErr>
where
ReadErr: core::fmt::Debug,
{
fn from(value: ReadDecodedError<ReadErr>) -> Self {
match value {
ReadDecodedError::DecodeErr(x) => ReadParsedError::DecodeErr(x),
ReadDecodedError::IoErr(x, num_discarded) => ReadParsedError::IoErr(x, num_discarded),
}
}
}
impl<ReadErr> From<ParseError> for ReadParsedError<ReadErr>
where
ReadErr: core::fmt::Debug,
{
fn from(value: ParseError) -> Self {
ReadParsedError::ParseErr(value)
}
}
impl<ReadErr> fmt::Display for ReadParsedError<ReadErr>
where
ReadErr: core::fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
<Self as fmt::Debug>::fmt(self, f)
}
}
#[cfg(feature = "std")]
impl<ReadErr> std::error::Error for ReadParsedError<ReadErr> where ReadErr: core::fmt::Debug {}
pub struct SmlReader<R, Buf>
where
R: ByteSource,
Buf: Buffer,
{
decoder: DecoderReader<Buf, R>,
}
pub(crate) type DummySmlReader = SmlReader<util::SliceReader<'static>, ArrayBuf<0>>;
impl DummySmlReader {
pub fn with_static_buffer<const N: usize>() -> SmlReaderBuilder<ArrayBuf<N>> {
SmlReaderBuilder { buf: PhantomData }
}
#[cfg(feature = "alloc")]
pub fn with_vec_buffer() -> SmlReaderBuilder<alloc::vec::Vec<u8>> {
SmlReaderBuilder { buf: PhantomData }
}
#[cfg(feature = "std")]
pub fn from_reader<R>(reader: R) -> SmlReader<util::IoReader<R>, DefaultBuffer>
where
R: std::io::Read,
{
SmlReader {
decoder: DecoderReader::new(util::IoReader::new(reader)),
}
}
#[cfg(feature = "embedded_hal")]
pub fn from_eh_reader<R, E>(reader: R) -> SmlReader<util::EhReader<R, E>, DefaultBuffer>
where
R: embedded_hal::serial::Read<u8, Error = E>,
{
SmlReader {
decoder: DecoderReader::new(util::EhReader::new(reader)),
}
}
pub fn from_slice(reader: &[u8]) -> SmlReader<util::SliceReader<'_>, DefaultBuffer> {
SmlReader {
decoder: DecoderReader::new(util::SliceReader::new(reader)),
}
}
pub fn from_iterator<B, I>(
iter: I,
) -> SmlReader<util::IterReader<I::IntoIter, B>, DefaultBuffer>
where
I: IntoIterator<Item = B>,
B: Borrow<u8>,
{
SmlReader {
decoder: DecoderReader::new(util::IterReader::new(iter.into_iter())),
}
}
}
impl<R, ReadErr, Buf> SmlReader<R, Buf>
where
R: ByteSource<ReadError = ReadErr>,
ReadErr: core::fmt::Debug,
Buf: Buffer,
{
pub fn read<'i, T>(&'i mut self) -> Result<T, T::Error>
where
T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
{
T::parse_from(self.decoder.read())
}
pub fn next<'i, T>(&'i mut self) -> Option<Result<T, T::Error>>
where
T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
{
Some(T::parse_from(self.decoder.next()?))
}
#[cfg(feature = "nb")]
pub fn read_nb<'i, T>(&'i mut self) -> nb::Result<T, T::Error>
where
T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
{
let res = match self.decoder.read_nb() {
Ok(x) => Ok(x),
Err(nb::Error::WouldBlock) => return Err(nb::Error::WouldBlock),
Err(nb::Error::Other(e)) => Err(e),
};
T::parse_from(res).map_err(nb::Error::Other)
}
#[cfg(feature = "nb")]
pub fn next_nb<'i, T>(&'i mut self) -> nb::Result<Option<T>, T::Error>
where
T: SmlParse<'i, Result<&'i [u8], ReadDecodedError<ReadErr>>>,
{
let res = match self.decoder.next_nb() {
Ok(None) => return Ok(None),
Ok(Some(x)) => Ok(x),
Err(nb::Error::WouldBlock) => return Err(nb::Error::WouldBlock),
Err(nb::Error::Other(e)) => Err(e),
};
T::parse_from(res).map(Some).map_err(nb::Error::Other)
}
}
type DefaultBuffer = ArrayBuf<{ 8 * 1024 }>;
pub struct SmlReaderBuilder<Buf: Buffer> {
buf: PhantomData<Buf>,
}
impl<Buf: Buffer> Clone for SmlReaderBuilder<Buf> {
fn clone(&self) -> Self {
Self { buf: PhantomData }
}
}
impl<Buf: Buffer> SmlReaderBuilder<Buf> {
#[cfg(feature = "std")]
pub fn from_reader<R: std::io::Read>(self, reader: R) -> SmlReader<util::IoReader<R>, Buf> {
SmlReader {
decoder: DecoderReader::new(util::IoReader::new(reader)),
}
}
#[cfg(feature = "embedded_hal")]
pub fn from_eh_reader<R: embedded_hal::serial::Read<u8, Error = E>, E>(
self,
reader: R,
) -> SmlReader<util::EhReader<R, E>, Buf> {
SmlReader {
decoder: DecoderReader::new(util::EhReader::new(reader)),
}
}
pub fn from_slice(self, reader: &[u8]) -> SmlReader<util::SliceReader<'_>, Buf> {
SmlReader {
decoder: DecoderReader::new(util::SliceReader::new(reader)),
}
}
pub fn from_iterator<B, I>(self, iter: I) -> SmlReader<util::IterReader<I::IntoIter, B>, Buf>
where
I: IntoIterator<Item = B>,
B: Borrow<u8>,
{
SmlReader {
decoder: DecoderReader::new(util::IterReader::new(iter.into_iter())),
}
}
}
pub trait SmlParse<'i, T>: Sized + util::private::Sealed {
type Error;
fn parse_from(value: T) -> Result<Self, Self::Error>;
}
pub type DecodedBytes<'i> = &'i [u8];
type ReadDecodedRes<'i, ReadErr> = Result<&'i [u8], ReadDecodedError<ReadErr>>;
impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for DecodedBytes<'i>
where
ReadErr: core::fmt::Debug,
{
type Error = ReadDecodedError<ReadErr>;
fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
value
}
}
impl<'i> SmlParse<'i, &'i [u8]> for DecodedBytes<'i> {
type Error = core::convert::Infallible;
fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
Ok(value)
}
}
impl<'i> util::private::Sealed for DecodedBytes<'i> {}
#[cfg(feature = "alloc")]
impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for File<'i>
where
ReadErr: core::fmt::Debug,
{
type Error = ReadParsedError<ReadErr>;
fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
Ok(parse(value?)?)
}
}
#[cfg(feature = "alloc")]
impl<'i> SmlParse<'i, &'i [u8]> for File<'i> {
type Error = ParseError;
fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
parse(value)
}
}
#[cfg(feature = "alloc")]
impl<'i> util::private::Sealed for File<'i> {}
impl<'i, ReadErr> SmlParse<'i, ReadDecodedRes<'i, ReadErr>> for Parser<'i>
where
ReadErr: core::fmt::Debug,
{
type Error = ReadDecodedError<ReadErr>;
fn parse_from(value: ReadDecodedRes<'i, ReadErr>) -> Result<Self, Self::Error> {
Ok(Parser::new(value?))
}
}
impl<'i> SmlParse<'i, &'i [u8]> for Parser<'i> {
type Error = core::convert::Infallible;
fn parse_from(value: &'i [u8]) -> Result<Self, Self::Error> {
Ok(Parser::new(value))
}
}
impl<'i> util::private::Sealed for Parser<'i> {}
#[test]
fn test_smlreader_construction() {
let arr = [1, 2, 3, 4, 5];
SmlReader::from_slice(&arr);
SmlReader::from_iterator(&arr);
SmlReader::from_iterator(arr.iter().map(|x| x + 1));
#[cfg(feature = "std")]
SmlReader::from_reader(std::io::Cursor::new(&arr));
SmlReader::with_static_buffer::<1234>().from_slice(&arr);
SmlReader::with_static_buffer::<1234>().from_iterator(arr.iter().map(|x| x + 1));
#[cfg(feature = "std")]
SmlReader::with_static_buffer::<1234>().from_reader(std::io::Cursor::new(&arr));
#[cfg(feature = "alloc")]
SmlReader::with_vec_buffer().from_slice(&arr);
#[cfg(feature = "alloc")]
SmlReader::with_vec_buffer().from_iterator(arr.iter().map(|x| x + 1));
#[cfg(feature = "std")]
SmlReader::with_vec_buffer().from_reader(std::io::Cursor::new(&arr));
}
#[test]
#[cfg(feature = "embedded_hal")]
fn test_smlreader_eh_construction() {
struct Pin;
impl embedded_hal::serial::Read<u8> for Pin {
type Error = i16;
fn read(&mut self) -> nb::Result<u8, Self::Error> {
Ok(123)
}
}
SmlReader::from_eh_reader(Pin);
SmlReader::with_static_buffer::<1234>().from_eh_reader(Pin);
#[cfg(feature = "alloc")]
SmlReader::with_vec_buffer().from_eh_reader(Pin);
}
mod read_tests {
#[test]
fn test_smlreader_reading() {
#[cfg(feature = "alloc")]
use super::File;
use super::{DecodedBytes, Parser, SmlReader};
let bytes = [1, 2, 3, 4];
let mut reader = SmlReader::from_slice(&bytes);
let _ = reader.read::<DecodedBytes>();
let _: Result<DecodedBytes, _> = reader.read();
#[cfg(feature = "alloc")]
let _ = reader.read::<File>();
let _ = reader.read::<Parser>();
let _ = reader.next::<DecodedBytes>();
#[cfg(feature = "alloc")]
let _ = reader.next::<File>();
let _ = reader.next::<Parser>();
}
#[test]
#[cfg(feature = "nb")]
fn test_smlreader_reading_nb() {
#[cfg(feature = "alloc")]
use super::File;
use super::{DecodedBytes, Parser, SmlReader};
let bytes = [1, 2, 3, 4];
let mut reader = SmlReader::from_slice(&bytes);
let _ = reader.next_nb::<DecodedBytes>();
#[cfg(feature = "alloc")]
let _ = reader.next_nb::<File>();
let _ = reader.next_nb::<Parser>();
let _ = reader.read_nb::<DecodedBytes>();
#[cfg(feature = "alloc")]
let _ = reader.read_nb::<File>();
let _ = reader.read_nb::<Parser>();
}
}