use crate::{ error::ParseError, stream::buf_reader::{Buffer, Bufferless, CombineBuffer}, }; use std::{ fmt, io::{self, Read}, }; #[cfg(feature = "pin-project-lite")] use std::pin::Pin; #[derive(Debug)] pub enum Error { Parse(E), Io { position: P, error: io::Error }, } impl<'a, P> From, P>> for crate::easy::Errors where P: Ord + Clone, { fn from(e: Error, P>) -> Self { match e { Error::Parse(e) => e, Error::Io { position, error } => { crate::easy::Errors::from_error(position, crate::easy::Error::Other(error.into())) } } } } impl std::error::Error for Error where E: std::error::Error, P: fmt::Display + fmt::Debug, { } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::Parse(e) => e.fmt(f), Error::Io { position: _, error } => error.fmt(f), } } } #[derive(Default)] /// Used together with the `decode!` macro pub struct Decoder { position: P, state: S, buffer: C, end_of_input: bool, } impl Decoder where P: Default, S: Default, { /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to /// be used when decoding but there may be data left in the internal buffer after decoding /// (accessible with [`Decoder::buffer`]) pub fn new() -> Self { Decoder::default() } /// Constructs a new [`Decoder`] with an internal buffer. Allows any `AsyncRead/Read` instance to /// be used when decoding but there may be data left in the internal buffer after decoding /// (accessible with [`Decoder::buffer`]) pub fn new_buffer() -> Self { Decoder::new() } } impl Decoder where P: Default, S: Default, { /// Constructs a new `Decoder` without an internal buffer. Requires the read instance to be /// wrapped with combine's [`BufReader`] instance to /// /// [`BufReader`]: super::buf_reader::BufReader pub fn new_bufferless() -> Self { Decoder::default() } } impl Decoder { pub fn buffer(&self) -> &[u8] { &self.buffer.0 } } impl Decoder { #[doc(hidden)] pub fn advance(&mut self, read: &mut R, removed: usize) where C: CombineBuffer, { // Remove the data we have parsed and adjust `removed` to be the amount of data we // committed from `self.reader` self.buffer.advance(read, removed) } #[doc(hidden)] #[cfg(feature = "pin-project-lite")] pub fn advance_pin(&mut self, read: Pin<&mut R>, removed: usize) where C: CombineBuffer, { // Remove the data we have parsed and adjust `removed` to be the amount of data we // committed from `self.reader` self.buffer.advance_pin(read, removed); } pub fn position(&self) -> &P { &self.position } #[doc(hidden)] pub fn __inner(&mut self) -> (&mut S, &mut P, &C, bool) { ( &mut self.state, &mut self.position, &self.buffer, self.end_of_input, ) } } impl Decoder where C: , { #[doc(hidden)] pub fn __before_parse(&mut self, mut reader: R) -> io::Result<()> where R: Read, C: crate::stream::buf_reader::CombineSyncRead, { if self.buffer.extend_buf_sync(&mut reader)? == 0 { self.end_of_input = true; } Ok(()) } } #[cfg(feature = "tokio-02")] impl Decoder { #[doc(hidden)] pub async fn __before_parse_tokio_02(&mut self, mut reader: Pin<&mut R>) -> io::Result<()> where R: tokio_02_dep::io::AsyncRead, C: crate::stream::buf_reader::CombineRead, { let copied = crate::future_ext::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut())) .await?; if copied == 0 { self.end_of_input = true; } Ok(()) } } #[cfg(feature = "tokio-03")] impl Decoder { #[doc(hidden)] pub async fn __before_parse_tokio_03(&mut self, mut reader: Pin<&mut R>) -> io::Result<()> where R: tokio_03_dep::io::AsyncRead, C: crate::stream::buf_reader::CombineRead, { let copied = crate::future_ext::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut())) .await?; if copied == 0 { self.end_of_input = true; } Ok(()) } } #[cfg(feature = "tokio")] impl Decoder { #[doc(hidden)] pub async fn __before_parse_tokio(&mut self, mut reader: Pin<&mut R>) -> io::Result<()> where R: tokio_dep::io::AsyncRead, C: crate::stream::buf_reader::CombineRead, { let copied = crate::future_ext::poll_fn(|cx| self.buffer.poll_extend_buf(cx, reader.as_mut())) .await?; if copied == 0 { self.end_of_input = true; } Ok(()) } } #[cfg(feature = "futures-03")] impl Decoder { #[doc(hidden)] pub async fn __before_parse_async(&mut self, reader: Pin<&mut R>) -> io::Result<()> where R: futures_io_03::AsyncRead, C: crate::stream::buf_reader::CombineAsyncRead, { let copied = self.buffer.extend_buf(reader).await?; if copied == 0 { self.end_of_input = true; } Ok(()) } }