mod adapter;
mod anchor;
mod assert;
mod builder;
mod consume;
mod empty;
mod fail;
mod into;
mod literal;
#[cfg(feature = "alloc")]
mod rec;
use core::cell::Cell;
use core::cell::RefCell;
pub use self::adapter::Adapter;
pub use self::adapter::DynRefAdapter;
pub use self::adapter::RefAdapter;
pub use self::anchor::AnchorEnd;
pub use self::anchor::AnchorStart;
pub use self::anchor::end;
pub use self::anchor::start;
pub use self::assert::Assert;
pub use self::assert::assert;
pub use self::assert::not;
pub use self::assert::peek;
pub use self::builder::DynamicRegexBuilderHelper;
pub use self::builder::into_regex_builder;
pub use self::consume::Consume;
pub use self::consume::ConsumeAll;
pub use self::consume::consume;
pub use self::consume::consume_all;
pub use self::empty::EmptyRegex;
pub use self::empty::empty;
pub use self::fail::FailRegex;
pub use self::fail::fail;
pub use self::into::RegexIntoHelper;
pub use self::literal::Literal;
pub use self::literal::LiteralTy;
pub use self::literal::literal;
#[cfg(feature = "alloc")]
pub use self::rec::*;
use crate::ctor::Array;
use crate::ctor::PairArray;
use crate::ctor::PairSlice;
use crate::ctor::Slice;
use crate::ctx::Context;
use crate::ctx::Match;
use crate::err::Error;
use crate::neu::EmptyCond;
use crate::neu::Many0;
use crate::neu::Many1;
use crate::neu::Neu;
use crate::neu::Once;
use crate::neu::Opt;
use crate::span::Span;
pub trait Regex<C> {
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error>;
fn parse(&self, ctx: &mut C) -> bool {
self.try_parse(ctx).is_ok()
}
}
impl<C, F> Regex<C> for F
where
F: Fn(&mut C) -> Result<Span, Error>,
{
#[inline]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
(self)(ctx)
}
}
impl<'a, C> Regex<C> for ()
where
C: Context<'a>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
Ok(Span::new(ctx.offset(), 0))
}
}
macro_rules! impl_orig_regex {
($self:ident, $regex:expr, $type:ty, $orig:ty) => {
impl<'a, C> Regex<C> for $type
where
C: Context<'a, Orig<'a> = &'a $orig>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let $self = self;
Regex::try_parse($regex, ctx)
}
}
};
}
macro_rules! impl_forward_regex {
($self:ident, $regex:expr, $type:ty) => {
impl<P, C> Regex<C> for $type
where
P: Regex<C>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let $self = self;
Regex::try_parse($regex, ctx)
}
}
};
}
#[cfg(feature = "alloc")]
mod alloc_regex_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::ctx::Context;
use crate::err::Error;
use crate::regex::Regex;
use crate::regex::literal;
use crate::span::Span;
impl_orig_regex!(self_, &literal(self_.as_str()), String, str);
impl_orig_regex!(self_, &literal(self_.as_str()), &String, str);
impl_orig_regex!(self_, &literal(self_.as_slice()), Vec<u8>, [u8]);
impl_orig_regex!(self_, &literal(self_.as_slice()), &Vec<u8>, [u8]);
impl_forward_regex!(self_, self_.as_ref(), Arc<P>);
impl_forward_regex!(self_, self_.as_ref(), Rc<P>);
macro_rules! impl_dyn_regex {
($type:ty) => {
impl<'b, C> Regex<C> for $type {
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
self.as_ref().try_parse(ctx)
}
}
};
}
macro_rules! impl_dyn_ctor {
($ctor:ty) => {
impl<'a, 'b, C, O, H> Regex<C> for $ctor {
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
self.as_ref().try_parse(ctx)
}
}
};
}
impl_dyn_regex!(Box<dyn Regex<C> + 'b>);
impl_dyn_regex!(Box<dyn Regex<C> + Send + 'b>);
impl_dyn_regex!(Box<dyn Regex<C> + Send + Sync + 'b>);
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_regex!(Arc<dyn Regex<C> + 'b>);
impl_dyn_regex!(Arc<dyn Regex<C> + Send + 'b>);
impl_dyn_regex!(Arc<dyn Regex<C> + 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_regex!(Rc<dyn Regex<C> + 'b>);
impl_dyn_regex!(Rc<dyn Regex<C> + Send + 'b>);
impl_dyn_ctor!(Rc<dyn Ctor<C, O, H> + 'b>);
impl_dyn_ctor!(Rc<dyn Ctor<C, O, H> + Send + 'b>);
}
impl_orig_regex!(self_, &literal(*self_), &str, str);
impl_orig_regex!(self_, &literal(*self_), &[u8], [u8]);
impl<'a, const N: usize, C> Regex<C> for &[u8; N]
where
C: Context<'a, Orig<'a> = &'a [u8]>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let pattern = crate::regex::literal(self.as_slice());
pattern.try_parse(ctx)
}
}
impl<'a, const N: usize, C> Regex<C> for [u8; N]
where
C: Context<'a, Orig<'a> = &'a [u8]>,
{
#[inline(always)]
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
let pattern = crate::regex::literal(self.as_slice());
pattern.try_parse(ctx)
}
}
impl_forward_regex!(self_, self_.as_ref().ok_or(Error::Option)?, Option<P>);
impl_forward_regex!(self_, &*self_.borrow(), RefCell<P>);
#[cfg(feature = "std")]
impl_forward_regex!(
self_,
&*self_.lock().map_err(|_| Error::Mutex)?,
crate::std::Mutex<P>
);
impl<P, C> Regex<C> for Cell<P>
where
P: Regex<C> + Copy,
{
fn try_parse(&self, ctx: &mut C) -> Result<Span, Error> {
self.get().try_parse(ctx)
}
}
pub const fn once<'a, C, U>(unit: U) -> Once<C, U, C::Item, EmptyCond>
where
C: Context<'a>,
U: Neu<C::Item>,
{
Once::new(unit, EmptyCond)
}
pub const fn opt<'a, C, U>(unit: U) -> Opt<C, U, C::Item, EmptyCond>
where
C: Context<'a>,
U: Neu<C::Item>,
{
Opt::new(unit, EmptyCond)
}
pub const fn many0<'a, C, U>(unit: U) -> Many0<C, U, C::Item, EmptyCond>
where
C: Context<'a>,
U: Neu<C::Item>,
{
Many0::new(unit, EmptyCond)
}
pub const fn many1<'a, C, N>(unit: N) -> Many1<C, N, C::Item, EmptyCond>
where
N: Neu<C::Item>,
C: Context<'a>,
{
Many1::new(unit, EmptyCond)
}
pub const fn count<'a, const M: usize, const N: usize, C, U>(
unit: U,
) -> crate::neu::Between<M, N, C, U, EmptyCond>
where
C: Context<'a>,
U: Neu<C::Item>,
{
crate::neu::Between::new(unit, EmptyCond)
}
pub const fn count_if<'a, const M: usize, const N: usize, C, U, F>(
unit: U,
cond: F,
) -> crate::neu::Between<M, N, C, U, F>
where
C: Context<'a>,
U: Neu<C::Item>,
F: crate::neu::NeuCond<'a, C>,
{
crate::neu::Between::new(unit, cond)
}
#[cfg(feature = "alloc")]
pub fn vector<T>(val: impl IntoIterator<Item = T>) -> crate::ctor::Vector<T> {
crate::ctor::Vector::new(val.into_iter().collect(), false)
}
#[cfg(feature = "alloc")]
pub fn vector_ltm<T>(val: impl IntoIterator<Item = T>) -> crate::ctor::Vector<T> {
crate::ctor::Vector::new(val.into_iter().collect(), true)
}
#[cfg(feature = "alloc")]
pub fn pair_vector<T, V: Clone>(
val: impl IntoIterator<Item = (T, V)>,
) -> crate::ctor::PairVector<T, V> {
crate::ctor::PairVector::new(val.into_iter().collect(), false)
}
#[cfg(feature = "alloc")]
pub fn pair_vector_ltm<T, V: Clone>(
val: impl IntoIterator<Item = (T, V)>,
) -> crate::ctor::PairVector<T, V> {
crate::ctor::PairVector::new(val.into_iter().collect(), true)
}
pub const fn array<const N: usize, T>(val: [T; N]) -> Array<N, T> {
Array::new(val, false)
}
pub const fn array_ltm<const N: usize, T>(val: [T; N]) -> Array<N, T> {
Array::new(val, true)
}
pub const fn slice<T>(val: &[T]) -> Slice<'_, T> {
Slice::new(val, false)
}
pub const fn slice_ltm<T>(val: &[T]) -> Slice<'_, T> {
Slice::new(val, true)
}
pub const fn pair_array<const N: usize, K, V>(val: [(K, V); N]) -> PairArray<N, K, V> {
PairArray::new(val, false)
}
pub const fn pair_array_ltm<const N: usize, K, V>(val: [(K, V); N]) -> PairArray<N, K, V> {
PairArray::new(val, true)
}
pub const fn pair_slice<K, V>(val: &[(K, V)]) -> PairSlice<'_, K, V> {
PairSlice::new(val, false)
}
pub const fn pair_slice_ltm<K, V>(val: &[(K, V)]) -> PairSlice<'_, K, V> {
PairSlice::new(val, true)
}
pub(crate) fn handler<'a, C, P, T, A>(
err: Error,
t2p: A,
) -> impl Fn(&[T], &mut C) -> Result<Span, Error>
where
P: Regex<C>,
C: Match<'a>,
A: Fn(&T) -> &P,
{
move |slice: &[T], ctx: &mut C| {
let beg = ctx.offset();
let mut ret = Err(err);
for item in slice.iter() {
let regex = t2p(item);
if let Ok(span) = ctx.try_mat(regex).inspect_err(|_| {
ctx.set_offset(beg);
}) {
ret = Ok(span);
break;
}
}
ret
}
}
pub(crate) fn handler_ltm<'a, C, P, T, A>(
err: Error,
t2p: A,
) -> impl Fn(&[T], &mut C) -> Result<Span, Error>
where
P: Regex<C>,
C: Match<'a>,
A: Fn(&T) -> &P,
{
move |slice: &[T], ctx: &mut C| {
let beg = ctx.offset();
let mut longest = None;
for item in slice.iter() {
ctx.set_offset(beg);
if let Ok(span) = ctx.try_mat(t2p(item))
&& longest.map(|v: Span| v.len() < span.len()).unwrap_or(true)
{
longest = Some(span);
}
}
longest.ok_or(err)
}
}
pub trait RegexRefAsCtor<C>
where
Self: Regex<C>,
{
fn as_ctor(&self) -> RefAdapter<'_, C, Self>;
}
impl<T: ?Sized, C> RegexRefAsCtor<C> for T
where
Self: Regex<C>,
{
fn as_ctor(&self) -> RefAdapter<'_, C, Self> {
RefAdapter::new(self)
}
}
pub trait RegexRefAsDynRegex<C>
where
Self: Regex<C>,
{
fn as_dyn_regex(&self) -> DynRefAdapter<'_, C>;
}
impl<C, T> RegexRefAsDynRegex<C> for T
where
Self: Regex<C>,
{
fn as_dyn_regex(&self) -> DynRefAdapter<'_, C> {
DynRefAdapter::new(self)
}
}
macro_rules! impl_not_for_regex {
(@$ty:ident [ ] [ ]) => {
impl core::ops::Not for $ty {
type Output = $crate::regex::Assert<Self>;
fn not(self) -> Self::Output { $crate::regex::not(self) }
}
};
(@$ty:ident [ ] [ $($p:ident),+ ]) => {
impl<$($p),+> core::ops::Not for $ty<$($p),+> {
type Output = $crate::regex::Assert<Self>;
fn not(self) -> Self::Output { $crate::regex::not(self) }
}
};
(@$ty:ident [ $($l:lifetime),+ ] [ $($p:ident),* ]) => {
impl<$($l),+ , $($p),*> core::ops::Not for $ty<$($l),+ , $($p),*> {
type Output = $crate::regex::Assert<Self>;
fn not(self) -> Self::Output { $crate::regex::not(self) }
}
};
($ty:ident) => {
impl_not_for_regex! { @$ty [ ] [ ] }
};
($ty:ident < $($l:lifetime),* $(,)? $($p:ident),* >) => {
impl_not_for_regex! { @$ty [$($l),*] [$($p),*] }
};
}
pub(crate) use impl_not_for_regex;