#![forbid(unsafe_code)]
use core::fmt::Debug;
use core::marker::PhantomData;
use core::ops::Range;
pub fn escape_ascii(input: impl AsRef<[u8]>) -> String {
let mut result = String::new();
for byte in input.as_ref() {
for ascii_byte in core::ascii::escape_default(*byte) {
result.push_str(core::str::from_utf8(&[ascii_byte]).unwrap());
}
}
result
}
pub trait RangeTrait {
fn is_discarding_range(&self) -> bool;
fn extend(self, r: &Range<usize>) -> Option<Self>
where
Self: Sized;
fn end(&self) -> usize;
fn range(&self) -> Range<usize>;
}
#[derive(Clone, PartialEq)]
pub struct DiscardingRange;
impl RangeTrait for DiscardingRange {
fn is_discarding_range(&self) -> bool {
true
}
fn extend(self, _r: &Range<usize>) -> Option<Self> {
Some(self)
}
fn end(&self) -> usize {
0
}
fn range(&self) -> Range<usize> {
0..0
}
}
impl Debug for DiscardingRange {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "DiscardingRange")
}
}
#[derive(Clone)]
pub struct MatchRange<R> {
start: usize,
end: usize,
outer: R,
}
impl<R> MatchRange<R> {
#[must_use]
pub fn into_outer(self) -> R {
self.outer
}
}
impl MatchRange<()> {
#[must_use]
pub fn zero() -> Self {
Self {
start: 0,
end: 0,
outer: (),
}
}
}
impl<R: RangeTrait + Clone + Debug> MatchRange<R> {
#[must_use]
pub fn new(outer: R, n: usize) -> Self {
if outer.is_discarding_range() {
Self {
start: n,
end: n,
outer,
}
} else {
let end = outer.range().end;
if end != n {
panic!("{} is not immediately after {:?}", n, outer);
}
Self {
start: end,
end,
outer,
}
}
}
}
impl<R: Clone + Debug> RangeTrait for MatchRange<R> {
fn is_discarding_range(&self) -> bool {
false
}
fn extend(mut self, r: &Range<usize>) -> Option<Self> {
println!("extend {:?} + {:?}", &self, &r);
if self.end != r.start {
println!("{:?} is not immediately after {:?}", &r, &self);
return None;
}
if r.end < r.start {
panic!("bad range: {:?}", &r);
}
self.end = r.end;
Some(self)
}
fn end(&self) -> usize {
self.end
}
fn range(&self) -> Range<usize> {
self.start..self.end
}
}
impl<R: Clone + Debug> Debug for MatchRange<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"MatchRange({}..{},{:?})",
self.start, self.end, self.outer
)
}
}
pub trait Matcher {
type RangeType;
fn reset(&mut self);
fn process_byte(
&mut self,
prev_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType>;
fn matches_empty(&mut self) -> bool;
}
pub fn match_all<T: Matcher<RangeType = MatchRange<()>> + Debug>(
matcher: &mut T,
data: &[u8],
) -> bool {
if data.is_empty() {
return matcher.matches_empty();
}
matcher.reset();
println!("{:?}", &matcher);
println!("process_byte {}", escape_ascii([data[0]]));
let mut final_state = matcher.process_byte(Some(MatchRange::zero()), data[0], 0);
println!("{:?}", &matcher);
println!("final_state = {:?}", final_state);
for (n, b) in data.iter().copied().enumerate().skip(1) {
println!("process_byte {}", escape_ascii([b]));
final_state = matcher.process_byte(None, b, n);
println!("{:?}", &matcher);
println!("final_state = {:?}", final_state);
}
final_state.map_or(false, |matching_range| {
matching_range.range() == (0..data.len())
})
}
#[derive(Clone, PartialOrd, PartialEq)]
pub struct Byte<R: RangeTrait + Debug> {
value: u8,
phantom: PhantomData<R>,
}
impl<R: RangeTrait + Debug> Byte<R> {
#[must_use]
pub fn new(b: u8) -> Self {
Self {
value: b,
phantom: PhantomData,
}
}
}
impl<R: RangeTrait + Debug> Matcher for Byte<R> {
type RangeType = R;
fn reset(&mut self) {}
fn process_byte(
&mut self,
prev_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
let prev_matching_range = prev_state?;
if b == self.value {
println!(
"{:?} extend {:?} + {}..{}",
self,
prev_matching_range,
n,
n + 1
);
#[allow(clippy::range_plus_one)]
prev_matching_range.extend(&(n..n + 1))
} else {
None
}
}
fn matches_empty(&mut self) -> bool {
false
}
}
impl<R: RangeTrait + Debug> Debug for Byte<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "Byte({})", escape_ascii([self.value]))
}
}
pub struct AnyByte<R: RangeTrait + Debug> {
phantom: PhantomData<R>,
}
impl<R: RangeTrait + Debug> AnyByte<R> {
#[must_use]
#[allow(clippy::new_without_default)]
pub fn new() -> Self {
Self {
phantom: PhantomData,
}
}
}
impl<R: RangeTrait + Debug> Matcher for AnyByte<R> {
type RangeType = R;
fn reset(&mut self) {}
fn process_byte(
&mut self,
prev_state: Option<Self::RangeType>,
_b: u8,
n: usize,
) -> Option<Self::RangeType> {
let prev_matching_range = prev_state?;
println!(
"{:?} extend {:?} + {}..{}",
self,
prev_matching_range,
n,
n + 1
);
#[allow(clippy::range_plus_one)]
prev_matching_range.extend(&(n..n + 1))
}
fn matches_empty(&mut self) -> bool {
false
}
}
impl<R: RangeTrait + Debug> Debug for AnyByte<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "AnyByte")
}
}
pub struct Class<R: RangeTrait + Debug> {
incl: bool,
bytes: &'static [u8],
phantom: PhantomData<R>,
}
impl<R: RangeTrait + Debug> Class<R> {
#[must_use]
pub fn new(incl: bool, bytes: &'static [u8]) -> Self {
Self {
incl,
bytes,
phantom: PhantomData,
}
}
}
impl<R: RangeTrait + Debug> Matcher for Class<R> {
type RangeType = R;
fn reset(&mut self) {}
fn process_byte(
&mut self,
prev_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
let prev_matching_range = prev_state?;
let contains = self.bytes.contains(&b);
if (self.incl && contains) || (!self.incl && !contains) {
println!(
"{:?} extend {:?} + {}..{}",
self,
prev_matching_range,
n,
n + 1
);
#[allow(clippy::range_plus_one)]
prev_matching_range.extend(&(n..n + 1))
} else {
None
}
}
fn matches_empty(&mut self) -> bool {
false
}
}
impl<R: RangeTrait + Debug> Debug for Class<R> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(
f,
"Class{}({})",
if self.incl { "" } else { "^" },
escape_ascii(self.bytes)
)
}
}
pub struct Seq<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
a: A,
b: B,
prev_a_state: Option<R>,
}
impl<R, A, B> Seq<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
#[must_use]
pub fn new(a: A, b: B) -> Self {
Self {
a,
b,
prev_a_state: None,
}
}
fn reset_impl(&mut self) {
self.a.reset();
self.b.reset();
self.prev_a_state = None;
}
fn process_byte_impl(&mut self, prev_state: Option<R>, b: u8, n: usize) -> Option<R> {
let prev_a_state_clone = self.prev_a_state.clone();
let result = self.b.process_byte(self.prev_a_state.take(), b, n);
println!(
"Seq.process_byte({},{}) {:?} --{:?}-> {:?}",
escape_ascii([b]),
n,
prev_a_state_clone,
self.b,
result
);
let prev_state_clone = prev_state.clone();
self.prev_a_state = self.a.process_byte(prev_state, b, n);
println!(
"Seq.process_byte({},{}) {:?} --{:?}-> {:?}",
escape_ascii([b]),
n,
prev_state_clone,
self.a,
self.prev_a_state
);
result
}
fn matches_empty_impl(&mut self) -> bool {
self.a.matches_empty() && self.b.matches_empty()
}
}
impl<R, A, B> Matcher for Seq<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, A, B> Matcher for &mut Seq<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, A, B> Debug for Seq<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "Seq({:?},{:?},{:?})", self.a, self.prev_a_state, self.b)
}
}
pub struct Either<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
a: A,
b: B,
phantom: PhantomData<R>,
}
impl<R, A, B> Either<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
#[must_use]
pub fn new(a: A, b: B) -> Self {
Self {
a,
b,
phantom: PhantomData,
}
}
fn reset_impl(&mut self) {
self.a.reset();
self.b.reset();
}
fn process_byte_impl(&mut self, prev_state: Option<R>, b: u8, n: usize) -> Option<R> {
let prev_state_clone = prev_state.clone();
if let Some(match_range) = self.a.process_byte(prev_state, b, n) {
return Some(match_range);
}
self.b.process_byte(prev_state_clone, b, n)
}
fn matches_empty_impl(&mut self) -> bool {
self.a.matches_empty() || self.b.matches_empty()
}
}
impl<R, A, B> Matcher for Either<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, A, B> Matcher for &mut Either<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, A, B> Debug for Either<R, A, B>
where
R: RangeTrait + Clone + Debug,
A: Matcher<RangeType = R> + Debug,
B: Matcher<RangeType = R> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "Either({:?},{:?})", self.a, self.b)
}
}
pub struct Optional<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = R> + Debug,
{
inner: T,
phantom: PhantomData<R>,
}
impl<R, T> Optional<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = R> + Debug,
{
#[must_use]
pub fn new(inner: T) -> Self {
Self {
inner,
phantom: PhantomData,
}
}
fn reset_impl(&mut self) {
self.inner.reset();
}
fn process_byte_impl(&mut self, prev_state: Option<R>, b: u8, n: usize) -> Option<R> {
let prev_state_clone = prev_state.clone();
self.inner
.process_byte(prev_state, b, n)
.or(prev_state_clone)
}
}
impl<R, T> Matcher for Optional<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
true
}
}
impl<R, T> Matcher for &mut Optional<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = R> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
true
}
}
impl<R, T> Debug for Optional<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = R> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "Optional({:?})", self.inner)
}
}
#[derive(Clone)]
pub struct CapturingGroup<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = MatchRange<R>> + Debug,
{
range: Option<Range<usize>>,
inner: T,
phantom: PhantomData<R>,
}
impl<R, T> CapturingGroup<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = MatchRange<R>> + Debug,
{
#[must_use]
pub fn new(inner: T) -> Self {
Self {
range: None,
inner,
phantom: PhantomData,
}
}
pub fn range(&self) -> Option<Range<usize>> {
self.range.clone()
}
fn reset_impl(&mut self) {
self.inner.reset();
self.range = None;
}
fn process_byte_impl(
&mut self,
prev_outer_state: Option<<CapturingGroup<R, T> as Matcher>::RangeType>,
b: u8,
n: usize,
) -> Option<<CapturingGroup<R, T> as Matcher>::RangeType> {
let prev_state = prev_outer_state.map(|p| MatchRange::new(p, n));
let state = self.inner.process_byte(prev_state, b, n);
let match_range = state?;
let range = match_range.range();
let outer_range = match_range.into_outer().extend(&range);
self.range = Some(range);
outer_range
}
fn matches_empty_impl(&mut self) -> bool {
self.inner.matches_empty()
}
}
impl<R, T> Matcher for CapturingGroup<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = MatchRange<R>> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, T> Matcher for &mut CapturingGroup<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = MatchRange<R>> + Debug,
{
type RangeType = R;
fn reset(&mut self) {
self.reset_impl()
}
fn process_byte(
&mut self,
prev_outer_state: Option<Self::RangeType>,
b: u8,
n: usize,
) -> Option<Self::RangeType> {
self.process_byte_impl(prev_outer_state, b, n)
}
fn matches_empty(&mut self) -> bool {
self.matches_empty_impl()
}
}
impl<R, T> Debug for CapturingGroup<R, T>
where
R: RangeTrait + Clone + Debug,
T: Matcher<RangeType = MatchRange<R>> + Debug,
{
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> Result<(), core::fmt::Error> {
write!(f, "CapturingGroup({:?})", self.inner)
}
}
#[test]
fn byte() {
let mut re = Byte::new(b'a');
assert_eq!("Byte(a)", format!("{:?}", re));
println!("size {} bytes: {:?}", core::mem::size_of_val(&re), &re);
assert!(!match_all(&mut re, b""));
assert!(match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"ab"));
assert!(!match_all(&mut re, b"aa"));
}
#[test]
fn seq() {
let mut re = Seq::new(Byte::new(b'a'), Byte::new(b'b'));
println!("size {} bytes: {:?}", core::mem::size_of_val(&re), &re);
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"a"));
assert!(match_all(&mut re, b"ab"));
assert!(!match_all(&mut re, b"aab"));
assert!(!match_all(&mut re, b"aba"));
assert!(!match_all(&mut re, b"abab"));
}
#[test]
fn seq_reset() {
let mut re = Seq::new(Byte::new(b'a'), Seq::new(Byte::new(b'b'), Byte::new(b'c')));
println!("size {} bytes: {:?}", core::mem::size_of_val(&re), &re);
assert!(!match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"b"));
assert!(!match_all(&mut re, b"c"));
assert!(!match_all(&mut re, b"X"));
}
#[test]
fn seq_nested() {
let mut re = Seq::new(Byte::new(b'a'), Seq::new(Byte::new(b'b'), Byte::new(b'c')));
println!("size {} bytes: {:?}", core::mem::size_of_val(&re), &re);
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"b"));
assert!(!match_all(&mut re, b"c"));
assert!(!match_all(&mut re, b"ab"));
assert!(!match_all(&mut re, b"bc"));
assert!(!match_all(&mut re, b"cd"));
assert!(match_all(&mut re, b"abc"));
assert!(!match_all(&mut re, b"Xabc"));
assert!(!match_all(&mut re, b"abcX"));
assert!(!match_all(&mut re, b"aabc"));
assert!(!match_all(&mut re, b"abcc"));
assert!(!match_all(&mut re, b"abca"));
assert!(!match_all(&mut re, b"abcabc"));
}
#[test]
fn seq_deeply_nested() {
let mut re = Seq::new(
Byte::new(b'a'),
Seq::new(Seq::new(Byte::new(b'b'), Byte::new(b'c')), Byte::new(b'd')),
);
println!("size {} bytes: {:?}", core::mem::size_of_val(&re), &re);
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"b"));
assert!(!match_all(&mut re, b"c"));
assert!(!match_all(&mut re, b"d"));
assert!(!match_all(&mut re, b"ab"));
assert!(!match_all(&mut re, b"bc"));
assert!(!match_all(&mut re, b"cd"));
assert!(!match_all(&mut re, b"abc"));
assert!(!match_all(&mut re, b"bcd"));
assert!(match_all(&mut re, b"abcd"));
assert!(!match_all(&mut re, b"Xabcd"));
assert!(!match_all(&mut re, b"abcdX"));
assert!(!match_all(&mut re, b"aabcd"));
assert!(!match_all(&mut re, b"abcda"));
assert!(!match_all(&mut re, b"abcdabcd"));
}
#[test]
fn seq_debug() {
let mut re = Seq::new(Byte::new(b'a'), Byte::new(b'b'));
assert_eq!("Seq(Byte(a),None,Byte(b))", format!("{:?}", re));
assert!(!match_all(&mut re, b"a"));
assert_eq!(
"Seq(Byte(a),Some(MatchRange(0..1,())),Byte(b))",
format!("{:?}", re)
);
}
#[test]
fn optional() {
let mut re = Optional::new(Byte::new(b'a'));
assert_eq!("Optional(Byte(a))", format!("{:?}", re));
assert!(match_all(&mut re, b""));
assert!(match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"aa"));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"Xa"));
}
#[test]
fn optional_at_start() {
let mut re = Seq::new(Optional::new(Byte::new(b'a')), Byte::new(b'a'));
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"aaa"));
assert!(!match_all(&mut re, b"Xaa"));
assert!(!match_all(&mut re, b"aaX"));
}
#[test]
fn optional_at_end() {
let mut re = Seq::new(Byte::new(b'a'), Optional::new(Byte::new(b'a')));
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"aaa"));
assert!(!match_all(&mut re, b"Xaa"));
assert!(!match_all(&mut re, b"aaX"));
}
#[test]
fn optional_in_middle() {
let mut re = Seq::new(
Byte::new(b'a'),
Seq::new(Optional::new(Byte::new(b'a')), Byte::new(b'a')),
);
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"Xaa"));
assert!(!match_all(&mut re, b"aaX"));
assert!(!match_all(&mut re, b"aXa"));
assert!(!match_all(&mut re, b"aaaa"));
assert!(!match_all(&mut re, b"aaaaa"));
assert!(!match_all(&mut re, b"aaaaaa"));
assert!(!match_all(&mut re, b"Xaaa"));
assert!(!match_all(&mut re, b"aaaX"));
assert!(!match_all(&mut re, b"XaaaX"));
}
#[test]
fn optional_in_group() {
let matcher = |data| {
let mut group = CapturingGroup::new(Optional::new(Byte::new(b'a')));
if match_all(
&mut Seq::new(Byte::new(b'a'), Seq::new(&mut group, Byte::new(b'a'))),
data,
) {
Some(group.range())
} else {
None
}
};
assert_eq!(None, matcher(b""));
assert_eq!(None, matcher(b"X"));
assert_eq!(None, matcher(b"a"));
assert_eq!(None, matcher(b"aX"));
assert_eq!(None, matcher(b"Xa"));
assert_eq!(None, matcher(b"Xaa"));
assert_eq!(None, matcher(b"aXa"));
assert_eq!(None, matcher(b"aaX"));
assert_eq!(None, matcher(b"XaaX"));
assert_eq!(None, matcher(b"Xaaa"));
assert_eq!(None, matcher(b"aXaa"));
assert_eq!(None, matcher(b"aaXa"));
assert_eq!(None, matcher(b"aaaX"));
assert_eq!(None, matcher(b"XaaaX"));
assert_eq!(None, matcher(b"aaaa"));
assert_eq!(None, matcher(b"aaaaa"));
assert_eq!(None, matcher(b"aaaaaa"));
}
#[test]
fn any_byte() {
let mut any_byte = AnyByte::new();
assert!(!match_all(&mut any_byte, b""));
assert!(match_all(&mut any_byte, b"X"));
assert!(!match_all(&mut any_byte, b"XY"));
assert_eq!("AnyByte", format!("{:?}", any_byte));
let mut group = CapturingGroup::new(AnyByte::new());
assert!(match_all(&mut Seq::new(&mut group, AnyByte::new()), b"XY"));
assert_eq!(Some(0..1), group.range());
}
#[test]
fn class_inclusive() {
let mut re = Class::new(true, b"abc");
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"aa"));
assert!(!match_all(&mut re, b"abc"));
assert!(match_all(&mut re, b"a"));
assert!(match_all(&mut re, b"b"));
assert!(match_all(&mut re, b"c"));
assert_eq!("Class(abc)", format!("{:?}", re));
let mut group = CapturingGroup::new(Class::new(true, b"abc"));
assert!(match_all(&mut Seq::new(&mut group, AnyByte::new()), b"aa"));
assert_eq!(Some(0..1), group.range());
}
#[test]
fn class_exclusive() {
let mut re = Class::new(false, b"abc");
assert!(!match_all(&mut re, b""));
assert!(match_all(&mut re, b"X"));
assert!(match_all(&mut re, b"Y"));
assert!(!match_all(&mut re, b"XY"));
assert!(!match_all(&mut re, b"a"));
assert!(!match_all(&mut re, b"b"));
assert!(!match_all(&mut re, b"c"));
assert_eq!("Class^(abc)", format!("{:?}", re));
let mut group = CapturingGroup::new(Class::new(false, b"abc"));
assert!(match_all(&mut Seq::new(&mut group, AnyByte::new()), b"XX"));
assert_eq!(Some(0..1), group.range());
}
#[test]
fn either() {
let mut re = Either::new(Byte::new(b'a'), Byte::new(b'b'));
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"Xa"));
assert!(!match_all(&mut re, b"Xb"));
assert!(!match_all(&mut re, b"aX"));
assert!(!match_all(&mut re, b"bX"));
assert!(!match_all(&mut re, b"XaY"));
assert!(!match_all(&mut re, b"XbY"));
assert!(!match_all(&mut re, b"aa"));
assert!(!match_all(&mut re, b"ab"));
assert!(!match_all(&mut re, b"ba"));
assert!(!match_all(&mut re, b"bb"));
assert!(match_all(&mut re, b"a"));
assert!(match_all(&mut re, b"b"));
}
#[test]
fn either_group() {
let mut group = CapturingGroup::new(Either::new(Byte::new(b'a'), Byte::new(b'b')));
assert!(!match_all(&mut group, b""));
assert!(!match_all(&mut group, b"X"));
assert!(!match_all(&mut group, b"Xa"));
assert!(!match_all(&mut group, b"Xb"));
assert!(!match_all(&mut group, b"aX"));
assert!(!match_all(&mut group, b"bX"));
assert!(!match_all(&mut group, b"XaY"));
assert!(!match_all(&mut group, b"XbY"));
assert!(!match_all(&mut group, b"aa"));
assert!(!match_all(&mut group, b"ab"));
assert!(!match_all(&mut group, b"ba"));
assert!(!match_all(&mut group, b"bb"));
assert!(match_all(&mut group, b"a"));
assert_eq!(Some(0..1), group.range());
assert!(match_all(&mut group, b"b"));
assert_eq!(Some(0..1), group.range());
}
#[test]
fn either_seq() {
let mut re = Seq::new(
Either::new(Byte::new(b'a'), Byte::new(b'b')),
Either::new(Byte::new(b'c'), Byte::new(b'd')),
);
assert!(!match_all(&mut re, b""));
assert!(!match_all(&mut re, b"X"));
assert!(!match_all(&mut re, b"Xac"));
assert!(!match_all(&mut re, b"Xad"));
assert!(!match_all(&mut re, b"Xbc"));
assert!(!match_all(&mut re, b"Xbd"));
assert!(!match_all(&mut re, b"acX"));
assert!(!match_all(&mut re, b"adX"));
assert!(!match_all(&mut re, b"bcX"));
assert!(!match_all(&mut re, b"bdX"));
assert!(!match_all(&mut re, b"XacY"));
assert!(!match_all(&mut re, b"XadY"));
assert!(!match_all(&mut re, b"XbcY"));
assert!(!match_all(&mut re, b"XbdY"));
assert!(!match_all(&mut re, b"aac"));
assert!(!match_all(&mut re, b"add"));
assert!(!match_all(&mut re, b"acac"));
assert!(!match_all(&mut re, b"acbd"));
assert!(match_all(&mut re, b"ac"));
assert!(match_all(&mut re, b"ad"));
assert!(!match_all(&mut re, b"ba"));
assert!(!match_all(&mut re, b"bb"));
assert!(match_all(&mut re, b"bc"));
assert!(match_all(&mut re, b"bd"));
assert!(!match_all(&mut re, b"ca"));
assert!(!match_all(&mut re, b"cb"));
assert!(!match_all(&mut re, b"cc"));
assert!(!match_all(&mut re, b"cd"));
assert!(!match_all(&mut re, b"da"));
assert!(!match_all(&mut re, b"db"));
assert!(!match_all(&mut re, b"dc"));
assert!(!match_all(&mut re, b"dd"));
}
#[test]
fn either_debug() {
let re: Either<DiscardingRange, _, _> = Either::new(Byte::new(b'a'), Byte::new(b'b'));
assert_eq!("Either(Byte(a),Byte(b))", format!("{:?}", re));
}
#[test]
fn group() {
let mut group = CapturingGroup::new(Byte::new(b'a'));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group),
&group
);
assert!(!match_all(&mut group, b""));
assert!(match_all(&mut group, b"a"));
assert_eq!(Some(0..1), group.range());
assert!(!match_all(&mut group, b"Xa"));
assert!(!match_all(&mut group, b"ab"));
assert!(!match_all(&mut group, b"aa"));
}
#[test]
fn group_nested1() {
let mut group_a = CapturingGroup::new(Byte::new(b'a'));
let mut group_outer = CapturingGroup::new(&mut group_a);
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_outer),
&group_outer
);
assert!(!match_all(&mut group_outer, b""));
assert!(!match_all(&mut group_outer, b"Xa"));
assert!(!match_all(&mut group_outer, b"ab"));
assert!(!match_all(&mut group_outer, b"aa"));
assert!(match_all(&mut group_outer, b"a"));
assert_eq!(Some(0..1), group_outer.range());
assert_eq!(Some(0..1), group_a.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested2() {
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_ab = CapturingGroup::new(Seq::new(Byte::new(b'a'), &mut group_b));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_ab),
group_ab
);
assert!(!match_all(&mut group_ab, b"Xab"));
assert!(!match_all(&mut group_ab, b"abX"));
assert!(!match_all(&mut group_ab, b"aab"));
assert!(!match_all(&mut group_ab, b"aba"));
assert!(!match_all(&mut group_ab, b"abb"));
assert!(!match_all(&mut group_ab, b"abab"));
assert!(!match_all(&mut group_ab, b""));
assert!(!match_all(&mut group_ab, b"a"));
assert!(match_all(&mut group_ab, b"ab"));
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(1..2), group_b.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested3() {
let mut group_a = CapturingGroup::new(Byte::new(b'a'));
let mut group_ab = CapturingGroup::new(Seq::new(&mut group_a, Byte::new(b'b')));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_ab),
group_ab
);
assert!(!match_all(&mut group_ab, b"Xab"));
assert!(!match_all(&mut group_ab, b"abX"));
assert!(!match_all(&mut group_ab, b"aab"));
assert!(!match_all(&mut group_ab, b"aba"));
assert!(!match_all(&mut group_ab, b"abb"));
assert!(!match_all(&mut group_ab, b"abab"));
assert!(!match_all(&mut group_ab, b""));
assert!(!match_all(&mut group_ab, b"a"));
assert!(match_all(&mut group_ab, b"ab"));
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(0..1), group_a.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested4() {
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_a = CapturingGroup::new(Byte::new(b'a'));
let mut group_ab = CapturingGroup::new(Seq::new(&mut group_a, &mut group_b));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_ab),
group_ab
);
assert!(!match_all(&mut group_ab, b"Xab"));
assert!(!match_all(&mut group_ab, b"abX"));
assert!(!match_all(&mut group_ab, b"aab"));
assert!(!match_all(&mut group_ab, b"aba"));
assert!(!match_all(&mut group_ab, b"abb"));
assert!(!match_all(&mut group_ab, b"abab"));
assert!(!match_all(&mut group_ab, b""));
assert!(!match_all(&mut group_ab, b"a"));
assert!(match_all(&mut group_ab, b"ab"));
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(0..1), group_a.range());
assert_eq!(Some(1..2), group_b.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested5() {
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_c = CapturingGroup::new(Byte::new(b'c'));
let mut group_ab = CapturingGroup::new(Seq::new(Byte::new(b'a'), &mut group_b));
let mut group_abc = CapturingGroup::new(Seq::new(&mut group_ab, &mut group_c));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_abc),
group_abc
);
assert!(!match_all(&mut group_abc, b"Xabc"));
assert!(!match_all(&mut group_abc, b"abcX"));
assert!(!match_all(&mut group_abc, b"aabc"));
assert!(!match_all(&mut group_abc, b"abca"));
assert!(!match_all(&mut group_abc, b"abcc"));
assert!(!match_all(&mut group_abc, b"abcabc"));
assert!(!match_all(&mut group_abc, b""));
assert!(!match_all(&mut group_abc, b"a"));
assert!(!match_all(&mut group_abc, b"ab"));
assert!(match_all(&mut group_abc, b"abc"));
assert_eq!(Some(0..3), group_abc.range());
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(1..2), group_b.range());
assert_eq!(Some(2..3), group_c.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested6() {
let mut group_a = CapturingGroup::new(Byte::new(b'a'));
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_bc = CapturingGroup::new(Seq::new(&mut group_b, Byte::new(b'c')));
let mut group_abc = CapturingGroup::new(Seq::new(&mut group_a, &mut group_bc));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_abc),
group_abc
);
assert!(!match_all(&mut group_abc, b"Xabc"));
assert!(!match_all(&mut group_abc, b"abcX"));
assert!(!match_all(&mut group_abc, b"aabc"));
assert!(!match_all(&mut group_abc, b"abca"));
assert!(!match_all(&mut group_abc, b"abcc"));
assert!(!match_all(&mut group_abc, b"abcabc"));
assert!(!match_all(&mut group_abc, b""));
assert!(!match_all(&mut group_abc, b"a"));
assert!(!match_all(&mut group_abc, b"ab"));
assert!(match_all(&mut group_abc, b"abc"));
assert_eq!(Some(0..3), group_abc.range());
assert_eq!(Some(1..3), group_bc.range());
assert_eq!(Some(0..1), group_a.range());
assert_eq!(Some(1..2), group_b.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested7() {
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_c = CapturingGroup::new(Byte::new(b'c'));
let mut group_ab = CapturingGroup::new(Seq::new(Byte::new(b'a'), &mut group_b));
let mut group_cd = CapturingGroup::new(Seq::new(&mut group_c, Byte::new(b'd')));
let mut group_abcd = CapturingGroup::new(Seq::new(&mut group_ab, &mut group_cd));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&group_abcd),
group_abcd
);
assert!(!match_all(&mut group_abcd, b"Xabcd"));
assert!(!match_all(&mut group_abcd, b"abcdX"));
assert!(!match_all(&mut group_abcd, b"aabcd"));
assert!(!match_all(&mut group_abcd, b"abcda"));
assert!(!match_all(&mut group_abcd, b"abcdd"));
assert!(!match_all(&mut group_abcd, b"abcdabcd"));
assert!(!match_all(&mut group_abcd, b""));
assert!(!match_all(&mut group_abcd, b"a"));
assert!(!match_all(&mut group_abcd, b"ab"));
assert!(!match_all(&mut group_abcd, b"abc"));
assert!(match_all(&mut group_abcd, b"abcd"));
assert_eq!(Some(0..4), group_abcd.range());
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(2..4), group_cd.range());
assert_eq!(Some(1..2), group_b.range());
assert_eq!(Some(2..3), group_c.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested8() {
let mut group_c = CapturingGroup::new(Byte::new(b'c'));
let mut group_bc = CapturingGroup::new(Seq::new(Byte::new(b'b'), &mut group_c));
let mut seq_abc = Seq::new(Byte::new(b'a'), &mut group_bc);
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&seq_abc),
seq_abc
);
assert!(!match_all(&mut seq_abc, b"Xabc"));
assert!(!match_all(&mut seq_abc, b"abcX"));
assert!(!match_all(&mut seq_abc, b"aabc"));
assert!(!match_all(&mut seq_abc, b"abca"));
assert!(!match_all(&mut seq_abc, b"abcc"));
assert!(!match_all(&mut seq_abc, b"abcabc"));
assert!(!match_all(&mut seq_abc, b""));
assert!(!match_all(&mut seq_abc, b"a"));
assert!(!match_all(&mut seq_abc, b"ab"));
assert!(match_all(&mut seq_abc, b"abc"));
assert_eq!(Some(1..3), group_bc.range());
assert_eq!(Some(2..3), group_c.range());
}
#[test]
#[allow(clippy::similar_names)]
fn group_nested9() {
let mut group_f = CapturingGroup::new(Byte::new(b'f'));
let mut group_e = CapturingGroup::new(Byte::new(b'e'));
let mut group_ef = CapturingGroup::new(Seq::new(&mut group_e, &mut group_f));
let mut group_c = CapturingGroup::new(Byte::new(b'c'));
let mut group_cd = CapturingGroup::new(Seq::new(&mut group_c, Byte::new(b'd')));
let mut group_b = CapturingGroup::new(Byte::new(b'b'));
let mut group_ab = CapturingGroup::new(Seq::new(Byte::new(b'a'), &mut group_b));
let mut seq_abcdef = Seq::new(&mut group_ab, Seq::new(&mut group_cd, &mut group_ef));
println!(
"size {} bytes: {:?}",
core::mem::size_of_val(&seq_abcdef),
seq_abcdef
);
assert!(!match_all(&mut seq_abcdef, b""));
assert!(!match_all(&mut seq_abcdef, b"a"));
assert!(!match_all(&mut seq_abcdef, b"ab"));
assert!(!match_all(&mut seq_abcdef, b"abc"));
assert!(!match_all(&mut seq_abcdef, b"abd"));
assert!(!match_all(&mut seq_abcdef, b"abe"));
assert!(!match_all(&mut seq_abcdef, b"abcdefa"));
assert!(!match_all(&mut seq_abcdef, b"aabcdef"));
assert!(!match_all(&mut seq_abcdef, b"Xabcdef"));
assert!(!match_all(&mut seq_abcdef, b"abcdefX"));
assert!(!match_all(&mut seq_abcdef, b"abcdefabcdef"));
assert!(match_all(&mut seq_abcdef, b"abcdef"));
assert_eq!(Some(0..2), group_ab.range());
assert_eq!(Some(2..4), group_cd.range());
assert_eq!(Some(4..6), group_ef.range());
assert_eq!(Some(1..2), group_b.range());
assert_eq!(Some(2..3), group_c.range());
assert_eq!(Some(4..5), group_e.range());
assert_eq!(Some(5..6), group_f.range());
}
#[test]
fn group_debug() {
let group: CapturingGroup<DiscardingRange, _> = CapturingGroup::new(Byte::new(b'a'));
assert_eq!("CapturingGroup(Byte(a))", format!("{:?}", group));
}