use core::convert::Infallible;
use crate::display::InputDisplay;
use crate::error::{
with_context, CoreContext, CoreExpected, CoreOperation, ExpectedLength, ExpectedValid,
ExpectedValue, External, Length, Value, WithChildContext, WithContext,
};
use crate::fmt::{Debug, Display, DisplayBase};
use crate::input::pattern::Pattern;
use crate::reader::Reader;
use super::{Bound, Bytes, MaybeString, Prefix, Span, String};
#[must_use = "input must be consumed"]
pub trait Input<'i>: Private<'i> {
fn bound(&self) -> Bound;
fn into_bound(self) -> Self;
fn into_bytes(self) -> Bytes<'i>;
fn into_string<E>(self) -> Result<String<'i>, E>
where
E: From<ExpectedValid<'i>>,
E: From<ExpectedLength<'i>>;
fn into_maybe_string(self) -> MaybeString<'i>;
fn display(&self) -> InputDisplay<'i>;
#[must_use]
#[inline(always)]
fn byte_len(&self) -> usize {
self.as_dangerous_bytes().len()
}
#[must_use]
#[inline(always)]
fn is_empty(&self) -> bool {
self.byte_len() == 0
}
#[must_use]
#[inline(always)]
fn is_bound(&self) -> bool {
self.bound() == Bound::StartEnd
}
#[inline(always)]
fn span(&self) -> Span {
Span::from(self.as_dangerous_bytes())
}
#[must_use]
#[inline(always)]
fn nth(&self, index: usize) -> Option<Self::Token> {
self.clone().tokens().nth(index)
}
#[must_use]
#[inline(always)]
fn first(&self) -> Option<Self::Token> {
self.clone().tokens().next()
}
#[must_use]
#[inline(always)]
fn last(&self) -> Option<Self::Token> {
self.clone().tokens().next_back()
}
#[inline]
fn read_all<F, T, E>(self, f: F) -> Result<T, E>
where
F: FnOnce(&mut Reader<'i, Self, E>) -> Result<T, E>,
E: WithContext<'i>,
E: From<ExpectedLength<'i>>,
{
let mut r = Reader::new(self.clone());
match r.context(
CoreContext::from_operation(CoreOperation::ReadAll, self.span()),
f,
) {
Ok(ok) if r.at_end() => Ok(ok),
Ok(_) => Err(E::from(ExpectedLength {
len: Length::Exactly(0),
context: CoreContext {
span: r.take_remaining().span(),
operation: CoreOperation::ReadAll,
expected: CoreExpected::NoTrailingInput,
},
input: self.into_maybe_string(),
})),
Err(err) => Err(err),
}
}
#[inline]
fn read_partial<F, T, E>(self, f: F) -> Result<(T, Self), E>
where
F: FnOnce(&mut Reader<'i, Self, E>) -> Result<T, E>,
E: WithContext<'i>,
{
let mut r = Reader::new(self.clone());
match r.context(
CoreContext::from_operation(CoreOperation::ReadPartial, self.span()),
f,
) {
Ok(ok) => Ok((ok, r.take_remaining())),
Err(err) => Err(err),
}
}
#[inline]
fn read_infallible<F, T>(self, f: F) -> (T, Self)
where
F: FnOnce(&mut Reader<'i, Self, Infallible>) -> T,
{
let mut r = Reader::new(self);
let ok = f(&mut r);
(ok, r.take_remaining())
}
#[inline]
fn into_external<F, T, E, Ex>(self, expected: &'static str, f: F) -> Result<T, E>
where
F: FnOnce(Self) -> Result<T, Ex>,
E: WithContext<'i>,
E: From<ExpectedValid<'i>>,
Ex: External<'i>,
{
f(self.clone()).map_err(|external| {
self.map_external_error(external, expected, CoreOperation::IntoExternal)
})
}
fn into_non_empty<E>(self) -> Result<Self, E>
where
E: From<ExpectedLength<'i>>,
{
if self.is_empty() {
Err(E::from(ExpectedLength {
len: Length::AtLeast(1),
context: CoreContext {
span: self.span(),
operation: CoreOperation::IntoNonEmpty,
expected: CoreExpected::NonEmpty,
},
input: self.into_maybe_string(),
}))
} else {
Ok(self)
}
}
}
pub trait Private<'i>: Sized + Clone + DisplayBase + Debug + Display {
type Token: BytesLength + Copy + 'static;
type TokenIter: DoubleEndedIterator<Item = Self::Token>;
type TokenIndicesIter: DoubleEndedIterator<Item = (usize, Self::Token)>;
fn end(self) -> Self;
fn tokens(self) -> Self::TokenIter;
fn tokens_indices(self) -> Self::TokenIndicesIter;
fn into_unbound_end(self) -> Self;
fn verify_token_boundary(&self, index: usize) -> Result<(), CoreExpected>;
fn split_at_opt(self, mid: usize) -> Option<(Self, Self)>;
unsafe fn split_at_byte_unchecked(self, mid: usize) -> (Self, Self);
}
pub(crate) trait PrivateExt<'i>: Input<'i> {
#[inline(always)]
fn as_dangerous_bytes(&self) -> &'i [u8] {
self.clone().into_bytes().as_dangerous()
}
#[inline(always)]
fn split_at<E>(self, mid: usize, operation: CoreOperation) -> Result<(Self, Self), E>
where
E: From<ExpectedLength<'i>>,
{
self.clone().split_at_opt(mid).ok_or_else(|| {
E::from(ExpectedLength {
len: Length::AtLeast(mid),
context: CoreContext {
span: self.span(),
operation,
expected: CoreExpected::EnoughInputFor("split"),
},
input: self.into_maybe_string(),
})
})
}
#[inline(always)]
fn split_at_byte<E>(self, mid: usize, operation: CoreOperation) -> Result<(Self, Self), E>
where
E: From<ExpectedValid<'i>>,
E: From<ExpectedLength<'i>>,
{
if self.byte_len() < mid {
Err(E::from(ExpectedLength {
len: Length::AtLeast(mid),
context: CoreContext {
span: self.span(),
operation,
expected: CoreExpected::EnoughInputFor("split"),
},
input: self.into_maybe_string(),
}))
} else {
match self.verify_token_boundary(mid) {
Ok(()) => {
Ok(unsafe { self.split_at_byte_unchecked(mid) })
}
Err(expected) => Err(E::from(ExpectedValid {
retry_requirement: None,
context: CoreContext {
span: self.as_dangerous_bytes()[mid..mid].into(),
operation,
expected,
},
input: self.into_maybe_string(),
})),
}
}
}
#[inline(always)]
fn split_token_opt(self) -> Option<(Self::Token, Self)> {
self.clone().tokens().next().map(|token| {
let (_, tail) = unsafe { self.split_at_byte_unchecked(token.byte_len()) };
(token, tail)
})
}
#[inline(always)]
fn split_token<E>(self, operation: CoreOperation) -> Result<(Self::Token, Self), E>
where
E: From<ExpectedLength<'i>>,
{
self.clone().split_token_opt().ok_or_else(|| {
E::from(ExpectedLength {
len: Length::AtLeast(1),
context: CoreContext {
span: self.span(),
operation,
expected: CoreExpected::EnoughInputFor("token"),
},
input: self.into_maybe_string(),
})
})
}
#[inline(always)]
fn split_prefix_opt<P>(self, prefix: P) -> (Option<Self>, Self)
where
P: Prefix<Self>,
{
if prefix.is_prefix_of(&self) {
let (head, tail) = unsafe { self.split_at_byte_unchecked(prefix.byte_len()) };
(Some(head), tail)
} else {
(None, self)
}
}
#[inline(always)]
fn split_prefix<P, E>(self, prefix: P, operation: CoreOperation) -> Result<(Self, Self), E>
where
E: From<ExpectedValue<'i>>,
P: Prefix<Self> + Into<Value<'i>>,
{
match self.clone().split_prefix_opt(&prefix) {
(Some(head), tail) => Ok((head, tail)),
(None, unmatched) => {
let bytes = unmatched.as_dangerous_bytes();
let prefix_len = prefix.byte_len();
let actual = if bytes.len() > prefix_len {
&bytes[..prefix_len]
} else {
&bytes
};
Err(E::from(ExpectedValue {
expected: prefix.into(),
context: CoreContext {
span: actual.into(),
operation,
expected: CoreExpected::ExactValue,
},
input: self.into_maybe_string(),
}))
}
}
}
#[inline(always)]
fn split_until_opt<P>(self, pattern: P) -> Option<(Self, Self)>
where
P: Pattern<Self>,
{
pattern.find_match(&self).map(|(index, _)| {
unsafe { self.split_at_byte_unchecked(index) }
})
}
#[inline(always)]
fn split_until_consume_opt<P>(self, pattern: P) -> Option<(Self, Self)>
where
P: Pattern<Self>,
{
pattern.find_match(&self).map(|(index, len)| {
let (head, tail) = unsafe { self.split_at_byte_unchecked(index) };
let (_, tail) = unsafe { tail.split_at_byte_unchecked(len) };
(head, tail)
})
}
#[inline(always)]
fn split_until<P, E>(self, pattern: P, operation: CoreOperation) -> Result<(Self, Self), E>
where
E: From<ExpectedValue<'i>>,
P: Pattern<Self> + Into<Value<'i>> + Copy,
{
self.clone().split_until_opt(pattern).ok_or_else(|| {
E::from(ExpectedValue {
expected: pattern.into(),
context: CoreContext {
span: self.span(),
operation,
expected: CoreExpected::PatternMatch,
},
input: self.into_maybe_string(),
})
})
}
#[inline(always)]
fn split_until_consume<P, E>(
self,
pattern: P,
operation: CoreOperation,
) -> Result<(Self, Self), E>
where
E: From<ExpectedValue<'i>>,
P: Pattern<Self> + Into<Value<'i>> + Copy,
{
self.clone()
.split_until_consume_opt(pattern)
.ok_or_else(|| {
E::from(ExpectedValue {
expected: pattern.into(),
context: CoreContext {
span: self.span(),
operation,
expected: CoreExpected::PatternMatch,
},
input: self.into_maybe_string(),
})
})
}
#[inline(always)]
fn split_while_opt<P>(self, pattern: P) -> Option<(Self, Self)>
where
P: Pattern<Self>,
{
pattern.find_reject(&self).map(|i| {
unsafe { self.split_at_byte_unchecked(i) }
})
}
#[inline(always)]
fn try_split_while<F, E>(self, mut f: F, operation: CoreOperation) -> Result<(Self, Self), E>
where
E: WithContext<'i>,
F: FnMut(Self::Token) -> Result<bool, E>,
{
for (i, token) in self.clone().tokens_indices() {
let should_continue = with_context(
CoreContext::from_operation(operation, self.span()),
self.clone(),
|| f(token),
)?;
if !should_continue {
let (head, tail) = unsafe { self.split_at_byte_unchecked(i) };
return Ok((head, tail));
}
}
Ok((self.clone(), self.end()))
}
#[inline(always)]
fn split_consumed<F, T, E>(self, f: F) -> (T, Self, Self)
where
F: FnOnce(&mut Reader<'i, Self, E>) -> T,
{
let mut reader = Reader::new(self.clone());
let value = f(&mut reader);
let tail = reader.take_remaining();
let mid = self.byte_len() - tail.byte_len();
let (head, _) = unsafe { self.split_at_byte_unchecked(mid) };
if tail.bound() == Bound::None {
(value, head.into_unbound_end(), tail)
} else {
(value, head, tail)
}
}
#[inline(always)]
fn try_split_consumed<F, T, E>(
self,
f: F,
operation: CoreOperation,
) -> Result<(T, Self, Self), E>
where
E: WithContext<'i>,
F: FnOnce(&mut Reader<'i, Self, E>) -> Result<T, E>,
{
let mut reader = Reader::new(self.clone());
let value = reader.context(CoreContext::from_operation(operation, self.span()), f)?;
let tail = reader.take_remaining();
let mid = self.byte_len() - tail.byte_len();
let (head, _) = unsafe { self.split_at_byte_unchecked(mid) };
if tail.bound() == Bound::None {
Ok((value, head.into_unbound_end(), tail))
} else {
Ok((value, head, tail))
}
}
#[inline(always)]
fn split_expect<F, T, E>(
self,
f: F,
expected: &'static str,
operation: CoreOperation,
) -> Result<(T, Self), E>
where
E: From<ExpectedValid<'i>>,
F: FnOnce(&mut Reader<'i, Self, E>) -> Option<T>,
{
let mut reader = Reader::new(self.clone());
if let Some(ok) = f(&mut reader) {
Ok((ok, reader.take_remaining()))
} else {
let tail = reader.take_remaining();
let span = self.as_dangerous_bytes()[..self.byte_len() - tail.byte_len()].into();
Err(E::from(ExpectedValid {
retry_requirement: None,
context: CoreContext {
span,
expected: CoreExpected::Valid(expected),
operation,
},
input: self.into_maybe_string(),
}))
}
}
#[inline(always)]
fn try_split_expect<F, T, E>(
self,
f: F,
expected: &'static str,
operation: CoreOperation,
) -> Result<(T, Self), E>
where
E: WithContext<'i>,
E: From<ExpectedValid<'i>>,
F: FnOnce(&mut Reader<'i, Self, E>) -> Result<Option<T>, E>,
{
let mut context = CoreContext {
span: self.span(),
expected: CoreExpected::Valid(expected),
operation,
};
let mut reader = Reader::new(self.clone());
match reader.context(context, f) {
Ok(Some(ok)) => Ok((ok, reader.take_remaining())),
Ok(None) => {
let tail = reader.take_remaining();
context.span =
self.as_dangerous_bytes()[..self.byte_len() - tail.byte_len()].into();
Err(E::from(ExpectedValid {
retry_requirement: None,
context,
input: self.into_maybe_string(),
}))
}
Err(err) => Err(err),
}
}
#[inline(always)]
fn try_split_expect_external<F, T, E, Ex>(
self,
f: F,
expected: &'static str,
operation: CoreOperation,
) -> Result<(T, Self), E>
where
F: FnOnce(Self) -> Result<(usize, T), Ex>,
E: WithContext<'i>,
E: From<ExpectedValid<'i>>,
E: From<ExpectedLength<'i>>,
Ex: External<'i>,
{
match f(self.clone()) {
Ok((read, ok)) => self
.split_at_byte(read, operation)
.map(|(_, remaining)| (ok, remaining)),
Err(external) => Err(self.map_external_error(external, expected, operation)),
}
}
fn map_external_error<E, Ex>(
self,
external: Ex,
expected: &'static str,
operation: CoreOperation,
) -> E
where
E: WithContext<'i>,
E: From<ExpectedValid<'i>>,
Ex: External<'i>,
{
let error = E::from(ExpectedValid {
retry_requirement: external.retry_requirement(),
context: CoreContext {
span: external.span().unwrap_or_else(|| self.span()),
expected: CoreExpected::Valid(expected),
operation,
},
input: self.into_maybe_string(),
});
external
.push_backtrace(WithChildContext::new(error))
.unwrap()
}
}
impl<'i, T> PrivateExt<'i> for T where T: Input<'i> {}
pub unsafe trait BytesLength: Copy {
fn byte_len(self) -> usize;
}
unsafe impl<T> BytesLength for &T
where
T: BytesLength,
{
#[inline(always)]
fn byte_len(self) -> usize {
(*self).byte_len()
}
}
unsafe impl BytesLength for u8 {
#[inline(always)]
fn byte_len(self) -> usize {
1
}
}
unsafe impl BytesLength for char {
#[inline(always)]
fn byte_len(self) -> usize {
self.len_utf8()
}
}
unsafe impl BytesLength for &[u8] {
#[inline(always)]
fn byte_len(self) -> usize {
self.len()
}
}
unsafe impl BytesLength for &str {
#[inline(always)]
fn byte_len(self) -> usize {
self.as_bytes().len()
}
}
unsafe impl<const N: usize> BytesLength for &[u8; N] {
#[inline(always)]
fn byte_len(self) -> usize {
self.len()
}
}
pub trait IntoInput<'i>: Copy {
type Input: Input<'i>;
fn into_input(self) -> Self::Input;
}
impl<'i, T> IntoInput<'i> for &T
where
T: IntoInput<'i>,
{
type Input = T::Input;
#[inline(always)]
fn into_input(self) -> Self::Input {
(*self).into_input()
}
}
impl<'i> IntoInput<'i> for &'i [u8] {
type Input = Bytes<'i>;
#[inline(always)]
fn into_input(self) -> Self::Input {
Bytes::new(self, Bound::Start)
}
}
impl<'i> IntoInput<'i> for &'i str {
type Input = String<'i>;
#[inline(always)]
fn into_input(self) -> Self::Input {
String::new(self, Bound::Start)
}
}
impl<'i, const N: usize> IntoInput<'i> for &'i [u8; N] {
type Input = Bytes<'i>;
#[inline(always)]
fn into_input(self) -> Self::Input {
Bytes::new(self, Bound::Start)
}
}