use crate::types::*;
use std::ops::Bound;
use std::ops::RangeBounds;
#[inline]
pub fn take<'a, Skip, Par, Rep>(range: Rep, mut callback: Par) -> impl Parser<'a, &'a str>
where
Par: Parser<'a, Skip>,
Rep: RangeBounds<usize>,
{
move |ctx: ParserContext<'a>| {
let minimum: usize = match range.start_bound() {
Bound::Excluded(val) => *val,
Bound::Included(val) => *val,
Bound::Unbounded => 0,
};
let maximum: usize = match range.end_bound() {
Bound::Excluded(val) => *val,
Bound::Included(val) => *val + 1,
Bound::Unbounded => 0,
};
let mut temp_ctx = ctx.clone();
let mut results = 0;
loop {
if maximum > 0 && results == maximum {
break;
}
match callback.parse(temp_ctx) {
Ok((ret_ctx, _)) => {
temp_ctx = ret_ctx;
results += 1;
}
Err((ret_ctx, error)) => {
temp_ctx = ret_ctx;
if results < minimum {
return Err(temp_ctx.with_data(SourceError::Ranges(vec![error])));
}
break;
}
}
}
Ok(ctx.expand(temp_ctx).with_str())
}
}
#[inline]
pub fn take_all<'a, Res, Par>(mut parser: Par) -> impl Parser<'a, &'a str>
where
Par: SequenceParser<'a, Res>,
{
move |ctx| {
parser
.take_all(ctx)
.map_error(|error| SourceError::Ranges(vec![error]))
}
}
#[inline]
pub fn take_any<'a, Res, Par>(mut parser: Par) -> impl Parser<'a, &'a str>
where
Par: BranchParser<'a, Res>,
{
move |ctx| parser.take_any(ctx)
}
#[inline]
pub fn take_until<'a, Skip, Res, Pred, Par>(
mut predicate: Pred,
mut callback: Par,
) -> impl Parser<'a, &'a str>
where
Pred: Parser<'a, Skip>,
Par: Parser<'a, Res>,
{
move |ctx: ParserContext<'a>| {
let mut temp_ctx = ctx.clone();
loop {
match predicate.parse(temp_ctx.clone()) {
Ok((_, _)) => {
break;
}
Err((_, _)) => {}
}
match callback.parse(temp_ctx) {
Ok((ret_ctx, _)) => {
temp_ctx = ret_ctx;
}
Err((ret_ctx, error)) => {
return Err(ret_ctx.with_data(SourceError::Ranges(vec![error])));
}
}
}
Ok(ctx.expand(temp_ctx).with_str())
}
}