use core::fmt;
use core::marker::PhantomData;
use crate::error::{
with_context, Context, ExpectedLength, ExpectedValid, ExpectedValue, FromContext,
OperationContext, ToRetryRequirement, Value,
};
use crate::input::Input;
pub struct Reader<'i, E> {
input: &'i Input,
error: PhantomData<E>,
}
impl<'i, E> Reader<'i, E> {
pub fn context<C, F, O>(&mut self, context: C, f: F) -> Result<O, E>
where
E: FromContext<'i>,
C: Context,
F: FnOnce(&mut Self) -> Result<O, E>,
{
with_context(self.input, context, || f(self))
}
pub fn peek_context<C, F, O>(&self, context: C, f: F) -> Result<O, E>
where
E: FromContext<'i>,
C: Context,
F: FnOnce(&Self) -> Result<O, E>,
{
with_context(self.input, context, || f(self))
}
#[inline]
pub fn at_end(&self) -> bool {
self.input.is_empty()
}
#[inline]
pub fn skip(&mut self, len: usize) -> Result<(), E>
where
E: From<ExpectedLength<'i>>,
{
let (_, tail) = self.input.split_at(len, "skip")?;
self.input = tail;
Ok(())
}
pub fn skip_while<F>(&mut self, pred: F) -> usize
where
F: FnMut(u8) -> bool,
{
let (head, tail) = self.input.split_while(pred);
self.input = tail;
head.len()
}
pub fn try_skip_while<F>(&mut self, pred: F) -> Result<usize, E>
where
E: FromContext<'i>,
F: FnMut(u8) -> Result<bool, E>,
{
let (head, tail) = self.input.try_split_while(pred, "try skip while")?;
self.input = tail;
Ok(head.len())
}
pub fn take(&mut self, len: usize) -> Result<&'i Input, E>
where
E: From<ExpectedLength<'i>>,
{
let (head, tail) = self.input.split_at(len, "take")?;
self.input = tail;
Ok(head)
}
pub fn take_remaining(&mut self) -> &'i Input {
let all = self.input;
self.input = all.end();
all
}
pub fn take_while<F>(&mut self, pred: F) -> &'i Input
where
F: FnMut(u8) -> bool,
{
let (head, tail) = self.input.split_while(pred);
self.input = tail;
head
}
pub fn try_take_while<F>(&mut self, pred: F) -> Result<&'i Input, E>
where
E: FromContext<'i>,
F: FnMut(u8) -> Result<bool, E>,
{
let (head, tail) = self.input.try_split_while(pred, "try take while")?;
self.input = tail;
Ok(head)
}
pub fn take_consumed<F>(&mut self, consumer: F) -> &'i Input
where
E: FromContext<'i>,
F: FnMut(&mut Self),
{
let (head, tail) = self.input.split_consumed(consumer);
self.input = tail;
head
}
pub fn try_take_consumed<F>(&mut self, consumer: F) -> Result<&'i Input, E>
where
E: FromContext<'i>,
F: FnMut(&mut Self) -> Result<(), E>,
{
let (head, tail) = self
.input
.try_split_consumed(consumer, "try take consumed")?;
self.input = tail;
Ok(head)
}
pub fn peek<F, O>(&self, len: usize, f: F) -> Result<O, E>
where
E: From<ExpectedLength<'i>>,
F: FnOnce(&Input) -> O,
{
let (head, _) = self.input.split_at(len, "peek")?;
Ok(f(head))
}
pub fn try_peek<F, O>(&self, len: usize, f: F) -> Result<O, E>
where
E: FromContext<'i>,
E: From<ExpectedLength<'i>>,
F: FnOnce(&'i Input) -> Result<O, E>,
O: 'static,
{
let (head, _) = self.input.split_at(len, "try peek")?;
with_context(self.input, OperationContext("try peek"), || f(head))
}
#[inline]
pub fn peek_u8(&self) -> Result<u8, E>
where
E: From<ExpectedLength<'i>>,
{
self.input.first("peek u8")
}
#[inline]
pub fn peek_eq(&self, bytes: &[u8]) -> bool {
self.input.has_prefix(bytes)
}
pub fn consume(&mut self, bytes: &'i [u8]) -> Result<(), E>
where
E: From<ExpectedLength<'i>>,
E: From<ExpectedValue<'i>>,
{
let prefix = Value::Bytes(bytes);
let tail = self.input.split_prefix::<E>(prefix, "consume")?;
self.input = tail;
Ok(())
}
pub fn consume_u8(&mut self, byte: u8) -> Result<(), E>
where
E: From<ExpectedLength<'i>>,
E: From<ExpectedValue<'i>>,
{
let prefix = Value::Byte(byte);
let tail = self.input.split_prefix::<E>(prefix, "consume u8")?;
self.input = tail;
Ok(())
}
pub fn expect<F, O>(&mut self, expected: &'static str, f: F) -> Result<O, E>
where
F: FnOnce(&mut Self) -> Option<O>,
E: FromContext<'i>,
E: From<ExpectedValid<'i>>,
{
let (ok, tail) = self.input.split_expect(f, expected, "expect")?;
self.input = tail;
Ok(ok)
}
pub fn try_expect<F, O>(&mut self, expected: &'static str, f: F) -> Result<O, E>
where
E: FromContext<'i>,
E: From<ExpectedValid<'i>>,
F: FnOnce(&mut Self) -> Result<Option<O>, E>,
{
let (ok, tail) = self.input.try_split_expect(f, expected, "try expect")?;
self.input = tail;
Ok(ok)
}
pub fn try_expect_erased<F, O, R>(&mut self, expected: &'static str, f: F) -> Result<O, E>
where
E: FromContext<'i>,
E: From<ExpectedValid<'i>>,
F: FnOnce(&mut Self) -> Result<O, R>,
R: ToRetryRequirement,
{
let (ok, tail) = self
.input
.try_split_expect_erased(f, expected, "try expect erased")?;
self.input = tail;
Ok(ok)
}
#[inline]
pub fn read_u8(&mut self) -> Result<u8, E>
where
E: From<ExpectedLength<'i>>,
{
let (byte, tail) = self.input.split_first::<E>("read u8")?;
self.input = tail;
Ok(byte)
}
impl_read_num!(i8, le: read_i8_le, be: read_i8_be);
impl_read_num!(u16, le: read_u16_le, be: read_u16_be);
impl_read_num!(i16, le: read_i16_le, be: read_i16_be);
impl_read_num!(u32, le: read_u32_le, be: read_u32_be);
impl_read_num!(i32, le: read_i32_le, be: read_i32_be);
impl_read_num!(u64, le: read_u64_le, be: read_u64_be);
impl_read_num!(i64, le: read_i64_le, be: read_i64_be);
impl_read_num!(u128, le: read_u128_le, be: read_u128_be);
impl_read_num!(i128, le: read_i128_le, be: read_i128_be);
impl_read_num!(f32, le: read_f32_le, be: read_f32_be);
impl_read_num!(f64, le: read_f64_le, be: read_f64_be);
#[inline]
pub fn error<T>(&mut self) -> Reader<'_, T> {
Reader {
input: self.input,
error: PhantomData,
}
}
pub(crate) fn new(input: &'i Input) -> Self {
Self {
input,
error: PhantomData,
}
}
}
impl<'i, E> fmt::Debug for Reader<'i, E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Reader")
.field("input", &self.input)
.finish()
}
}