pub mod complete;
pub mod streaming;
#[cfg(test)]
mod tests;
use core::marker::PhantomData;
use crate::error::ErrorKind;
use crate::error::ParseError;
use crate::internal::{Err, Needed, Parser};
use crate::lib::std::result::Result::*;
use crate::traits::{Compare, CompareResult};
use crate::AsChar;
use crate::Check;
use crate::ExtendInto;
use crate::FindSubstring;
use crate::FindToken;
use crate::Input;
use crate::IsStreaming;
use crate::Mode;
use crate::OutputM;
use crate::OutputMode;
use crate::ToUsize;
pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
Tag {
tag,
e: PhantomData,
}
}
pub struct Tag<T, E> {
tag: T,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>, T> Parser<I> for Tag<T, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
let tag_len = self.tag.input_len();
let t = self.tag.clone();
match i.compare(t) {
CompareResult::Ok => Ok((i.take_from(tag_len), OM::Output::bind(|| i.take(tag_len)))),
CompareResult::Incomplete => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::new(tag_len - i.input_len())))
} else {
Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::Tag;
Error::from_error_kind(i, e)
})))
}
}
CompareResult::Error => Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::Tag;
Error::from_error_kind(i, e)
}))),
}
}
}
pub fn tag_no_case<T, I, Error: ParseError<I>>(tag: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
TagNoCase {
tag,
e: PhantomData,
}
}
pub struct TagNoCase<T, E> {
tag: T,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>, T> Parser<I> for TagNoCase<T, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
let tag_len = self.tag.input_len();
let t = self.tag.clone();
match i.compare_no_case(t) {
CompareResult::Ok => Ok((i.take_from(tag_len), OM::Output::bind(|| i.take(tag_len)))),
CompareResult::Incomplete => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::new(tag_len - i.input_len())))
} else {
Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::Tag;
Error::from_error_kind(i, e)
})))
}
}
CompareResult::Error => Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::Tag;
Error::from_error_kind(i, e)
}))),
}
}
}
pub struct SplitPosition<F, E> {
predicate: F,
error: PhantomData<E>,
}
impl<I, Error: ParseError<I>, F> Parser<I> for SplitPosition<F, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
type Output = I;
type Error = Error;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
i.split_at_position_mode::<OM, _, _>(|c| (self.predicate)(c))
}
}
pub struct SplitPosition1<F, E> {
e: ErrorKind,
predicate: F,
error: PhantomData<E>,
}
impl<I, Error: ParseError<I>, F> Parser<I> for SplitPosition1<F, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
type Output = I;
type Error = Error;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
i.split_at_position_mode1::<OM, _, _>(|c| (self.predicate)(c), self.e)
}
}
pub fn is_not<T, I, Error: ParseError<I>>(arr: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
SplitPosition1 {
e: ErrorKind::IsNot,
predicate: move |c| arr.find_token(c),
error: PhantomData,
}
}
pub fn is_a<T, I, Error: ParseError<I>>(arr: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
SplitPosition1 {
e: ErrorKind::IsA,
predicate: move |c| !arr.find_token(c),
error: PhantomData,
}
}
pub fn take_while<F, I, Error: ParseError<I>>(cond: F) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
SplitPosition {
predicate: move |c| !cond(c),
error: PhantomData,
}
}
pub fn take_while1<F, I, Error: ParseError<I>>(cond: F) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
SplitPosition1 {
e: ErrorKind::TakeWhile1,
predicate: move |c| !cond(c),
error: PhantomData,
}
}
pub fn take_while_m_n<F, I, Error: ParseError<I>>(
m: usize,
n: usize,
predicate: F,
) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
TakeWhileMN {
m,
n,
predicate,
e: PhantomData,
}
}
pub struct TakeWhileMN<F, E> {
m: usize,
n: usize,
predicate: F,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>, F> Parser<I> for TakeWhileMN<F, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(
&mut self,
input: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
let mut count = 0;
for (i, (index, item)) in input.iter_indices().enumerate() {
if i == self.n {
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
}
if !(self.predicate)(item) {
if i >= self.m {
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
} else {
return Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::TakeWhileMN)
})));
}
}
count += 1;
}
let input_len = input.input_len();
if OM::Incomplete::is_streaming() {
let needed = if self.m > input_len {
self.m - input_len
} else {
1
};
Err(Err::Incomplete(Needed::new(needed)))
} else if count >= self.m {
Ok((
input.take_from(input_len),
OM::Output::bind(|| input.take(input_len)),
))
} else {
Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::TakeWhileMN)
})))
}
}
}
#[allow(clippy::redundant_closure)]
pub fn take_till<F, I, Error: ParseError<I>>(cond: F) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
SplitPosition {
predicate: cond,
error: PhantomData,
}
}
#[allow(clippy::redundant_closure)]
pub fn take_till1<F, I, Error: ParseError<I>>(cond: F) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
SplitPosition1 {
e: ErrorKind::TakeTill1,
predicate: cond,
error: PhantomData,
}
}
pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl Parser<I, Output = I, Error = Error>
where
I: Input,
C: ToUsize,
{
Take {
length: count.to_usize(),
e: PhantomData,
}
}
pub struct Take<E> {
length: usize,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>> Parser<I> for Take<Error>
where
I: Input,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match i.slice_index(self.length) {
Err(needed) => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(needed))
} else {
Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::Eof;
Error::from_error_kind(i, e)
})))
}
}
Ok(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))),
}
}
}
pub fn take_until<T, I, Error: ParseError<I>>(tag: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
TakeUntil {
tag,
e: PhantomData,
}
}
pub struct TakeUntil<T, E> {
tag: T,
e: PhantomData<E>,
}
impl<I, T, Error: ParseError<I>> Parser<I> for TakeUntil<T, Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match i.find_substring(self.tag.clone()) {
None => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::Unknown))
} else {
Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::TakeUntil;
Error::from_error_kind(i, e)
})))
}
}
Some(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))),
}
}
}
pub fn take_until1<T, I, Error: ParseError<I>>(tag: T) -> impl Parser<I, Output = I, Error = Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
TakeUntil1 {
tag,
e: PhantomData,
}
}
pub struct TakeUntil1<T, E> {
tag: T,
e: PhantomData<E>,
}
impl<I, T, Error: ParseError<I>> Parser<I> for TakeUntil1<T, Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(&mut self, i: I) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match i.find_substring(self.tag.clone()) {
None => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::Unknown))
} else {
Err(Err::Error(OM::Error::bind(|| {
let e: ErrorKind = ErrorKind::TakeUntil;
Error::from_error_kind(i, e)
})))
}
}
Some(0) => Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(i, ErrorKind::TakeUntil)
}))),
Some(index) => Ok((i.take_from(index), OM::Output::bind(|| i.take(index)))),
}
}
}
pub fn escaped<I, Error, F, G>(
normal: F,
control_char: char,
escapable: G,
) -> impl Parser<I, Output = I, Error = Error>
where
I: Input + Clone + crate::traits::Offset,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
Escaped {
normal,
escapable,
control_char,
e: PhantomData,
}
}
pub struct Escaped<F, G, E> {
normal: F,
escapable: G,
control_char: char,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>, F, G> Parser<I> for Escaped<F, G, Error>
where
I: Input + Clone + crate::traits::Offset,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
type Output = I;
type Error = Error;
fn process<OM: OutputMode>(
&mut self,
input: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
let mut i = input.clone();
while i.input_len() > 0 {
let current_len = i.input_len();
match self
.normal
.process::<OutputM<Check, Check, OM::Incomplete>>(i.clone())
{
Ok((i2, _)) => {
if i2.input_len() == 0 {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::Unknown));
} else {
let index = input.input_len();
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
}
} else if i2.input_len() == current_len {
let index = input.offset(&i2);
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
} else {
i = i2;
}
}
Err(Err::Error(_)) => {
if i.iter_elements().next().unwrap().as_char() == self.control_char {
let next = self.control_char.len_utf8();
if next >= i.input_len() {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::new(1)));
} else {
return Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::Escaped)
})));
}
} else {
match self
.escapable
.process::<OutputM<Check, OM::Error, OM::Incomplete>>(i.take_from(next))
{
Ok((i2, _)) => {
if i2.input_len() == 0 {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::Unknown));
} else {
let index = input.input_len();
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
}
} else {
i = i2;
}
}
Err(e) => return Err(e),
}
}
} else {
let index = input.offset(&i);
if index == 0 {
return Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::Escaped)
})));
} else {
return Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
));
}
}
}
Err(Err::Failure(e)) => {
return Err(Err::Failure(e));
}
Err(Err::Incomplete(i)) => {
return Err(Err::Incomplete(i));
}
}
}
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::Unknown))
} else {
let index = input.input_len();
Ok((
input.take_from(index),
OM::Output::bind(|| input.take(index)),
))
}
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn escaped_transform<I, Error, F, G, ExtendItem, Output>(
normal: F,
control_char: char,
transform: G,
) -> impl Parser<I, Output = Output, Error = Error>
where
I: Clone + crate::traits::Offset + Input,
I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<F as Parser<I>>::Output: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<G as Parser<I>>::Output: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
EscapedTransform {
normal,
control_char,
transform,
e: PhantomData,
extend: PhantomData,
o: PhantomData,
}
}
pub struct EscapedTransform<F, G, E, ExtendItem, Output> {
normal: F,
transform: G,
control_char: char,
e: PhantomData<E>,
extend: PhantomData<ExtendItem>,
o: PhantomData<Output>,
}
impl<I, Error: ParseError<I>, F, G, ExtendItem, Output> Parser<I>
for EscapedTransform<F, G, Error, ExtendItem, Output>
where
I: Clone + crate::traits::Offset + Input,
I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<F as Parser<I>>::Output: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<G as Parser<I>>::Output: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
type Output = Output;
type Error = Error;
fn process<OM: OutputMode>(
&mut self,
input: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
let mut index = 0;
let mut res = OM::Output::bind(|| input.new_builder());
while index < input.input_len() {
let current_len = input.input_len();
let remainder = input.take_from(index);
match self.normal.process::<OM>(remainder.clone()) {
Ok((i2, o)) => {
res = OM::Output::combine(o, res, |o, mut res| {
o.extend_into(&mut res);
res
});
if i2.input_len() == 0 {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::Unknown));
} else {
let index = input.input_len();
return Ok((input.take_from(index), res));
}
} else if i2.input_len() == current_len {
return Ok((remainder, res));
} else {
index = input.offset(&i2);
}
}
Err(Err::Error(_)) => {
if remainder.iter_elements().next().unwrap().as_char() == self.control_char {
let next = index + self.control_char.len_utf8();
let input_len = input.input_len();
if next >= input_len {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::Unknown));
} else {
return Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(remainder, ErrorKind::EscapedTransform)
})));
}
} else {
match self.transform.process::<OM>(input.take_from(next)) {
Ok((i2, o)) => {
res = OM::Output::combine(o, res, |o, mut res| {
o.extend_into(&mut res);
res
});
if i2.input_len() == 0 {
if OM::Incomplete::is_streaming() {
return Err(Err::Incomplete(Needed::Unknown));
} else {
return Ok((input.take_from(input.input_len()), res));
}
} else {
index = input.offset(&i2);
}
}
Err(Err::Error(e)) => return Err(Err::Error(e)),
Err(Err::Failure(e)) => {
return Err(Err::Failure(e));
}
Err(Err::Incomplete(i)) => {
return Err(Err::Incomplete(i));
}
}
}
} else {
if index == 0 {
return Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(remainder, ErrorKind::EscapedTransform)
})));
}
return Ok((remainder, res));
}
}
Err(Err::Failure(e)) => {
return Err(Err::Failure(e));
}
Err(Err::Incomplete(i)) => {
return Err(Err::Incomplete(i));
}
}
}
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::Unknown))
} else {
Ok((input.take_from(index), res))
}
}
}