pub mod decoders;
#[cfg(feature = "std")]
use crate::ReadError;
use crate::{DecodeError, UnconsumedError};
pub trait Decodable {
type Decoder: Decoder<Output = Self>;
fn decoder() -> Self::Decoder;
}
pub trait Decoder: Sized {
type Output;
type Error;
#[must_use = "must check result to avoid panics on subsequent calls"]
#[track_caller]
fn push_bytes(&mut self, bytes: &mut &[u8]) -> Result<bool, Self::Error>;
#[must_use = "must check result to avoid panics on subsequent calls"]
#[track_caller]
fn end(self) -> Result<Self::Output, Self::Error>;
fn read_limit(&self) -> usize;
}
pub fn decode_from_slice<T: Decodable>(
bytes: &[u8],
) -> Result<T, DecodeError<<T::Decoder as Decoder>::Error>> {
let mut remaining = bytes;
let data = decode_from_slice_unbounded::<T>(&mut remaining).map_err(DecodeError::Parse)?;
if remaining.is_empty() {
Ok(data)
} else {
Err(DecodeError::Unconsumed(UnconsumedError()))
}
}
pub fn decode_from_slice_unbounded<T>(
bytes: &mut &[u8],
) -> Result<T, <T::Decoder as Decoder>::Error>
where
T: Decodable,
{
let mut decoder = T::decoder();
while !bytes.is_empty() {
if !decoder.push_bytes(bytes)? {
break;
}
}
decoder.end()
}
#[cfg(feature = "std")]
pub fn decode_from_read<T, R>(mut reader: R) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
where
T: Decodable,
R: std::io::BufRead,
{
let mut decoder = T::decoder();
loop {
let mut buffer = match reader.fill_buf() {
Ok(buffer) => buffer,
Err(error) if error.kind() == std::io::ErrorKind::Interrupted => continue,
Err(error) => return Err(ReadError::Io(error)),
};
if buffer.is_empty() {
return decoder.end().map_err(ReadError::Decode);
}
let original_len = buffer.len();
let need_more = decoder.push_bytes(&mut buffer).map_err(ReadError::Decode)?;
let consumed = original_len - buffer.len();
reader.consume(consumed);
if !need_more {
return decoder.end().map_err(ReadError::Decode);
}
}
}
#[cfg(feature = "std")]
pub fn decode_from_read_unbuffered<T, R>(
reader: R,
) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
where
T: Decodable,
R: std::io::Read,
{
decode_from_read_unbuffered_with::<T, R, 4096>(reader)
}
#[cfg(feature = "std")]
pub fn decode_from_read_unbuffered_with<T, R, const BUFFER_SIZE: usize>(
mut reader: R,
) -> Result<T, ReadError<<T::Decoder as Decoder>::Error>>
where
T: Decodable,
R: std::io::Read,
{
let mut decoder = T::decoder();
let mut buffer = [0u8; BUFFER_SIZE];
while decoder.read_limit() > 0 {
let clamped_buffer = &mut buffer[..decoder.read_limit().min(BUFFER_SIZE)];
match reader.read(clamped_buffer) {
Ok(0) => {
return decoder.end().map_err(ReadError::Decode);
}
Ok(bytes_read) => {
if !decoder
.push_bytes(&mut &clamped_buffer[..bytes_read])
.map_err(ReadError::Decode)?
{
return decoder.end().map_err(ReadError::Decode);
}
}
Err(ref e) if e.kind() == std::io::ErrorKind::Interrupted => {
}
Err(e) => return Err(ReadError::Io(e)),
}
}
decoder.end().map_err(ReadError::Decode)
}