mod adapter;
mod affix;
mod array;
mod branch;
mod collect;
mod dthen;
mod enclose;
mod extract;
mod into;
mod longest;
mod map;
mod opt;
mod or;
mod pat;
#[cfg(feature = "alloc")]
mod repeat;
mod repeat2;
mod sep;
mod slice;
mod then;
#[cfg(feature = "alloc")]
mod vec;
use core::cell::Cell;
use core::cell::RefCell;
pub use self::adapter::Adapter;
pub use self::adapter::DynRefAdapter;
pub use self::affix::Prefix;
pub use self::affix::Suffix;
pub use self::array::Array;
pub use self::array::PairArray;
pub use self::branch::Branch;
pub use self::branch::branch;
pub use self::collect::Collect;
pub use self::dthen::DynamicCtorThenBuilder;
pub use self::dthen::DynamicCtorThenBuilderHelper;
pub use self::enclose::Enclose;
pub use self::extract::Extract;
pub use self::extract::extract;
pub use self::into::CtorIntoHelper;
pub use self::longest::LongestTokenMatch;
pub use self::map::Map;
pub use self::opt::OptionPat;
pub use self::or::Or;
pub use self::pat::Pattern;
pub use self::repeat2::Repeat2;
pub use self::sep::SepCollect;
pub use self::sep::SepOnce;
pub use self::sep::Separate2;
pub use self::slice::PairSlice;
pub use self::slice::Slice;
pub use self::then::IfThen;
pub use self::then::Then;
#[cfg(feature = "alloc")]
pub use self::repeat::Repeat;
#[cfg(feature = "alloc")]
pub use self::sep::Separate;
#[cfg(feature = "alloc")]
pub use self::vec::PairVector;
#[cfg(feature = "alloc")]
pub use self::vec::Vector;
use crate::ctx::Context;
use crate::ctx::Match;
use crate::err::Error;
use crate::map::FuncMapper;
use crate::map::mapper;
use crate::neu::AsciiWhiteSpace;
use crate::neu::EmptyCond;
use crate::neu::Many0;
use crate::neu::Neu;
use crate::neu::WhiteSpace;
use crate::regex::Regex;
use crate::regex::RegexRefAsCtor;
use crate::span::Span;
#[cfg(feature = "alloc")]
use crate::neu::CRange;
pub trait Ctor<C, O, H>: Regex<C> {
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error>;
}
impl<'a, C, O, H, F> Ctor<C, O, H> for F
where
C: Match<'a>,
H: Handler<C, Out = O>,
F: Fn(&mut C) -> Result<Span, Error>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
self.as_ctor().construct(ctx, handler)
}
}
pub trait Handler<C> {
type Out;
type Error: Into<Error>;
fn invoke(&mut self, ctx: &C, span: &Span) -> Result<Self::Out, Self::Error>;
}
impl<Func, Out, C> Handler<C> for Func
where
Func: FnMut(&C, &Span) -> Result<Out, Error>,
{
type Out = Out;
type Error = Error;
fn invoke(&mut self, ctx: &C, span: &Span) -> Result<Self::Out, Self::Error> {
(self)(ctx, span)
}
}
macro_rules! impl_orig_ctor {
($type:ty, $orig:ty) => {
impl<'a, 'b, C, O, H> Ctor<C, O, H> for $type
where
C: Context<'a, Orig<'a> = &'a $orig> + Match<'a>,
H: Handler<C, Out = O>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
Ctor::construct(&self.as_ctor(), ctx, handler)
}
}
};
}
macro_rules! impl_forward_ctor {
($self:ident, $regex:expr, $type:ty) => {
impl<'a, 'b, C, O, I, H> Ctor<C, O, H> for $type
where
I: Ctor<C, O, H>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
let $self = self;
Ctor::construct($regex, ctx, handler)
}
}
};
}
#[cfg(feature = "alloc")]
mod alloc_ctor_impls {
use crate::alloc::Arc;
use crate::alloc::Box;
use crate::alloc::Rc;
use crate::alloc::String;
use crate::alloc::Vec;
use crate::ctor::Ctor;
use crate::ctor::Handler;
use crate::ctx::Context;
use crate::ctx::Match;
use crate::err::Error;
use crate::regex::Regex;
use crate::regex::RegexRefAsCtor;
macro_rules! impl_as_ctor {
($self:ident, $regex:expr, $type:ty) => {
impl<'a, 'b, C, O, H> Ctor<C, O, H> for $type
where
C: Match<'a>,
H: Handler<C, Out = O>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
let $self = self;
Ctor::construct(&$regex.as_ctor(), ctx, handler)
}
}
};
}
impl_as_ctor!(self_, self_.as_ref(), Box<dyn Regex<C> + 'b>);
impl_as_ctor!(self_, self_.as_ref(), Box<dyn Regex<C> + Send + 'b>);
impl_as_ctor!(self_, self_.as_ref(), Box<dyn Regex<C> + Send + Sync + 'b>);
impl_as_ctor!(self_, self_.as_ref(), Rc<dyn Regex<C> + 'b>);
impl_as_ctor!(self_, self_.as_ref(), Rc<dyn Regex<C> + Send + 'b>);
impl_orig_ctor!(String, str);
impl_orig_ctor!(&'_ String, str);
impl_orig_ctor!(Vec<u8>, [u8]);
impl_orig_ctor!(&'_ Vec<u8>, [u8]);
impl_forward_ctor!(self_, self_.as_ref(), Arc<I>);
impl_forward_ctor!(self_, self_.as_ref(), Rc<I>);
macro_rules! impl_dyn_ctor {
( $type:ty) => {
impl<'a, 'b, C, O, H> Ctor<C, O, H> for $type {
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
Ctor::construct(self.as_ref(), ctx, handler)
}
}
};
}
impl_dyn_ctor!(Box<dyn Ctor<C, O, H> + 'b>);
impl_dyn_ctor!(Box<dyn Ctor<C, O, H> + Send + 'b>);
impl_dyn_ctor!(Box<dyn Ctor<C, O, H> + Send + Sync + 'b>);
impl_dyn_ctor!(Arc<dyn Ctor<C, O, H> + 'b>);
impl_dyn_ctor!(Arc<dyn Ctor<C, O, H> + Send + 'b>);
impl_dyn_ctor!(Arc<dyn Ctor<C, O, H> + Send + Sync + 'b>);
impl_dyn_ctor!(Rc<dyn Ctor<C, O, H> + 'b>);
impl_dyn_ctor!(Rc<dyn Ctor<C, O, H> + Send + 'b>);
}
impl_orig_ctor!(&'_ str, str);
impl_orig_ctor!(&'_ [u8], [u8]);
impl<'a, const N: usize, C, O, H> Ctor<C, O, H> for &[u8; N]
where
C: Context<'a, Orig<'a> = &'a [u8]> + Match<'a>,
H: Handler<C, Out = O>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
self.as_ctor().construct(ctx, handler)
}
}
impl<'a, const N: usize, C, O, H> Ctor<C, O, H> for [u8; N]
where
C: Context<'a, Orig<'a> = &'a [u8]> + Match<'a>,
H: Handler<C, Out = O>,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
self.as_ctor().construct(ctx, handler)
}
}
impl_forward_ctor!(self_, self_.as_ref().ok_or(Error::Option)?, Option<I>);
impl_forward_ctor!(self_, &*self_.borrow(), RefCell<I>);
#[cfg(feature = "std")]
impl_forward_ctor!(
self_,
&*self_.lock().map_err(|_| Error::Mutex)?,
crate::std::Mutex<I>
);
impl<C, O, I, H> Ctor<C, O, H> for Cell<I>
where
I: Ctor<C, O, H> + Copy,
{
fn construct(&self, ctx: &mut C, handler: &mut H) -> Result<O, Error> {
Ctor::construct(&self.get(), ctx, handler)
}
}
pub trait CtorOps<'a, C>: Sized
where
C: Context<'a>,
{
fn try_map<F, O>(self, f: F) -> Map<C, Self, F, O>;
fn map<F, O>(self, f: F) -> Map<C, Self, FuncMapper<F>, O> {
self.try_map(mapper(f))
}
fn pat(self) -> Pattern<C, Self>;
fn opt(self) -> OptionPat<C, Self>;
fn enclose<L, R>(self, open: L, close: R) -> Enclose<C, Self, L, R>;
#[cfg(feature = "alloc")]
fn sep<S>(self, sep: S) -> Separate<C, Self, S>;
fn sep2<S, const M: usize, const N: usize>(self, sep: S) -> Separate2<C, Self, S, M, N>;
fn sep_once<S, R>(self, sep: S, right: R) -> SepOnce<C, Self, S, R>;
fn sep_collect<S, O, V>(self, sep: S) -> SepCollect<C, Self, S, O, V>;
fn or<P>(self, pat: P) -> Or<C, Self, P>;
fn longest<P>(self, pat: P) -> LongestTokenMatch<C, Self, P>;
fn then<T>(self, then: T) -> Then<C, Self, T>;
fn if_then<I, T>(self, test: I, then: T) -> IfThen<C, Self, I, T>;
#[cfg(feature = "alloc")]
fn repeat(self, range: impl Into<CRange<usize>>) -> Repeat<C, Self>;
fn repeat2<const M: usize, const N: usize>(self) -> Repeat2<C, Self, M, N>;
fn collect<O, T>(self) -> Collect<C, Self, O, T>;
fn if_else<I, E>(self, test: I, other: E) -> Branch<C, Self, I, E>
where
I: Fn(&C) -> Result<bool, Error>;
fn suffix<T>(self, suffix: T) -> Suffix<C, Self, T>;
fn prefix<T>(self, prefix: T) -> Prefix<C, Self, T>;
#[allow(clippy::type_complexity)]
fn skip_ws(self) -> Suffix<C, Self, Many0<C, WhiteSpace, C::Item>>
where
C: Context<'a>,
WhiteSpace: Neu<C::Item>;
#[allow(clippy::type_complexity)]
fn skip_ascii_ws(self) -> Suffix<C, Self, Many0<C, AsciiWhiteSpace<C::Item>, C::Item>>
where
C: Context<'a>,
AsciiWhiteSpace<C::Item>: Neu<C::Item>;
#[allow(clippy::type_complexity)]
fn skip_ws_leading(self) -> Prefix<C, Self, Many0<C, WhiteSpace, C::Item>>
where
C: Context<'a>,
WhiteSpace: Neu<C::Item>;
#[allow(clippy::type_complexity)]
fn skip_ascii_ws_leading(self) -> Prefix<C, Self, Many0<C, AsciiWhiteSpace<C::Item>, C::Item>>
where
C: Context<'a>,
AsciiWhiteSpace<C::Item>: Neu<C::Item>;
}
impl<'a, C, T: Regex<C>> CtorOps<'a, C> for T
where
C: Context<'a>,
{
fn try_map<F, O>(self, func: F) -> Map<C, Self, F, O> {
Map::new(self, func)
}
fn pat(self) -> Pattern<C, Self> {
Pattern::new(self)
}
fn opt(self) -> OptionPat<C, Self> {
OptionPat::new(self)
}
fn enclose<L, R>(self, open: L, close: R) -> Enclose<C, Self, L, R> {
Enclose::new(self, open, close)
}
#[cfg(feature = "alloc")]
fn sep<S>(self, sep: S) -> Separate<C, Self, S> {
Separate::new(self, sep)
}
fn sep2<S, const M: usize, const N: usize>(self, sep: S) -> Separate2<C, Self, S, M, N> {
Separate2::new(self, sep)
}
fn sep_once<S, R>(self, sep: S, right: R) -> SepOnce<C, Self, S, R> {
SepOnce::new(self, sep, right)
}
fn sep_collect<S, O, V>(self, sep: S) -> SepCollect<C, Self, S, O, V> {
SepCollect::new(self, sep)
}
fn or<P>(self, pat: P) -> Or<C, Self, P> {
Or::new(self, pat)
}
fn longest<P>(self, pat: P) -> LongestTokenMatch<C, Self, P> {
LongestTokenMatch::new(self, pat)
}
fn then<P>(self, then: P) -> Then<C, Self, P> {
Then::new(self, then)
}
fn if_then<I, P>(self, test: I, then: P) -> IfThen<C, Self, I, P> {
IfThen::new(self, test, then)
}
#[cfg(feature = "alloc")]
fn repeat(self, range: impl Into<CRange<usize>>) -> Repeat<C, Self> {
Repeat::new(self, range)
}
fn repeat2<const M: usize, const N: usize>(self) -> Repeat2<C, Self, M, N> {
Repeat2::new(self)
}
fn collect<O, V>(self) -> Collect<C, Self, O, V> {
Collect::new(self)
}
fn if_else<F, E>(self, test: F, other: E) -> Branch<C, Self, F, E>
where
F: Fn(&C) -> Result<bool, Error>,
{
Branch::new(test, self, other)
}
fn suffix<P>(self, pat: P) -> Suffix<C, Self, P> {
Suffix::new(self, pat)
}
fn prefix<P>(self, pat: P) -> Prefix<C, Self, P> {
Prefix::new(self, pat)
}
fn skip_ws(self) -> Suffix<C, Self, Many0<C, WhiteSpace, C::Item>>
where
C: Context<'a>,
WhiteSpace: Neu<C::Item>,
{
Suffix::new(self, Many0::new(WhiteSpace::new(), EmptyCond))
}
fn skip_ascii_ws(self) -> Suffix<C, Self, Many0<C, AsciiWhiteSpace<C::Item>, C::Item>>
where
C: Context<'a>,
AsciiWhiteSpace<C::Item>: Neu<C::Item>,
{
Suffix::new(self, Many0::new(AsciiWhiteSpace::new(), EmptyCond))
}
fn skip_ws_leading(self) -> Prefix<C, Self, Many0<C, WhiteSpace, C::Item>>
where
C: Context<'a>,
WhiteSpace: Neu<C::Item>,
{
Prefix::new(self, Many0::new(WhiteSpace::new(), EmptyCond))
}
fn skip_ascii_ws_leading(self) -> Prefix<C, Self, Many0<C, AsciiWhiteSpace<C::Item>, C::Item>>
where
C: Context<'a>,
AsciiWhiteSpace<C::Item>: Neu<C::Item>,
{
Prefix::new(self, Many0::new(AsciiWhiteSpace::new(), EmptyCond))
}
}
pub trait CtorRefAsDynCtor<C, O, H>
where
Self: Ctor<C, O, H>,
{
fn as_dyn_ctor(&self) -> DynRefAdapter<'_, C, O, H>;
}
impl<C, O, H, T> CtorRefAsDynCtor<C, O, H> for T
where
Self: Ctor<C, O, H>,
{
fn as_dyn_ctor(&self) -> DynRefAdapter<'_, C, O, H> {
DynRefAdapter::new(self)
}
}
pub(crate) fn handler<'a, C, T, P, O, H, A, B, R>(
err: Error,
t2p: A,
r2r: B,
) -> impl Fn(&[T], &mut C, &mut H) -> Result<R, Error>
where
P: Ctor<C, O, H>,
C: Match<'a>,
H: Handler<C>,
A: Fn(&T) -> &P,
B: Fn(O, &T) -> R,
{
move |slice: &[T], c: &mut C, h: &mut H| {
let offset = c.offset();
let mut ret = Err(err);
for item in slice.iter() {
let regex = t2p(item);
if let Ok(val) = regex.construct(c, h).inspect_err(|_| {
c.set_offset(offset);
}) {
ret = Ok(r2r(val, item));
break;
}
}
ret
}
}
pub(crate) fn handler_ltm<'a, C, T, P, O, H, A, B, R>(
err: Error,
t2p: A,
r2r: B,
) -> impl Fn(&[T], &mut C, &mut H) -> Result<R, Error>
where
P: Ctor<C, O, H>,
C: Match<'a>,
H: Handler<C>,
A: Fn(&T) -> &P,
B: Fn(O, &T) -> R,
{
move |slice: &[T], ctx: &mut C, h: &mut H| {
let beg = ctx.offset();
let mut ret = None;
let mut end = beg;
for item in slice.iter() {
ctx.set_offset(beg);
if let Ok(val) = t2p(item).construct(ctx, h)
&& ctx.offset() > end
{
end = ctx.offset();
ret = Some((val, item));
}
}
ret.map(|v| r2r(v.0, v.1)).ok_or(err)
}
}
pub(crate) fn sel<T>(val: &T) -> &T {
val
}
pub(crate) fn sel_kv<K, V>(val: &(K, V)) -> &K {
&val.0
}
pub(crate) fn r2r<O, T>(out: O, _: &T) -> O {
out
}
pub(crate) fn r2r_kv<O, K, V: Clone>(out: O, val: &(K, V)) -> (O, V) {
(out, val.1.clone())
}