pub mod numbering;
#[cfg(feature = "tendril")]
pub mod tendril;
use crate::primitives::{Guard, IntoInner};
pub trait Buffer: PartialEq<Self> {
type Token: Copy + PartialEq;
fn fold<B, F>(self, _: B, _: F) -> B
where
F: FnMut(B, Self::Token) -> B;
fn iterate<F>(&self, _: F)
where
F: FnMut(Self::Token);
fn len(&self) -> usize;
#[cfg(feature = "std")]
fn to_vec(&self) -> Vec<Self::Token>;
#[cfg(feature = "std")]
fn into_vec(self) -> Vec<Self::Token>;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<'a, I: Copy + PartialEq> Buffer for &'a [I] {
type Token = I;
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Token) -> B,
{
self.iter().cloned().fold(init, f)
}
fn iterate<F>(&self, mut f: F)
where
F: FnMut(Self::Token),
{
for c in self[..].iter().cloned() {
f(c)
}
}
fn len(&self) -> usize {
self[..].len()
}
#[cfg(feature = "std")]
fn to_vec(&self) -> Vec<Self::Token> {
self[..].to_vec()
}
#[cfg(feature = "std")]
fn into_vec(self) -> Vec<Self::Token> {
self.to_vec()
}
}
impl<'a> Buffer for &'a str {
type Token = char;
fn fold<B, F>(self, init: B, f: F) -> B
where
F: FnMut(B, Self::Token) -> B,
{
self.chars().fold(init, f)
}
fn iterate<F>(&self, mut f: F)
where
F: FnMut(Self::Token),
{
for c in self.chars() {
f(c)
}
}
fn len(&self) -> usize {
self.chars().count()
}
fn is_empty(&self) -> bool {
self[..].is_empty()
}
#[cfg(feature = "std")]
fn to_vec(&self) -> Vec<Self::Token> {
self[..].chars().collect()
}
#[cfg(feature = "std")]
fn into_vec(self) -> Vec<Self::Token> {
self.chars().collect()
}
}
pub trait Input: Sized {
type Token: Copy + PartialEq;
#[doc(hidden)]
type Marker;
type Buffer: Buffer<Token = Self::Token>;
#[inline]
fn ret<T, E>(self, t: T) -> ParseResult<Self, T, E> {
ParseResult(self, Ok(t))
}
#[inline]
fn err<T, E>(self, e: E) -> ParseResult<Self, T, E> {
ParseResult(self, Err(e))
}
#[inline]
fn from_result<T, E>(self, r: Result<T, E>) -> ParseResult<Self, T, E> {
ParseResult(self, r)
}
#[doc(hidden)]
fn _peek(&mut self, _: Guard) -> Option<Self::Token>;
#[doc(hidden)]
fn _pop(&mut self, _: Guard) -> Option<Self::Token>;
#[doc(hidden)]
fn _consume(&mut self, _: Guard, _: usize) -> Option<Self::Buffer>;
#[doc(hidden)]
fn _consume_while<F>(&mut self, _: Guard, _: F) -> Self::Buffer
where
F: FnMut(Self::Token) -> bool;
#[doc(hidden)]
fn _consume_from(&mut self, _: Guard, _: Self::Marker) -> Self::Buffer;
#[doc(hidden)]
fn _consume_remaining(&mut self, _: Guard) -> Self::Buffer;
#[inline]
#[doc(hidden)]
fn _skip_while<F>(&mut self, g: Guard, f: F)
where
F: FnMut(Self::Token) -> bool,
{
self._consume_while(g, f);
}
#[doc(hidden)]
fn _mark(&self, _: Guard) -> Self::Marker;
#[doc(hidden)]
fn _restore(self, _: Guard, _: Self::Marker) -> Self;
}
impl<'a, I: Copy + PartialEq> Input for &'a [I] {
type Buffer = &'a [I];
type Marker = &'a [I];
type Token = I;
#[inline]
fn _peek(&mut self, _g: Guard) -> Option<Self::Token> {
self.first().cloned()
}
#[inline]
fn _pop(&mut self, _g: Guard) -> Option<Self::Token> {
self.first().cloned().map(|c| {
*self = &self[1..];
c
})
}
#[inline]
fn _consume(&mut self, _g: Guard, n: usize) -> Option<Self::Buffer> {
if n > self.len() {
None
} else {
let b = &self[..n];
*self = &self[n..];
Some(b)
}
}
#[inline]
fn _consume_while<F>(&mut self, g: Guard, mut f: F) -> Self::Buffer
where
F: FnMut(Self::Token) -> bool,
{
if let Some(n) = self.iter().position(|c| !f(*c)) {
let b = &self[..n];
*self = &self[n..];
b
} else {
self._consume_remaining(g)
}
}
#[inline]
fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer {
&m[..m.len() - self.len()]
}
#[inline]
fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer {
let b = &self[..];
*self = &self[b.len()..];
b
}
#[inline]
fn _mark(&self, _g: Guard) -> Self::Marker {
self
}
#[inline]
fn _restore(self, _g: Guard, m: Self::Marker) -> Self {
m
}
}
impl<'a> Input for &'a str {
type Buffer = &'a str;
type Marker = &'a str;
type Token = char;
#[inline]
fn _peek(&mut self, _g: Guard) -> Option<Self::Token> {
self.chars().next()
}
#[inline]
fn _pop(&mut self, _g: Guard) -> Option<Self::Token> {
let mut iter = self.char_indices();
iter.next().map(|(_, c)| {
match iter.next().map(|(p, _)| p) {
Some(n) => *self = &self[n..],
None => *self = &self[self.len()..],
}
c
})
}
#[inline]
fn _consume(&mut self, g: Guard, n: usize) -> Option<Self::Buffer> {
match self.char_indices().enumerate().take(n + 1).last() {
Some((num, (pos, _))) if n == num => {
let b = &self[..pos];
*self = &self[pos..];
Some(b)
}
Some((num, _)) if n == num + 1 => Some(self._consume_remaining(g)),
_ => None,
}
}
#[inline]
fn _consume_while<F>(&mut self, g: Guard, mut f: F) -> Self::Buffer
where
F: FnMut(Self::Token) -> bool,
{
if let Some((pos, _)) = self.char_indices().skip_while(|&(_, c)| f(c)).next() {
let b = &self[..pos];
*self = &self[pos..];
b
} else {
self._consume_remaining(g)
}
}
#[inline]
fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer {
&m[..m.len() - self.len()]
}
#[inline]
fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer {
let b = &self[..];
*self = &self[b.len()..];
b
}
#[inline]
fn _mark(&self, _g: Guard) -> Self::Marker {
self
}
#[inline]
fn _restore(self, _g: Guard, m: Self::Marker) -> Self {
m
}
}
pub trait U8Input: Input<Token = u8> {}
impl<T> U8Input for T where T: Input<Token = u8> {}
#[must_use]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct ParseResult<I: Input, T, E>(I, Result<T, E>);
impl<I: Input, T, E> ParseResult<I, T, E> {
#[inline]
pub fn bind<F, U, V>(self, f: F) -> ParseResult<I, U, V>
where
F: FnOnce(I, T) -> ParseResult<I, U, V>,
V: From<E>,
{
match self.1 {
Ok(t) => f(self.0, t).map_err(From::from),
Err(e) => ParseResult(self.0, Err(From::from(e))),
}
}
#[inline]
pub fn then<F, U, V>(self, f: F) -> ParseResult<I, U, V>
where
F: FnOnce(I) -> ParseResult<I, U, V>,
V: From<E>,
{
self.bind(|i, _| f(i))
}
#[inline]
pub fn map<U, F>(self, f: F) -> ParseResult<I, U, E>
where
F: FnOnce(T) -> U,
{
match self {
ParseResult(i, Ok(t)) => ParseResult(i, Ok(f(t))),
ParseResult(i, Err(e)) => ParseResult(i, Err(e)),
}
}
#[inline]
pub fn map_err<V, F>(self, f: F) -> ParseResult<I, T, V>
where
F: FnOnce(E) -> V,
{
match self {
ParseResult(i, Ok(t)) => ParseResult(i, Ok(t)),
ParseResult(i, Err(e)) => ParseResult(i, Err(f(e))),
}
}
#[inline]
pub fn inspect<F>(self, f: F) -> ParseResult<I, T, E>
where
F: FnOnce(&T),
{
if let Ok(ref t) = self.1 {
f(t)
}
self
}
}
impl<I: Input, T, E> IntoInner for ParseResult<I, T, E> {
type Inner = (I, Result<T, E>);
#[inline(always)]
fn into_inner(self) -> Self::Inner {
(self.0, self.1)
}
}
#[cfg(test)]
pub mod test {
use std::fmt::Debug;
use super::{Buffer, Input, ParseResult};
use crate::primitives::IntoInner;
#[test]
fn ret() {
let r1: ParseResult<_, u32, ()> = b"in1".ret::<_, ()>(23u32);
let r2: ParseResult<_, i32, &str> = b"in2".ret::<_, &str>(23i32);
assert_eq!(r1.into_inner(), (&b"in1"[..], Ok(23u32)));
assert_eq!(r2.into_inner(), (&b"in2"[..], Ok(23i32)));
}
#[test]
fn err() {
let r1: ParseResult<_, (), u32> = b"in1".err::<(), _>(23u32);
let r2: ParseResult<_, &str, i32> = b"in2".err::<&str, _>(23i32);
assert_eq!(r1.into_inner(), (&b"in1"[..], Err(23u32)));
assert_eq!(r2.into_inner(), (&b"in2"[..], Err(23i32)));
}
#[test]
fn from_result() {
let i1: Result<u32, &str> = Ok(23);
let i2: Result<&str, &str> = Err("foobar");
let r1 = b"in1".from_result(i1);
let r2 = b"in2".from_result(i2);
assert_eq!(r1.into_inner(), (&b"in1"[..], Ok(23u32)));
assert_eq!(r2.into_inner(), (&b"in2"[..], Err("foobar")));
}
#[test]
fn monad_left_identity() {
fn f<I: Input>(i: I, n: u32) -> ParseResult<I, u32, ()> {
i.ret(n + 1)
}
let a = 123;
let lhs = b"test".ret(a).bind(f);
let rhs = f(&b"test"[..], a);
assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(124)));
assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(124)));
}
#[test]
fn monad_right_identity() {
let m1 = b"test".ret::<_, ()>(1);
let m2 = b"test".ret::<_, ()>(1);
let lhs = m1.bind::<_, _, ()>(Input::ret);
let rhs = m2;
assert_eq!((lhs.0, rhs.1), (&b"test"[..], Ok(1)));
assert_eq!((rhs.0, lhs.1), (&b"test"[..], Ok(1)));
}
#[test]
fn monad_associativity() {
fn f<I: Input>(i: I, num: u32) -> ParseResult<I, u64, ()> {
i.ret((num + 1) as u64)
}
fn g<I: Input>(i: I, num: u64) -> ParseResult<I, u64, ()> {
i.ret(num * 2)
}
let lhs_m = b"test".ret::<_, ()>(2);
let rhs_m = b"test".ret::<_, ()>(2);
let lhs = lhs_m.bind(f).bind(g);
let rhs = rhs_m.bind(|i, x| f(i, x).bind(g));
assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(6)));
assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(6)));
}
#[test]
fn parse_result_inspect() {
use crate::primitives::IntoInner;
let mut n1 = 0;
let mut n2 = 0;
let i1 = b"test ".ret::<u32, ()>(23);
let i2 = b"test ".ret::<u32, ()>(23);
let r1 = i1.inspect(|d: &u32| {
assert_eq!(d, &23);
n1 += 1;
});
let r2 = i2.inspect(|d: &u32| {
assert_eq!(d, &23);
n2 += 1;
});
assert_eq!(r1.into_inner(), (&b"test "[..], Ok(23)));
assert_eq!(n1, 1);
assert_eq!(r2.into_inner(), (&b"test "[..], Ok(23)));
assert_eq!(n2, 1);
}
#[test]
fn input_propagation() {
let mut n_calls = 0;
let i = b"test1".ret::<_, ()>(23);
assert_eq!(i.0, b"test1");
assert_eq!(i.1, Ok(23));
let r: ParseResult<_, _, ()> = i.bind(|i, t| {
n_calls += 1;
i.ret(t)
});
assert_eq!((r.0, r.1), (&b"test1"[..], Ok(23)));
assert_eq!(n_calls, 1);
}
#[test]
fn error_propagation() {
let mut n_calls = 0;
let i = b"test1".err::<(), _>(23);
assert_eq!(i.0, b"test1");
assert_eq!(i.1, Err(23));
let r = i.bind(|i, t| {
n_calls += 1;
i.ret(t)
});
assert_eq!((r.0, r.1), (&b"test1"[..], Err(23)));
assert_eq!(n_calls, 0);
}
#[test]
fn slice() {
fn f<I: Input>(i: I, n: u32) -> ParseResult<I, u32, ()> {
i.ret(n + 1)
}
let lhs = (&b"test"[..]).ret(123).bind(f);
let rhs = f(&b"test"[..], 123);
assert_eq!((lhs.0, lhs.1), (&b"test"[..], Ok(124)));
assert_eq!((rhs.0, rhs.1), (&b"test"[..], Ok(124)));
}
#[test]
fn test_consuming_whole_slice_does_not_reset_the_pointer() {
use crate::primitives::Primitives;
let slice: &[u8] = b"abc";
let mut b = slice;
b.consume(1);
b.consume_while(|_| true);
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
let mut b = slice;
b.consume(3);
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
let mut b = slice;
b.pop();
b.pop();
b.pop();
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
}
#[test]
fn test_consuming_whole_str_does_not_reset_the_pointer() {
use crate::primitives::Primitives;
let slice: &str = "abc";
let mut b = slice;
b.consume(1);
b.consume_while(|_| true);
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
let mut b = slice;
b.consume(3);
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
let mut b = slice;
b.pop();
b.pop();
b.pop();
let consumed = b.as_ptr() as usize - slice.as_ptr() as usize;
assert_eq!(consumed, 3);
}
#[test]
fn test_slice() {
run_primitives_test(&b"abc"[..], |x| x);
}
#[test]
fn test_string() {
run_primitives_test("abc", |c| c as char);
}
pub fn run_primitives_test<I: Input, F: Fn(u8) -> I::Token>(mut s: I, f: F)
where
I::Token: Debug,
I::Buffer: Clone,
{
use crate::primitives::Primitives;
fn buffer_eq_slice<B: Buffer + Clone, F: Fn(u8) -> B::Token>(b: B, s: &[u8], f: F)
where
B::Token: Debug,
{
assert_eq!(b.len(), s.len());
assert_eq!(b.is_empty(), s.is_empty());
assert_eq!(
b.clone().fold(0, |n, c| {
assert_eq!(c, f(s[n]));
n + 1
}),
s.len()
);
buffer_to_vec(b, s, f);
}
#[cfg(feature = "std")]
fn buffer_to_vec<B: Buffer + Clone, F: Fn(u8) -> B::Token>(b: B, s: &[u8], f: F)
where
B::Token: Debug,
{
assert_eq!(b.to_vec(), s.iter().cloned().map(f).collect::<Vec<_>>());
}
#[cfg(not(feature = "std"))]
fn buffer_to_vec<B: Buffer + Clone, F: Fn(u8) -> B::Token>(_: B, _: &[u8], _: F)
where
B::Token: Debug,
{
}
let m = s.mark();
assert_eq!(s.peek(), Some(f(b'a')));
assert_eq!(s.pop(), Some(f(b'a')));
assert_eq!(s.peek(), Some(f(b'b')));
assert_eq!(s.pop(), Some(f(b'b')));
assert_eq!(s.peek(), Some(f(b'c')));
assert_eq!(s.pop(), Some(f(b'c')));
assert_eq!(s.peek(), None);
assert_eq!(s.pop(), None);
assert_eq!(s.peek(), None);
assert_eq!(s.pop(), None);
assert!(s.consume(1).is_none());
buffer_eq_slice(s.consume_remaining(), &b""[..], &f);
{
let mut n = 0;
let b = s.consume_while(|_| {
n += 1;
true
});
assert_eq!(n, 0);
buffer_eq_slice(b, &b""[..], &f);
}
let mut s = s.restore(m);
assert_eq!(s.peek(), Some(f(b'a')));
let m = s.mark();
buffer_eq_slice(s.consume_remaining(), &b"abc"[..], &f);
assert_eq!(s.peek(), None);
let mut s = s.restore(m);
assert_eq!(s.peek(), Some(f(b'a')));
let m = s.mark();
{
let b = s.consume(2);
assert!(b.is_some());
buffer_eq_slice(b.unwrap(), &b"ab"[..], &f);
}
assert_eq!(s.peek(), Some(f(b'c')));
let mut s = s.restore(m);
assert_eq!(s.peek(), Some(f(b'a')));
let m = s.mark();
{
let b = s.consume(3);
assert!(b.is_some());
buffer_eq_slice(b.unwrap(), &b"abc"[..], &f);
}
assert_eq!(s.peek(), None);
let mut s = s.restore(m);
let m = s.mark();
if let Some(b) = s.consume(3) {
let mut v = Vec::new();
assert_eq!(b.len(), 3);
assert!(!b.is_empty());
b.iterate(|c| {
v.push(c);
});
assert_eq!(v, [f(b'a'), f(b'b'), f(b'c')]);
assert_eq!(b.len(), 3);
assert!(!b.is_empty());
} else {
panic!("s.consume(3) failed");
}
assert_eq!(s.peek(), None);
let mut s = s.restore(m);
assert_eq!(s.peek(), Some(f(b'a')));
let m = s.mark();
{
let mut n = 0;
let b = s.consume_while(|c| {
assert_eq!(c, f(b"abc"[n]));
n += 1;
n < 3
});
assert_eq!(n, 3);
buffer_eq_slice(b, &b"ab"[..], &f);
}
assert_eq!(s.peek(), Some(f(b'c')));
assert_eq!(s.pop(), Some(f(b'c')));
assert_eq!(s.peek(), None);
assert_eq!(s.pop(), None);
buffer_eq_slice(s.consume_from(m), &b"abc"[..], &f);
}
}