diff --git a/.travis.yml b/.travis.yml index 2c932076..c835defa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,8 +5,8 @@ rust: - stable - beta - nightly - # Minimum supported version (bitflags fails on 1.1): - - 1.2.0 + # Minimum supported version (bitflags fails on 1.7 due to op_assign_traits not being stable): + - 1.8.0 # necessary for `travis-cargo coveralls --no-sudo` addons: diff --git a/CHANGELOG.md b/CHANGELOG.md index ddf0215d..d4e4e109 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,29 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Added +- `prelude` module containing basic types, parsers and combinators. + + This is supposed to be the equivalent of Attoparsec's main package. + +- `run_parser` which executes a parser on any given `Input` type. + +- `buffer::InputBuf` which contains a slice and an incomplete flag, much as the old `Input` struct. + +- `Input` implementation for `&[T]` where `T: Copy + PartialEq`. + +- `Input` implementation for `&str`. + +- `types::Buffer` trait which is implemented for all buffers providing common logic to perform the + final parsing on a buffer without knowing the exact buffer implementation. + +- `types::U8Input` trait alias for `Input`. + +- `primitives::Primitives` trait providing access to the primitive methods of the `Input` trait. + + This is used for building fundamental parsers/combinators. + +- `ParseResult::inspect` allowing code to observe the success value. + - `chomp::Error` now includes a backtrace in `test` and `debug` build profiles thanks to the [debugtrace crate](https://github.com/m4rw3r/debugtrace_rs). Backtraces can also be activated permanently using the `backtrace` feature but this will incur the significant cost of allocating @@ -17,6 +40,27 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Changes +- **Backwards-incompatible:** `Input` is now a trait with associated types `Token` and `Buffer`. + + This removes all incomplete logic from the parsers themselves and moves it into the `InputBuf` + type. This `InputBuf` is used if a partial buffer is in memory. It also allows the parsers to + operate directly on slices or use more effective means of storing buffers depending on the + `Input` implementation. + + To upgrade you replace the previous concrete `Input` type with a generic, use its associated + type if required, and refer to the `Buffer` associated type to allow for zero-copy parsing:: + + -fn http_version(i: Input) -> U8Result<&[u8]>; + +fn http_version>(i: I) -> SimpleResult; + + The associated types can be restricted if requried: + + fn request(i: I) -> SimpleResult, Vec>)> + where I::Buffer: ::std::ops::Deref; + +- **Backwards-incompatible:** Moved types into a more logical module structure, prelude now + exists as a `prelude` module. + - **Backwards-incompatible:** `chomp::Error` is no longer an enum, this is to facillitate the support of backtraces while keeping code compatible between the different build profiles. @@ -26,10 +70,19 @@ This project adheres to [Semantic Versioning](http://semver.org/). ### Removed +- `Input::incomplete` - `Input::new` - `ParseResult::expect` -- `ParseResult::unwrap` - `ParseResult::unwrap_err` +- `ParseResult::unwrap` +- `buffer::IntoStream` +- `primitives::InputClone` +- `primitives::State` + +## Bugfixes + +- `combinators::bounded` now have a defined behavior when a `Range` has `start == end`: They will parse exactly `start` times. This also fixed a few overflows and unreachable code being reachable. +- `combinators::bounded::many_till` got fixed for an overflow happening when `0: usize` was used to limit the number of iterations. ## [0.2.6] - 2016-07-07 diff --git a/Cargo.toml b/Cargo.toml index e3642946..f7c5b291 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,13 +22,15 @@ include = [ ] [dependencies] -bitflags = "0.5.0" -conv = { version = "0.3", default-features = false, features = ["std"] } +bitflags = "0.7.0" +conv = { version = "0.3.3", default-features = false, features = ["std"] } debugtrace = { version = "0.1.0" } +tendril = { version = "0.2.2", optional = true } # Technically a dev-dependency, but dev-dependencies are not allowed to be optional, # compiletest_rs fails to compile on stable and beta compiletest_rs = { version = "0.2.1", optional = true } +clippy = { version = ">0.0.1", optional = true } [features] # Feature for running extra (compiletime fail) tests on nightly diff --git a/README.md b/README.md index 6579a70f..ecff757e 100644 --- a/README.md +++ b/README.md @@ -47,14 +47,14 @@ fn f() -> (u8, u8, u8) { A Chomp parser with a similar structure looks like this: ```rust -fn f(i: Input) -> U8Result<(u8, u8, u8)> { +fn f(i: I) -> SimpleResult { parse!{i; - let a = read_digit(); - let b = read_digit(); - string(b"missiles"); - ret (a, b, a + b); + let a = digit(); + let b = digit(); + string(b"missiles"); + ret (a, b, a + b) } -} +} ``` And to implement `read_digit` we can utilize the `map` function to manipulate any success value while preserving any error or incomplete state: @@ -68,7 +68,7 @@ fn read_digit() -> u8 { } // Chomp, error handling built in, and we make sure we only get a number: -fn read_digit(i: Input) -> U8Result { +fn read_digit(i: I) -> SimpleResult { satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0') } ``` diff --git a/benches/combinators.rs b/benches/combinators.rs index cbb4a832..f3a6f55a 100644 --- a/benches/combinators.rs +++ b/benches/combinators.rs @@ -7,19 +7,19 @@ use test::Bencher; use std::iter; -use chomp::*; -use chomp::buffer::{Stream, IntoStream}; +use chomp::prelude::*; +use chomp::buffer::InputBuf; #[bench] fn count_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn count_vec(i: Input) -> ParseResult, Error> { + fn count_vec(i: I) -> ParseResult, Error> { count(i, 1024, any) } b.iter(|| { - data.into_stream().parse(count_vec) + parse_only(count_vec, &data) }) } @@ -27,12 +27,12 @@ fn count_vec_1k(b: &mut Bencher) { fn count_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn count_vec(i: Input) -> ParseResult, Error> { + fn count_vec(i: I) -> ParseResult, Error> { count(i, 10024, any) } b.iter(|| { - data.into_stream().parse(count_vec) + parse_only(count_vec, &data) }) } @@ -40,12 +40,12 @@ fn count_vec_10k(b: &mut Bencher) { fn many_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn many_vec(i: Input) -> ParseResult, Error> { + fn many_vec(i: I) -> ParseResult, Error> { many(i, any) } b.iter(|| { - data.into_stream().parse(many_vec) + parse_only(many_vec, &data) }) } @@ -53,12 +53,12 @@ fn many_vec_1k(b: &mut Bencher) { fn many_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many_vec(i: Input) -> ParseResult, Error> { + fn many_vec(i: I) -> ParseResult, Error> { many(i, any) } b.iter(|| { - data.into_stream().parse(many_vec) + parse_only(many_vec, &data) }) } @@ -66,12 +66,12 @@ fn many_vec_10k(b: &mut Bencher) { fn many1_vec_1k(b: &mut Bencher) { let data = iter::repeat(b'a').take(1024).collect::>(); - fn many1_vec(i: Input) -> ParseResult, Error> { + fn many1_vec(i: I) -> ParseResult, Error> { many1(i, any) } b.iter(|| { - data.into_stream().parse(many1_vec) + parse_only(many1_vec, &data) }) } @@ -79,11 +79,50 @@ fn many1_vec_1k(b: &mut Bencher) { fn many1_vec_10k(b: &mut Bencher) { let data = iter::repeat(b'a').take(10024).collect::>(); - fn many1_vec(i: Input) -> ParseResult, Error> { + fn many1_vec(i: I) -> ParseResult, Error> { many1(i, any) } b.iter(|| { - data.into_stream().parse(many1_vec) + parse_only(many1_vec, &data) + }) +} + +#[bench] +fn count_vec_10k_maybe_incomplete(b: &mut Bencher) { + let data = iter::repeat(b'a').take(10024).collect::>(); + + fn count_vec(i: I) -> ParseResult, Error> { + count(i, 10024, any) + } + + b.iter(|| { + count_vec(InputBuf::new(&data)) + }) +} + +#[bench] +fn many_vec_10k_maybe_incomplete(b: &mut Bencher) { + let data = iter::repeat(b'a').take(10024).collect::>(); + + fn many_vec(i: I) -> ParseResult, Error> { + many(i, any) + } + + b.iter(|| { + many_vec(InputBuf::new(&data)) + }) +} + +#[bench] +fn many1_vec_10k_maybe_incomplete(b: &mut Bencher) { + let data = iter::repeat(b'a').take(10024).collect::>(); + + fn many1_vec(i: I) -> ParseResult, Error> { + many1(i, any) + } + + b.iter(|| { + many1_vec(InputBuf::new(&data)) }) } diff --git a/benches/http_bench.rs b/benches/http_bench.rs index 4c0c408d..e157990e 100644 --- a/benches/http_bench.rs +++ b/benches/http_bench.rs @@ -4,20 +4,19 @@ extern crate test; extern crate chomp; use test::Bencher; -use chomp::*; -use chomp::buffer::{Stream, IntoStream}; +use chomp::prelude::*; #[derive(Debug)] -struct Request<'a> { - method: &'a [u8], - uri: &'a [u8], - version: &'a [u8], +struct Request { + method: B, + uri: B, + version: B, } #[derive(Debug)] -struct Header<'a> { - name: &'a [u8], - value: Vec<&'a [u8]>, +struct Header { + name: B, + value: Vec, } fn is_token(c: u8) -> bool { @@ -52,22 +51,18 @@ fn is_not_space(c: u8) -> bool { c != b' ' } fn is_end_of_line(c: u8) -> bool { c == b'\r' || c == b'\n' } fn is_http_version(c: u8) -> bool { c >= b'0' && c <= b'9' || c == b'.' } -fn end_of_line(i: Input) -> U8Result { - or(i, |i| parse!{i; - token(b'\r'); - token(b'\n'); - ret b'\r'}, - |i| token(i, b'\n')) +fn end_of_line(i: I) -> SimpleResult { + parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')} } -fn http_version(i: Input) -> U8Result<&[u8]> { +fn http_version(i: I) -> SimpleResult { parse!{i; string(b"HTTP/"); take_while1(is_http_version) } } -fn request_line(i: Input) -> U8Result { +fn request_line(i: I) -> SimpleResult> { parse!{i; let method = take_while1(is_token); take_while1(is_space); @@ -83,7 +78,7 @@ fn request_line(i: Input) -> U8Result { } } -fn message_header_line(i: Input) -> U8Result<&[u8]> { +fn message_header_line(i: I) -> SimpleResult { parse!{i; take_while1(is_horizontal_space); let line = take_till(is_end_of_line); @@ -93,7 +88,7 @@ fn message_header_line(i: Input) -> U8Result<&[u8]> { } } -fn message_header(i: Input) -> U8Result
{ +fn message_header(i: I) -> SimpleResult> { parse!{i; let name = take_while1(is_token); token(b':'); @@ -106,7 +101,8 @@ fn message_header(i: Input) -> U8Result
{ } } -fn request(i: Input) -> U8Result<(Request, Vec
)> { +#[inline(never)] +fn request(i: I) -> SimpleResult, Vec>)> { parse!{i; let r = request_line(); end_of_line(); @@ -130,7 +126,7 @@ Connection: keep-alive\r \r"; b.iter(|| { - data.into_stream().parse(request) + parse_only(request, data) }) } @@ -142,7 +138,7 @@ Host: localhost\r \r"; b.iter(|| { - data.into_stream().parse(request) + parse_only(request, data) }) } @@ -161,7 +157,7 @@ Cookie: azk=ue1-5eb08aeed9a7401c9195cb933eb7c966\r \r"; b.iter(|| { - data.into_stream().parse(request) + parse_only(request, data) }) } @@ -170,6 +166,8 @@ fn multiple_requests(b: &mut Bencher) { let data = include_bytes!("./data/http-requests.txt"); b.iter(|| { - data.into_stream().parse::<_, Vec<_>, _>(parser!{many(request)}) + let r: Result, _> = parse_only(parser!{many(request)}, data); + + r }) } diff --git a/examples/http_parser.rs b/examples/http_parser.rs index 78b71e96..4deec9cd 100644 --- a/examples/http_parser.rs +++ b/examples/http_parser.rs @@ -15,21 +15,21 @@ extern crate chomp; use std::fs::File; use std::env; -use chomp::*; +use chomp::prelude::*; use chomp::buffer::{Source, Stream, StreamError}; #[derive(Debug)] -struct Request<'a> { - method: &'a [u8], - uri: &'a [u8], - version: &'a [u8], +struct Request { + method: B, + uri: B, + version: B, } #[derive(Debug)] -struct Header<'a> { - name: &'a [u8], - value: Vec<&'a [u8]>, +struct Header { + name: B, + value: Vec, } fn is_token(c: u8) -> bool { @@ -64,22 +64,18 @@ fn is_not_space(c: u8) -> bool { c != b' ' } fn is_end_of_line(c: u8) -> bool { c == b'\r' || c == b'\n' } fn is_http_version(c: u8) -> bool { c >= b'0' && c <= b'9' || c == b'.' } -fn end_of_line(i: Input) -> U8Result { - or(i, |i| parse!{i; - token(b'\r'); - token(b'\n'); - ret b'\r'}, - |i| token(i, b'\n')) +fn end_of_line(i: I) -> SimpleResult { + parse!{i; (token(b'\r') <|> ret b'\0') >> token(b'\n')} } -fn http_version(i: Input) -> U8Result<&[u8]> { +fn http_version(i: I) -> SimpleResult { parse!{i; string(b"HTTP/"); take_while1(is_http_version) } } -fn request_line(i: Input) -> U8Result { +fn request_line(i: I) -> SimpleResult> { parse!{i; let method = take_while1(is_token); take_while1(is_space); @@ -95,7 +91,7 @@ fn request_line(i: Input) -> U8Result { } } -fn message_header_line(i: Input) -> U8Result<&[u8]> { +fn message_header_line(i: I) -> SimpleResult { parse!{i; take_while1(is_horizontal_space); let line = take_till(is_end_of_line); @@ -105,7 +101,7 @@ fn message_header_line(i: Input) -> U8Result<&[u8]> { } } -fn message_header(i: Input) -> U8Result
{ +fn message_header(i: I) -> SimpleResult> { parse!{i; let name = take_while1(is_token); token(b':'); @@ -118,7 +114,9 @@ fn message_header(i: Input) -> U8Result
{ } } -fn request(i: Input) -> U8Result<(Request, Vec
)> { +#[inline(never)] +fn request(i: I) -> SimpleResult, Vec>)> + where I::Buffer: ::std::ops::Deref { parse!{i; let r = request_line(); end_of_line(); @@ -140,7 +138,7 @@ fn main() { Ok(_) => n += 1, Err(StreamError::Retry) => {}, // Needed to refill buffer when necessary Err(StreamError::EndOfInput) => break, - Err(e) => { panic!("{:?}", e); } + Err(e) => { panic!("{}: {:?}", n, e); } } } diff --git a/src/ascii.rs b/src/ascii.rs index e9f1c333..6c59346e 100644 --- a/src/ascii.rs +++ b/src/ascii.rs @@ -1,13 +1,21 @@ //! Utilities and parsers for dealing with ASCII data in `u8` format. -use conv::{NoError, ValueFrom}; -use conv::errors::UnwrapOk; - use std::ops::{Add, Mul}; -use {Input, U8Result}; +use conv::{ + NoError, + ValueFrom, +}; +use conv::errors::UnwrapOk; + +use types::{Buffer, Input}; use combinators::option; -use parsers::{take_while, take_while1, satisfy}; +use parsers::{ + SimpleResult, + satisfy, + take_while, + take_while1, +}; /// Lowercase ASCII predicate. #[inline] @@ -79,7 +87,7 @@ pub fn is_alphanumeric(c: u8) -> bool { /// assert_eq!(parse_only(skip_whitespace, b" \t "), Ok(())); /// ``` #[inline] -pub fn skip_whitespace(i: Input) -> U8Result<()> { +pub fn skip_whitespace>(i: I) -> SimpleResult { take_while(i, is_whitespace).map(|_| ()) } @@ -98,7 +106,7 @@ pub fn skip_whitespace(i: Input) -> U8Result<()> { /// assert_eq!(parse_only(digit, b"1"), Ok(b'1')); /// ``` #[inline] -pub fn digit(i: Input) -> U8Result { +pub fn digit>(i: I) -> SimpleResult { satisfy(i, is_digit) } @@ -120,9 +128,9 @@ pub fn digit(i: Input) -> U8Result { /// assert_eq!(r, Ok(-123i16)); /// ``` #[inline] -pub fn signed(i: Input, f: F) -> U8Result +pub fn signed, T, F>(i: I, f: F) -> SimpleResult where T: Copy + ValueFrom + Add + Mul, - F: FnOnce(Input) -> U8Result { + F: FnOnce(I) -> SimpleResult { option(i, |i| satisfy(i, |c| c == b'-' || c == b'+') .map(|s| T::value_from(if s == b'+' { 1 } else { -1 }).unwrap_ok()), @@ -142,12 +150,12 @@ pub fn signed(i: Input, f: F) -> U8Result /// use chomp::parse_only; /// use chomp::ascii::decimal; /// -/// let r = parse_only(decimal::, b"123"); +/// let r = parse_only(decimal::<_, u8>, b"123"); /// /// assert_eq!(r, Ok(123u8)); /// ``` #[inline] -pub fn decimal + Add + Mul>(i: Input) -> U8Result { +pub fn decimal, T: Copy + ValueFrom + Add + Mul>(i: I) -> SimpleResult { take_while1(i, is_digit).map(to_decimal) } @@ -158,8 +166,8 @@ pub fn decimal + Add + Mul + Add + Mul>(buf: &[u8]) -> T { - buf.iter().fold(T::value_from(0).unwrap_ok(), |a, n| a * T::value_from(10).unwrap_ok() + T::value_from(n - b'0').unwrap_ok()) +fn to_decimal + Add + Mul, I: Buffer>(iter: I) -> T { + iter.fold(T::value_from(0).unwrap_ok(), |a, n| a * T::value_from(10).unwrap_ok() + T::value_from(n - b'0').unwrap_ok()) } #[cfg(test)] @@ -168,13 +176,13 @@ mod test { macro_rules! test_to_decimal { ( $($n:ty),+ ) => { $( - assert_eq!(to_decimal::<$n>(b""), 0); - assert_eq!(to_decimal::<$n>(b"0"), 0); - assert_eq!(to_decimal::<$n>(b"1"), 1); - assert_eq!(to_decimal::<$n>(b"2"), 2); - assert_eq!(to_decimal::<$n>(b"10"), 10); - assert_eq!(to_decimal::<$n>(b"20"), 20); - assert_eq!(to_decimal::<$n>(b"25"), 25); + assert_eq!(to_decimal::<$n, _>(&b""[..]), 0); + assert_eq!(to_decimal::<$n, _>(&b"0"[..]), 0); + assert_eq!(to_decimal::<$n, _>(&b"1"[..]), 1); + assert_eq!(to_decimal::<$n, _>(&b"2"[..]), 2); + assert_eq!(to_decimal::<$n, _>(&b"10"[..]), 10); + assert_eq!(to_decimal::<$n, _>(&b"20"[..]), 20); + assert_eq!(to_decimal::<$n, _>(&b"25"[..]), 25); )+ } } diff --git a/src/buffer/buffer.rs b/src/buffer/buffer.rs deleted file mode 100644 index 05ce1129..00000000 --- a/src/buffer/buffer.rs +++ /dev/null @@ -1,289 +0,0 @@ -use std::ops; -use std::ptr; -use std::io; - -use std::cell::Cell; - -use buffer::DataSource; - -const DEFAULT_BUFFER_SIZE: usize = 6 * 1024; - -/// Trait all parser buffers implement. -/// -/// Enables the consumer to request specific amounts of data and only consume partial parts of the -/// buffer. -pub trait Buffer: ops::Deref { - /// Attempt to fill the buffer using the closure `F`. - /// - /// The successful return from `F` should contain the number of items successfully written to - /// the slice. - /// - /// # Notes - /// - /// * The returned value must *NOT* be larger than the length of the given slice. - /// - /// * Return `0` if no more data is available or if the slice is of zero length. - /// - /// * The slice might contain uninitialized memory, do not read from the slice. - #[inline] - fn fill>(&mut self, &mut S) -> io::Result; - - - /// Buffer attempts to clear space for additional items. - #[inline] - fn request_space(&mut self, usize); - - /// Consumes the given amount of bytes, must be less than or equal to `len()`. - /// - /// Does not invalidate any borrow of data from self. - #[inline] - fn consume(&self, items: usize); - - /// Returns the number of bytes left in the buffer. - #[inline] - fn len(&self) -> usize; - - /// If the buffer has no more data. - #[inline] - fn is_empty(&self) -> bool { - self.len() == 0 - } - - /// Returns the maximum amount of data which can be stored - #[inline] - fn capacity(&self) -> usize; -} - -/// A fixed size buffer. -/// -/// Only allocates when created. -// TODO: Tests -#[derive(Debug, Eq, PartialEq)] -pub struct FixedSizeBuffer { - /// Backing memory. - buffer: Vec, - /// Number of items of `buffer` which contain actual data. - populated: usize, - /// The number of bytes from the start of the buffer which are used. - /// - /// As long as used <= populated it is safe. - used: Cell, -} - -impl FixedSizeBuffer { - /// Creates a fixed-size buffer with the default buffer size. - #[inline] - pub fn new() -> Self { - Self::with_size(DEFAULT_BUFFER_SIZE) - } - - /// Creates a fixed-size buffer with the supplied buffer size. - #[inline] - pub fn with_size(size: usize) -> Self { - assert!(size > 0); - - let mut buf = Vec::with_capacity(size); - - // TODO: Would it be better with a Default requirement on I? - // We set the length here to allow fill() to hand out a slice of uninitialized memory - // to be populated. - // NOTE: We cannot actually expose this memory to the parser since self.populated will - // be the upper limit for the deref to slice. - unsafe { - buf.set_len(size); - } - - FixedSizeBuffer { - buffer: buf, - populated: 0, - used: Cell::new(0), - } - } -} - -impl ops::Deref for FixedSizeBuffer { - type Target = [I]; - - #[inline] - fn deref(&self) -> &[I] { - &self.buffer[self.used.get()..self.populated] - } -} - -impl ops::DerefMut for FixedSizeBuffer { - #[inline] - fn deref_mut(&mut self) -> &mut [I] { - &mut self.buffer[self.used.get()..self.populated] - } -} - -impl Buffer for FixedSizeBuffer { - #[inline] - fn fill>(&mut self, s: &mut S) -> io::Result { - s.read(&mut self.buffer[self.populated..]).map(|n| { - debug_assert!(self.populated + n <= self.buffer.len()); - - self.populated += n; - - n - }) - } - - #[inline] - fn request_space(&mut self, items: usize) { - use std::ptr; - - assert!(self.populated >= self.used.get()); - - // Only copy if we actually need to free the space - if self.buffer.len() - self.populated < items { - unsafe { - ptr::copy(self.buffer.as_ptr().offset(self.used.get() as isize), self.buffer.as_mut_ptr(), self.populated - self.used.get()); - } - - self.populated -= self.used.get(); - self.used.set(0); - } - } - - #[inline] - fn consume(&self, items: usize) { - debug_assert!(self.used.get() + items <= self.populated); - - self.used.set(self.used.get() + items) - } - - #[inline] - fn len(&self) -> usize { - self.populated - self.used.get() - } - - #[inline] - fn capacity(&self) -> usize { - self.buffer.len() - } -} - -/// A buffer which will reallocate to fit the requested amount of data. -/// -/// # Note: -/// -/// Will not decrease in size. -// TODO: Tests -#[derive(Debug)] -pub struct GrowingBuffer { - /// Backing memory. - buffer: Vec, - /// Number of items of `buffer` which contain actual data. - populated: usize, - /// Maximal size of the buffer, 0 means infinity. - limit: usize, - /// The number of bytes from the start of the buffer which are used. - /// - /// As long as used <= populated it is safe. - used: Cell, -} - -impl GrowingBuffer { - /// Creates a new unlimited `GrowingBuffer`. - #[inline] - pub fn new() -> Self { - Self::with_limit(0) - } - - /// Creates a new `GrowingBuffer` with the specified limit. - /// - /// # Note - /// - /// The actual amount of allocated memory might be larger than the specified limit, depends on - /// the allocator. - #[inline] - pub fn with_limit(limit: usize) -> Self { - GrowingBuffer { - buffer: Vec::new(), - populated: 0, - limit: limit, - used: Cell::new(0), - } - } -} - -impl ops::Deref for GrowingBuffer { - type Target = [I]; - - #[inline] - fn deref(&self) -> &[I] { - &self.buffer[self.used.get()..self.populated] - } -} - -impl ops::DerefMut for GrowingBuffer { - #[inline] - fn deref_mut(&mut self) -> &mut [I] { - &mut self.buffer[self.used.get()..self.populated] - } -} - -impl Buffer for GrowingBuffer { - #[inline] - fn fill>(&mut self, s: &mut S) -> io::Result { - s.read(&mut self.buffer[self.populated..]).map(|n| { - debug_assert!(self.populated + n <= self.buffer.len()); - - self.populated += n; - - n - }) - } - - #[inline] - fn request_space(&mut self, items: usize) { - // If we are over the limit, refuse - if self.limit != 0 && self.buffer.capacity() > self.limit { - return; - } - - if items + self.len() > self.buffer.capacity() { - // We do not have enough space for the new items, reallocate - self.buffer.reserve(items); - - let cap = self.buffer.capacity(); - - // TODO: Would it be better with a Default requirement on I? - // We set the length here to allow fill() to hand out a slice of uninitialized memory - // to be populated. - // NOTE: We cannot actually expose this memory to the parser since self.populated will - // be the upper limit for the deref to slice. - unsafe { - self.buffer.set_len(cap); - } - } - - // Only copy if we actually need to free the space - if self.buffer.len() - self.populated < items { - unsafe { - ptr::copy(self.buffer.as_ptr().offset(self.used.get() as isize), self.buffer.as_mut_ptr(), self.populated - self.used.get()); - } - - self.populated -= self.used.get(); - self.used.set(0); - } - } - - #[inline] - fn consume(&self, items: usize) { - debug_assert!(self.used.get() + items <= self.populated); - - self.used.set(self.used.get() + items) - } - - #[inline] - fn len(&self) -> usize { - self.populated - self.used.get() - } - - #[inline] - fn capacity(&self) -> usize { - self.buffer.len() - } -} diff --git a/src/buffer/data_source.rs b/src/buffer/data_source.rs index 49afcda5..c574d96c 100644 --- a/src/buffer/data_source.rs +++ b/src/buffer/data_source.rs @@ -5,7 +5,7 @@ use std::io; /// Abstraction over `io::Read`, `Iterator` and others. pub trait DataSource { /// The type of items this data source produces. - type Item; + type Item: Copy + PartialEq; /// Populates the supplied buffer with data, returns the number of items written. /// @@ -68,7 +68,8 @@ impl IteratorDataSource { } } -impl DataSource for IteratorDataSource { +impl DataSource for IteratorDataSource + where I::Item: Copy + PartialEq { type Item = I::Item; #[inline] diff --git a/src/buffer/mod.rs b/src/buffer/mod.rs index df933bd6..be21b2c3 100644 --- a/src/buffer/mod.rs +++ b/src/buffer/mod.rs @@ -9,7 +9,7 @@ //! //! use chomp::buffer; //! use chomp::buffer::Stream; -//! use chomp::{token, take_while, take_while1}; +//! use chomp::prelude::{token, take_while, take_while1}; //! use chomp::ascii::is_whitespace; //! //! let f = File::open("./README.md").unwrap(); @@ -28,33 +28,33 @@ //! ``` mod stateful; -mod buffer; mod slice; pub mod data_source; use std::io; +use std::ops; +use std::ptr; -use {ParseResult, Input}; -use parse::ParseError; +use std::cell::Cell; + +use types::{Input, ParseResult}; +use types::Buffer as InputBuffer; +use primitives::Guard; pub use self::slice::SliceStream; pub use self::data_source::DataSource; pub use self::stateful::Source; -pub use self::buffer::{ - Buffer, - FixedSizeBuffer, - GrowingBuffer, -}; + +const DEFAULT_BUFFER_SIZE: usize = 6 * 1024; /// Error type for parsing using the `Stream` trait. #[derive(Debug)] -pub enum StreamError<'a, I, E> - where I: 'a { +pub enum StreamError { /// An error occurred in the parser, the given slice indicates the part which failed. - ParseError(&'a [I], E), + ParseError(B, E), /// Parser failed to complete with the available data. - Incomplete(usize), + Incomplete, /// An IO-error occurred while attempting to fill the buffer. IoError(io::Error), /// The last parser completed successfully and there is no more input to parse. @@ -65,34 +65,23 @@ pub enum StreamError<'a, I, E> Retry, } -impl<'a, I, E> PartialEq for StreamError<'a, I, E> - where E: PartialEq, I: PartialEq { +impl> PartialEq for StreamError { #[inline] - fn eq(&self, other: &StreamError<'a, I, E>) -> bool { + fn eq(&self, other: &StreamError) -> bool { match (self, other) { (&StreamError::ParseError(ref b1, ref e1), &StreamError::ParseError(ref b2, ref e2)) => b1 == b2 && e1 == e2, - (&StreamError::Incomplete(n1), &StreamError::Incomplete(n2)) => n1 == n2, - (&StreamError::EndOfInput, &StreamError::EndOfInput) => true, - (&StreamError::Retry, &StreamError::Retry) => true, + (&StreamError::Incomplete, &StreamError::Incomplete) + | (&StreamError::EndOfInput, &StreamError::EndOfInput) + | (&StreamError::Retry, &StreamError::Retry) => true, _ => false, } } } -impl<'a, I, E> From> for StreamError<'a, I, E> - where I: 'a { - fn from(e: ParseError<'a, I, E>) -> Self { - match e { - ParseError::Error(b, e) => StreamError::ParseError(b, e), - ParseError::Incomplete(n) => StreamError::Incomplete(n), - } - } -} - /// Trait wrapping the state management in reading from a data source while parsing. pub trait Stream<'a, 'i> { /// The input item type, usually depending on which `DataSource` is used. - type Item: 'i; + type Input: Input + 'i; /// Attempts to run the supplied parser `F` once on the currently populated data in this /// stream, providing a borrow of the inner data storage. @@ -100,20 +89,557 @@ pub trait Stream<'a, 'i> { /// If a `StreamError::Retry` is returned the consuming code it should just retry the action /// (the implementation might require a separate call to refill the stream). #[inline] - fn parse(&'a mut self, f: F) -> Result> - where F: FnOnce(Input<'i, Self::Item>) -> ParseResult<'i, Self::Item, T, E>, + fn parse(&'a mut self, f: F) -> Result::Buffer, E>> + where F: FnOnce(Self::Input) -> ParseResult, T: 'i, E: 'i; } -/// Trait for conversion into a `Stream`. -pub trait IntoStream<'a, 'i> { - /// The input item type provided by the stream. - type Item: 'i; - /// The `Stream` instance type. - type Into: Stream<'a, 'i, Item=Self::Item>; +/// Input buffer type which contains a flag which tells if we might need to read more data. +#[must_use] +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct InputBuf<'a, I: 'a>( + /// If this is set to true a parser has tried to read past the end of this buffer. + bool, + /// Current buffer slice + &'a [I], +); + +impl<'a, I: 'a> InputBuf<'a, I> { + /// Creates a new input buffer with incomplete set to false. + #[inline] + pub fn new(buf: &'a [I]) -> Self { + InputBuf(false, buf) + } + + /// Returns true if parsers want to obtain more data. + /// + /// The result of the parsing is only accurate if this is false after completed parsing. + #[inline] + pub fn is_incomplete(&self) -> bool { + self.0 + } + + /// Returns the length of the contained buffer, may be an incomplete buffer. + #[inline] + pub fn len(&self) -> usize { + self.1.len() + } + + /// Returns true if the contained buffer is empty, may return true even when incomplete. + #[inline] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl<'a, I: Copy + PartialEq> Input for InputBuf<'a, I> { + type Token = I; + type Marker = &'a [I]; + type Buffer = &'a [I]; + + #[inline] + fn _peek(&mut self, _g: Guard) -> Option { + if let Some(c) = self.1.first() { + Some(*c) + } else { + self.0 = true; + + None + } + } + + #[inline] + fn _pop(&mut self, g: Guard) -> Option { + self._peek(g).map(|c| { + self.1 = &self.1[1..]; + + c + }) + } + + #[inline] + fn _consume(&mut self, _g: Guard, n: usize) -> Option { + if n > self.1.len() { + self.0 = true; + + None + } else { + let b = &self.1[..n]; + + self.1 = &self.1[n..]; + + Some(b) + } + } + + #[inline] + fn _consume_while(&mut self, g: Guard, mut f: F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool { + if let Some(n) = self.1.iter().position(|c| !f(*c)) { + let b = &self.1[..n]; + + self.1 = &self.1[n..]; + + b + } else { + self._consume_remaining(g) + } + } + + #[inline] + fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + &m[..m.len() - self.1.len()] + } + + #[inline] + fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + self.0 = true; + + let b = self.1; + + self.1 = &self.1[..0]; + + b + } + + #[inline] + fn _mark(&self, _g: Guard) -> Self::Marker { + // Incomplete state is separate from the parsed state, no matter how we hit incomplete we + // want to keep it. + self.1 + } + + #[inline] + fn _restore(mut self, _g: Guard, m: Self::Marker) -> Self { + self.1 = m; + + self + } +} + +/// Trait all parser buffers implement. +/// +/// Enables the consumer to request specific amounts of data and only consume partial parts of the +/// buffer. +pub trait Buffer: ops::Deref { + /// Attempt to fill the buffer using the closure `F`. + /// + /// The successful return from `F` should contain the number of items successfully written to + /// the slice. + /// + /// # Notes + /// + /// * The returned value must *NOT* be larger than the length of the given slice. + /// + /// * Return `0` if no more data is available or if the slice is of zero length. + /// + /// * The slice might contain uninitialized memory, do not read from the slice. + #[inline] + fn fill>(&mut self, &mut S) -> io::Result; + + /// Buffer attempts to clear space for additional items. + #[inline] + fn request_space(&mut self, usize); + + /// Consumes the given amount of bytes, must be less than or equal to `len()`. + /// + /// Does not invalidate any borrow of data from self. + #[inline] + fn consume(&self, items: usize); + + /// Returns the number of bytes left in the buffer. + #[inline] + fn len(&self) -> usize; + + /// If the buffer has no more data. + #[inline] + fn is_empty(&self) -> bool { + self.len() == 0 + } + + /// Returns the maximum amount of data which can be stored + #[inline] + fn capacity(&self) -> usize; +} + +/// A fixed size buffer. +/// +/// Only allocates when created. +// TODO: Tests +#[derive(Debug, Eq, PartialEq)] +pub struct FixedSizeBuffer { + /// Backing memory. + buffer: Vec, + /// Number of items of `buffer` which contain actual data. + populated: usize, + /// The number of bytes from the start of the buffer which are used. + /// + /// As long as used <= populated it is safe. + used: Cell, +} + +impl FixedSizeBuffer { + /// Creates a fixed-size buffer with the default buffer size. + #[inline] + pub fn new() -> Self { + Self::with_size(DEFAULT_BUFFER_SIZE) + } + + /// Creates a fixed-size buffer with the supplied buffer size. + #[inline] + pub fn with_size(size: usize) -> Self { + assert!(size > 0); + + let mut buf = Vec::with_capacity(size); + + // TODO: Would it be better with a Default requirement on I? + // We set the length here to allow fill() to hand out a slice of uninitialized memory + // to be populated. + // NOTE: We cannot actually expose this memory to the parser since self.populated will + // be the upper limit for the deref to slice. + unsafe { + buf.set_len(size); + } + + FixedSizeBuffer { + buffer: buf, + populated: 0, + used: Cell::new(0), + } + } +} + +impl ops::Deref for FixedSizeBuffer { + type Target = [I]; + + #[inline] + fn deref(&self) -> &[I] { + &self.buffer[self.used.get()..self.populated] + } +} + +impl ops::DerefMut for FixedSizeBuffer { + #[inline] + fn deref_mut(&mut self) -> &mut [I] { + &mut self.buffer[self.used.get()..self.populated] + } +} + +impl Buffer for FixedSizeBuffer { + #[inline] + fn fill>(&mut self, s: &mut S) -> io::Result { + s.read(&mut self.buffer[self.populated..]).map(|n| { + debug_assert!(self.populated + n <= self.buffer.len()); + + self.populated += n; + + n + }) + } + + #[inline] + fn request_space(&mut self, items: usize) { + use std::ptr; + + assert!(self.populated >= self.used.get()); + + // Only copy if we actually need to free the space + if self.buffer.len() - self.populated < items { + unsafe { + ptr::copy(self.buffer.as_ptr().offset(self.used.get() as isize), self.buffer.as_mut_ptr(), self.populated - self.used.get()); + } + + self.populated -= self.used.get(); + self.used.set(0); + } + } + + #[inline] + fn consume(&self, items: usize) { + debug_assert!(self.used.get() + items <= self.populated); + + self.used.set(self.used.get() + items) + } + + #[inline] + fn len(&self) -> usize { + self.populated - self.used.get() + } + + #[inline] + fn capacity(&self) -> usize { + self.buffer.len() + } +} + +/// A buffer which will reallocate to fit the requested amount of data. +/// +/// # Note: +/// +/// Will not decrease in size. +// TODO: Tests +#[derive(Debug)] +pub struct GrowingBuffer { + /// Backing memory. + buffer: Vec, + /// Number of items of `buffer` which contain actual data. + populated: usize, + /// Maximal size of the buffer, 0 means infinity. + limit: usize, + /// The number of bytes from the start of the buffer which are used. + /// + /// As long as used <= populated it is safe. + used: Cell, +} + +impl GrowingBuffer { + /// Creates a new unlimited `GrowingBuffer`. + #[inline] + pub fn new() -> Self { + Self::with_limit(0) + } + + /// Creates a new `GrowingBuffer` with the specified limit. + /// + /// # Note + /// + /// The actual amount of allocated memory might be larger than the specified limit, depends on + /// the allocator. + #[inline] + pub fn with_limit(limit: usize) -> Self { + GrowingBuffer { + buffer: Vec::new(), + populated: 0, + limit: limit, + used: Cell::new(0), + } + } +} + +impl ops::Deref for GrowingBuffer { + type Target = [I]; + + #[inline] + fn deref(&self) -> &[I] { + &self.buffer[self.used.get()..self.populated] + } +} + +impl ops::DerefMut for GrowingBuffer { + #[inline] + fn deref_mut(&mut self) -> &mut [I] { + &mut self.buffer[self.used.get()..self.populated] + } +} - /// Convert self into a `Stream`. +impl Buffer for GrowingBuffer { #[inline] - fn into_stream(self) -> Self::Into; + fn fill>(&mut self, s: &mut S) -> io::Result { + s.read(&mut self.buffer[self.populated..]).map(|n| { + debug_assert!(self.populated + n <= self.buffer.len()); + + self.populated += n; + + n + }) + } + + #[inline] + fn request_space(&mut self, items: usize) { + // If we are over the limit, refuse + if self.limit != 0 && self.buffer.capacity() > self.limit { + return; + } + + if items + self.len() > self.buffer.capacity() { + // We do not have enough space for the new items, reallocate + self.buffer.reserve(items); + + let cap = self.buffer.capacity(); + + // TODO: Would it be better with a Default requirement on I? + // We set the length here to allow fill() to hand out a slice of uninitialized memory + // to be populated. + // NOTE: We cannot actually expose this memory to the parser since self.populated will + // be the upper limit for the deref to slice. + unsafe { + self.buffer.set_len(cap); + } + } + + // Only copy if we actually need to free the space + if self.buffer.len() - self.populated < items { + unsafe { + ptr::copy(self.buffer.as_ptr().offset(self.used.get() as isize), self.buffer.as_mut_ptr(), self.populated - self.used.get()); + } + + self.populated -= self.used.get(); + self.used.set(0); + } + } + + #[inline] + fn consume(&self, items: usize) { + debug_assert!(self.used.get() + items <= self.populated); + + self.used.set(self.used.get() + items) + } + + #[inline] + fn len(&self) -> usize { + self.populated - self.used.get() + } + + #[inline] + fn capacity(&self) -> usize { + self.buffer.len() + } +} + +#[cfg(test)] +mod test { + use super::InputBuf; + use types::{Input, ParseResult}; + use primitives::{IntoInner, Primitives}; + + use types::test::run_primitives_test; + + #[test] + fn ret() { + let i1: InputBuf = InputBuf::new(b"in1"); + let i2: InputBuf = InputBuf::new(b"in2"); + + let r1: ParseResult<_, u32, ()> = i1.ret::<_, ()>(23u32); + let r2: ParseResult<_, i32, &str> = i2.ret::<_, &str>(23i32); + + assert_eq!(r1.into_inner(), (InputBuf::new(b"in1"), Ok(23u32))); + assert_eq!(r2.into_inner(), (InputBuf::new(b"in2"), Ok(23i32))); + } + + #[test] + fn err() { + let i1: InputBuf = InputBuf::new(b"in1"); + let i2: InputBuf = InputBuf::new(b"in2"); + + let r1: ParseResult<_, (), u32> = i1.err::<(), _>(23u32); + let r2: ParseResult<_, &str, i32> = i2.err::<&str, _>(23i32); + + assert_eq!(r1.into_inner(), (InputBuf::new(b"in1"), Err(23u32))); + assert_eq!(r2.into_inner(), (InputBuf::new(b"in2"), Err(23i32))); + } + + #[test] + fn test_input_buf() { + + run_primitives_test(InputBuf::new(b"abc"), |x| x); + + let mut b = InputBuf::new(b"a"); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 1); + assert_eq!(b.is_empty(), false); + b.peek(); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 1); + assert_eq!(b.is_empty(), false); + b.pop(); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + assert_eq!(b.peek(), None); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + assert_eq!(b.pop(), None); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + + let mut b = InputBuf::new(b"ab"); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 2); + assert_eq!(b.is_empty(), false); + b.consume(1); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 1); + assert_eq!(b.is_empty(), false); + b.consume(1); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + assert_eq!(b.consume(1), None); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + + let mut b = InputBuf::new(b"ab"); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 2); + assert_eq!(b.is_empty(), false); + assert_eq!(b.consume(3), None); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 2); + assert_eq!(b.is_empty(), false); + + let mut b = InputBuf::new(b"ab"); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 2); + assert_eq!(b.is_empty(), false); + assert_eq!(b.consume_while(|_| true), &b"ab"[..]); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + + let mut b = InputBuf::new(b"ab"); + assert_eq!(b.consume_while(|c| c == b'a'), &b"a"[..]); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 1); + assert_eq!(b.is_empty(), false); + assert_eq!(b.consume_while(|c| c == b'b'), &b"b"[..]); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + assert_eq!(b.consume_while(|c| c == b'b'), &b""[..]); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + + let mut b = InputBuf::new(b"abc"); + let m = b.mark(); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 3); + assert_eq!(b.is_empty(), false); + b.consume(3); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + assert_eq!(b.consume_from(m), &b"abc"[..]); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + + let mut b = InputBuf::new(b"abc"); + let m = b.mark(); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 3); + assert_eq!(b.is_empty(), false); + b.consume(2); + b.consume(2); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 1); + assert_eq!(b.is_empty(), false); + let b = b.restore(m); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 3); + assert_eq!(b.is_empty(), false); + + let mut b = InputBuf::new(b"abc"); + assert_eq!(b.is_incomplete(), false); + assert_eq!(b.len(), 3); + assert_eq!(b.is_empty(), false); + b.consume_remaining(); + assert_eq!(b.is_incomplete(), true); + assert_eq!(b.len(), 0); + assert_eq!(b.is_empty(), true); + } } diff --git a/src/buffer/slice.rs b/src/buffer/slice.rs index 97d61c68..35966e40 100644 --- a/src/buffer/slice.rs +++ b/src/buffer/slice.rs @@ -1,20 +1,17 @@ -use primitives::input; -use primitives::{State, InputBuffer, IntoInner}; +use primitives::IntoInner; -use {Input, ParseResult}; -use buffer::{IntoStream, StreamError, Stream}; +use types::{Input, ParseResult}; +use buffer::{InputBuf, StreamError, Stream}; /// Stream implementation for immutable slices. /// /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{token, take}; -/// use chomp::buffer::{IntoStream, Stream}; +/// use chomp::parsers::{token, take}; +/// use chomp::buffer::{SliceStream, Stream}; /// -/// let i = b"foo"; -/// -/// let r = i.into_stream().parse(parser!{ +/// let r = SliceStream::new(b"foo").parse(parser!{ /// token(b'f'); /// take(2) /// }); @@ -26,12 +23,10 @@ use buffer::{IntoStream, StreamError, Stream}; /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{token, many, take}; -/// use chomp::buffer::{IntoStream, Stream}; -/// -/// let i = b"foofoo"; +/// use chomp::prelude::{token, many, take}; +/// use chomp::buffer::{SliceStream, Stream}; /// -/// let r = i.into_stream().parse(parser!{many(parser!{ +/// let r = SliceStream::new(b"foofoo").parse(parser!{many(parser!{ /// token(b'f'); /// take(2) /// })}); @@ -68,43 +63,40 @@ impl<'i, I: 'i> SliceStream<'i, I> { } } -impl<'a, 'i, I: 'i> IntoStream<'a, 'i> for &'i [I] { - type Item = I; - type Into = SliceStream<'i, I>; - - #[inline] - fn into_stream(self) -> SliceStream<'i, I> { - SliceStream::new(self) - } -} - -impl<'a, 'i, I: 'i> Stream<'a, 'i> for SliceStream<'i, I> { - type Item = I; +impl<'a, 'i, I: 'i + Copy + PartialEq> Stream<'a, 'i> for SliceStream<'i, I> { + type Input = InputBuf<'i, I>; #[inline] - fn parse(&'a mut self, f: F) -> Result> - where F: FnOnce(Input<'i, Self::Item>) -> ParseResult<'i, Self::Item, T, E>, + fn parse(&'a mut self, f: F) -> Result::Buffer, E>> + where F: FnOnce(Self::Input) -> ParseResult, T: 'i, E: 'i { + use primitives::Primitives; + if self.is_empty() { return Err(StreamError::EndOfInput); } - match f(input::new(input::END_OF_INPUT, &self.slice[self.pos..])).into_inner() { - State::Data(remainder, data) => { + match f(InputBuf::new(&self.slice[self.pos..])).into_inner() { + (remainder, Ok(data)) => { // TODO: Do something neater with the remainder - self.pos += self.len() - remainder.buffer().len(); + self.pos += self.len() - remainder.len(); Ok(data) }, - State::Error(remainder, err) => { - // TODO: Do something neater with the remainder - // TODO: Detail this behaviour, maybe make it configurable - self.pos += self.len() - remainder.len(); + (mut remainder, Err(err)) => { + if remainder.is_incomplete() { + Err(StreamError::Incomplete) + } else { + // TODO: Do something neater with the remainder + // TODO: Detail this behaviour, maybe make it configurable + let r = remainder.len(); + + self.pos += self.len() - r; - Err(StreamError::ParseError(remainder, err)) + Err(StreamError::ParseError(remainder.consume_remaining(), err)) + } }, - State::Incomplete(n) => Err(StreamError::Incomplete(n + self.len())), } } } diff --git a/src/buffer/stateful.rs b/src/buffer/stateful.rs index 86ae7e1b..0f80cf09 100644 --- a/src/buffer/stateful.rs +++ b/src/buffer/stateful.rs @@ -1,16 +1,15 @@ use std::io; -use std::cmp; -use {Input, ParseResult}; -use primitives::input; -use primitives::{InputBuffer, State, IntoInner}; +use types::{Input, ParseResult}; +use primitives::IntoInner; use buffer::{ Buffer, DataSource, FixedSizeBuffer, - StreamError, + InputBuf, Stream, + StreamError, }; use buffer::data_source::{IteratorDataSource, ReadDataSource}; @@ -56,7 +55,8 @@ impl> Source, B> { } } -impl> Source, B> { +impl> Source, B> + where I::Item: Copy + PartialEq { /// Creates a new `Source` from `Iterator` and `Buffer` instances. #[inline] pub fn from_iter(source: I, buffer: B) -> Self { @@ -92,7 +92,7 @@ impl> Source { while buffer.len() < request { match try!(buffer.fill(source)) { 0 => break, - n => read = read + n, + n => read += n, } } } @@ -103,13 +103,12 @@ impl> Source { /// Attempts to fill the buffer to satisfy the last call to `parse()`. #[inline] pub fn fill(&mut self) -> io::Result { - // Make sure we actually try to read something in case the buffer is empty - let req = cmp::max(1, self.request); + let req = self.buffer.len() + 1; self.fill_requested(req).map(|n| { self.state.remove(INCOMPLETE); - if self.buffer.len() >= req { + if n > 0 { self.state.remove(END_OF_INPUT); } else { self.state.insert(END_OF_INPUT); @@ -200,13 +199,15 @@ impl, B: Buffer> io::BufRead for Source { impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source where S::Item: 'a { - type Item = S::Item; + type Input = InputBuf<'a, S::Item>; #[inline] - fn parse(&'a mut self, f: F) -> Result> - where F: FnOnce(Input<'a, Self::Item>) -> ParseResult<'a, Self::Item, T, E>, + fn parse(&'a mut self, f: F) -> Result::Buffer, E>> + where F: FnOnce(Self::Input) -> ParseResult, T: 'a, E: 'a { + use primitives::Primitives; + if self.state.contains(INCOMPLETE | AUTOMATIC_FILL) { try!(self.fill().map_err(StreamError::IoError)); } @@ -215,31 +216,35 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source return Err(StreamError::EndOfInput); } - let input_state = if self.state.contains(END_OF_INPUT) { input::END_OF_INPUT } else { input::DEFAULT }; - - match f(input::new(input_state, &self.buffer)).into_inner() { - State::Data(remainder, data) => { - // TODO: Do something neater with the remainder - self.buffer.consume(self.buffer.len() - remainder.buffer().len()); - - Ok(data) - }, - State::Error(remainder, err) => { - // TODO: Do something neater with the remainder - // TODO: Detail this behaviour, maybe make it configurable - self.buffer.consume(self.buffer.len() - remainder.len()); - - Err(StreamError::ParseError(remainder, err)) - }, - State::Incomplete(n) => { - self.request = self.buffer.len() + n; - - if self.state.contains(END_OF_INPUT) { - Err(StreamError::Incomplete(self.request)) - } else { + match f(InputBuf::new(&self.buffer)).into_inner() { + (remainder, Ok(data)) => { + if remainder.is_incomplete() && !self.state.contains(END_OF_INPUT) { + // We can't accept this since we might have hit a premature end self.state.insert(INCOMPLETE); Err(StreamError::Retry) + } else { + // TODO: Do something neater with the remainder + self.buffer.consume(self.buffer.len() - remainder.len()); + + Ok(data) + } + }, + (mut remainder, Err(err)) => { + match (remainder.is_incomplete(), self.state.contains(END_OF_INPUT)) { + (true, true) => Err(StreamError::Incomplete), + (true, false) => { + self.state.insert(INCOMPLETE); + + Err(StreamError::Retry) + }, + _ => { + // TODO: Do something neater with the remainder + // TODO: Detail this behaviour, maybe make it configurable + self.buffer.consume(self.buffer.len() - remainder.len()); + + Err(StreamError::ParseError(remainder.consume_remaining(), err)) + } } }, } @@ -249,8 +254,14 @@ impl<'a, S: DataSource, B: Buffer> Stream<'a, 'a> for Source #[cfg(test)] mod test { use std::io; - use {any, take}; - use Error; + + use types::Input; + use parsers::{ + Error, + any, + take, + take_while, + }; use buffer::{ FixedSizeBuffer, StreamError, @@ -400,12 +411,47 @@ mod test { assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Retry)); assert_eq!(n, 2); assert_eq!(m, 1); - assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Incomplete(2))); + assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Retry)); assert_eq!(n, 3); assert_eq!(m, 1); - assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Incomplete(2))); + assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Incomplete)); assert_eq!(n, 4); assert_eq!(m, 1); + assert_eq!(b.parse(|i| { n += 1; take(i, 2).inspect(|_| m += 1) }), Err(StreamError::Incomplete)); + assert_eq!(n, 5); + assert_eq!(m, 1); + } + + #[test] + fn incomplete2() { + let mut o = 0; + let mut n = 0; // Times it has entered the parsing function + let mut m = 0; // Times it has managed to get past the request for data + let mut b = buf(&b"tes"[..], 2); + + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Ok(&b"t"[..])); + assert_eq!(n, 1); + assert_eq!(m, 1); + o = 0; + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Err(StreamError::Retry)); + assert_eq!(n, 2); + assert_eq!(m, 2); + o = 0; + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Ok(&b"e"[..])); + assert_eq!(n, 3); + assert_eq!(m, 3); + o = 0; + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Err(StreamError::Retry)); + assert_eq!(n, 4); + assert_eq!(m, 4); + o = 0; + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Ok(&b"s"[..])); + assert_eq!(n, 5); + assert_eq!(m, 5); + o = 0; + assert_eq!(b.parse(|i| { n += 1; take_while(i, |_| { o += 1; o < 2 }).inspect(|_| m += 1) }), Err(StreamError::EndOfInput)); + assert_eq!(n, 5); + assert_eq!(m, 5); } #[test] diff --git a/src/combinators/bounded.rs b/src/combinators/bounded.rs index 1416f409..18901b27 100644 --- a/src/combinators/bounded.rs +++ b/src/combinators/bounded.rs @@ -7,7 +7,8 @@ //! //! ``` //! use chomp::combinators::bounded::many; -//! use chomp::{parse_only, any}; +//! use chomp::parse_only; +//! use chomp::parsers::any; //! //! // Read any character 2 or 3 times //! let r: Result, _> = parse_only(|i| many(i, 2..4, any), b"abcd"); @@ -25,11 +26,13 @@ use std::ops::{ }; use std::cmp::max; -use {Input, ParseResult}; -use primitives::{InputClone, InputBuffer, IntoInner, State}; +use types::{Input, ParseResult}; +use primitives::{Primitives, IntoInner}; /// Trait for applying a parser multiple times based on a range. pub trait BoundedRange { + // TODO: Update documentation regarding input state. Incomplete will point to the last + // successful parsed data. mark a backtrack point to be able to restart parsing. /// Applies the parser `F` multiple times until it fails or the maximum value of the range has /// been reached, collecting the successful values into a `T: FromIterator`. /// @@ -47,10 +50,8 @@ pub trait BoundedRange { /// * If the last parser succeeds on the last input item then this parser is still considered /// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. #[inline] - fn parse_many<'a, I, T, E, F, U>(self, Input<'a, I>, F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, I, F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator; /// Applies the parser `F` multiple times until it fails or the maximum value of the range has @@ -69,10 +70,10 @@ pub trait BoundedRange { /// * If the last parser succeeds on the last input item then this parser is still considered /// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. #[inline] - fn skip_many<'a, I, T, E, F>(self, Input<'a, I>, F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E>; + fn skip_many(self, I, F) -> ParseResult + where F: FnMut(I) -> ParseResult; + // TODO: Fix documentation regarding incomplete /// Applies the parser `P` multiple times until the parser `F` succeeds and returns a value /// populated by the values yielded by `P`. Consumes the matched part of `F`. If `F` does not /// succeed within the given range `R` this combinator will propagate any failure from `P`. @@ -89,22 +90,17 @@ pub trait BoundedRange { /// * If the last parser succeeds on the last input item then this combinator is still considered /// incomplete unless the parser `F` matches or the lower bound has not been met. #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N>; + fn many_till(self, I, R, F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult; } impl BoundedRange for Range { #[inline] - fn parse_many<'a, I, T, E, F, U>(self, i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { // Range does not perform this assertion assert!(self.start <= self.end); @@ -113,7 +109,7 @@ impl BoundedRange for Range { input: i, parser: f, // Range is closed on left side, open on right, ie. [self.start, self.end) - state: (usize, usize): (self.start, max(self.end, 1) - 1), + state: (usize, usize): (self.start, max(self.start, self.end.saturating_sub(1))), size_hint(self) { (self.data.0, Some(self.data.1)) @@ -126,64 +122,59 @@ impl BoundedRange for Range { } } on { - self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + self.data.0 = self.data.0.saturating_sub(1); + // Can't overflow unless we do not quit when self.data.1 == 0 self.data.1 -= 1; } } => result : T { // Got all occurrences of the parser - (s, (0, 0), _) => s.ret(result), + // First state or reached max => do not restore to mark since it is from last + // iteration + (s, (0, 0), _, _) => s.ret(result), // Ok, last parser failed and we have reached minimum, we have iterated all. // Return remainder of buffer and the collected result - (s, (0, _), EndState::Error(_, _)) => s.ret(result), - // Nested parser incomplete but reached at least minimum, propagate if not at end - (s, (0, _), EndState::Incomplete(n)) => if s.is_last_slice() { - s.ret(result) - } else { - s.incomplete(n) - }, + (s, (0, _), m, Some(_)) => s.restore(m).ret(result), // Did not reach minimum, propagate - (s, (_, _), EndState::Error(b, e)) => s.replace(b).err(e), - (s, (_, _), EndState::Incomplete(n)) => s.incomplete(n) + (s, (_, _), _, Some(e)) => s.err(e), + (_, _, _, None) => unreachable!(), } } } #[inline] - fn skip_many<'a, I, T, E, F>(self, mut i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + fn skip_many(self, mut i: I, mut f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { // Range does not perform this assertion assert!(self.start <= self.end); // Closed on left side, open on right - let (mut min, mut max) = (self.start, max(self.end, 1) - 1); + let (mut min, mut max) = (self.start, max(self.start, self.end.saturating_sub(1))); loop { if max == 0 { break; } - match f(i.clone()).into_inner() { - State::Data(b, _) => { - min = if min == 0 { 0 } else { min - 1 }; + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(_)) => { + min = min.saturating_sub(1); + // Can't overflow unless we do not quit when max == 0 max -= 1; i = b }, - State::Error(b, e) => if min == 0 { + (b, Err(e)) => if min == 0 { + i = b.restore(m); + break; } else { - // Not enough iterations - return i.replace(b).err(e); + // Not enough iterations, propagate + return b.err(e); }, - State::Incomplete(n) => if min == 0 && i.is_last_slice() { - break; - } else { - // We have not done the minimum amount of iterations - return i.incomplete(n); - } } } @@ -191,14 +182,11 @@ impl BoundedRange for Range { } #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + fn many_till(self, i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { // Range does not perform this assertion assert!(self.start <= self.end); @@ -207,7 +195,7 @@ impl BoundedRange for Range { parser: p, end: end, // Range is closed on left side, open on right, ie. [self.start, self.end) - state: (usize, usize): (self.start, max(self.end, 1) - 1), + state: (usize, usize): (self.start, max(self.start, self.end.saturating_sub(1))), size_hint(self) { (self.data.0, Some(self.data.1)) @@ -217,19 +205,34 @@ impl BoundedRange for Range { pre { if self.data.0 == 0 { // We have reached minimum, we can attempt to end now - iter_till_end_test!(self); - } - - // Maximum reached, stop iteration and check error state - if self.data.1 == 0 { - // Attempt to make a successful end - iter_till_end_test!(self); - return None; + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + let m = i.mark(); + + match (self.data.1, (self.end)(i).into_inner()) { + // We can always end + (_, (b, Ok(_))) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + + return None + }, + // We have reached end, end must match or it is an error + (0, (b, Err(e))) => { + self.buf = Some(b); + self.state = EndStateTill::Error(From::from(e)); + + return None; + }, + // Failed to end, restore and continue since we can parse more + (_, (b, Err(_))) => self.buf = Some(b.restore(m)), + } } } on { - self.data.0 = if self.data.0 == 0 { 0 } else { self.data.0 - 1 }; + self.data.0 = self.data.0.saturating_sub(1); + // Can't overflow unless we do not quit when self.data.1 == 0 self.data.1 -= 1; } } @@ -238,8 +241,8 @@ impl BoundedRange for Range { // Got all occurrences of the parser (s, (0, _), EndStateTill::EndSuccess) => s.ret(result), // Did not reach minimum or a failure, propagate - (s, (_, _), EndStateTill::Error(b, e)) => s.replace(b).err(e), - (s, (_, _), EndStateTill::Incomplete(n)) => s.incomplete(n), + (s, (_, _), EndStateTill::Error(e)) => s.err(e), + (_, (_, _), EndStateTill::Incomplete) => unreachable!(), // We cannot reach this since we only run the end test once we have reached the // minimum number of matches (_, (_, _), EndStateTill::EndSuccess) => unreachable!() @@ -250,10 +253,8 @@ impl BoundedRange for Range { impl BoundedRange for RangeFrom { #[inline] - fn parse_many<'a, I, T, E, F, U>(self, i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { run_iter!{ input: i, @@ -268,52 +269,43 @@ impl BoundedRange for RangeFrom { next(self) { pre {} on { - self.data = if self.data == 0 { 0 } else { self.data - 1 }; + self.data = self.data.saturating_sub(1); } } => result : T { // We got at least n items - (s, 0, EndState::Error(_, _)) => s.ret(result), - // Nested parser incomplete, propagate if not at end - (s, 0, EndState::Incomplete(n)) => if s.is_last_slice() { - s.ret(result) - } else { - s.incomplete(n) - }, + (s, 0, m, Some(_)) => s.restore(m).ret(result), // Items still remaining, propagate - (s, _, EndState::Error(b, e)) => s.replace(b).err(e), - (s, _, EndState::Incomplete(n)) => s.incomplete(n) + (s, _, _, Some(e)) => s.err(e), + (_, _, _, None) => unreachable!(), } } } #[inline] - fn skip_many<'a, I, T, E, F>(self, mut i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + fn skip_many(self, mut i: I, mut f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { // Closed on left side, open on right let mut min = self.start; loop { - match f(i.clone()).into_inner() { - State::Data(b, _) => { - min = if min == 0 { 0 } else { min - 1 }; + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(_)) => { + min = min.saturating_sub(1); i = b }, - State::Error(b, e) => if min == 0 { + (b, Err(e)) => if min == 0 { + i = b.restore(m); + break; } else { - // Not enough iterations - return i.replace(b).err(e); + // Not enough iterations, propagate + return b.err(e); }, - State::Incomplete(n) => if min == 0 && i.is_last_slice() { - break; - } else { - // We have not done the minimum amount of iterations - return i.incomplete(n); - } } } @@ -321,14 +313,11 @@ impl BoundedRange for RangeFrom { } #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + fn many_till(self, i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { run_iter_till!{ input: i, parser: p, @@ -348,19 +337,19 @@ impl BoundedRange for RangeFrom { } } on { - self.data = if self.data == 0 { 0 } else { self.data - 1 }; + self.data = self.data.saturating_sub(1); } } => result : T { // Got all occurrences of the parser - (s, 0, EndStateTill::EndSuccess) => s.ret(result), + (s, 0, EndStateTill::EndSuccess) => s.ret(result), // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(b, e)) => s.replace(b).err(e), - (s, _, EndStateTill::Incomplete(n)) => s.incomplete(n), + (s, _, EndStateTill::Error(e)) => s.err(e), + (_, _, EndStateTill::Incomplete) => unreachable!(), // We cannot reach this since we only run the end test once we have reached the // minimum number of matches - (_, _, EndStateTill::EndSuccess) => unreachable!() + (_, _, EndStateTill::EndSuccess) => unreachable!() } } } @@ -368,10 +357,8 @@ impl BoundedRange for RangeFrom { impl BoundedRange for RangeFull { #[inline] - fn parse_many<'a, I, T, E, F, U>(self, i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { run_iter!{ input: i, @@ -388,30 +375,25 @@ impl BoundedRange for RangeFull { } => result : T { - (s, (), EndState::Error(_, _)) => s.ret(result), - // Nested parser incomplete, propagate if not at end - (s, (), EndState::Incomplete(n)) => if s.is_last_slice() { - s.ret(result) - } else { - s.incomplete(n) - } + (s, (), m, Some(_)) => s.restore(m).ret(result), + (_, _, _, None) => unreachable!(), } } } #[inline] - fn skip_many<'a, I, T, E, F>(self, mut i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + fn skip_many(self, mut i: I, mut f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { loop { - match f(i.clone()).into_inner() { - State::Data(b, _) => i = b, - State::Error(_, _) => break, - State::Incomplete(n) => if i.is_last_slice() { + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(_)) => i = b, + (b, Err(_)) => { + i = b.restore(m); + break; - } else { - return i.incomplete(n); - } + }, } } @@ -419,14 +401,11 @@ impl BoundedRange for RangeFull { } #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + fn many_till(self, i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { run_iter_till!{ input: i, parser: p, @@ -447,9 +426,9 @@ impl BoundedRange for RangeFull { => result : T { (s, (), EndStateTill::EndSuccess) => s.ret(result), - (s, (), EndStateTill::Error(b, e)) => s.replace(b).err(e), + (s, (), EndStateTill::Error(e)) => s.err(e), // Nested parser incomplete, propagate if not at end - (s, (), EndStateTill::Incomplete(n)) => s.incomplete(n) + (_, (), EndStateTill::Incomplete) => unreachable!() } } } @@ -457,10 +436,8 @@ impl BoundedRange for RangeFull { impl BoundedRange for RangeTo { #[inline] - fn parse_many<'a, I, T, E, F, U>(self, i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { run_iter!{ input: i, @@ -484,24 +461,19 @@ impl BoundedRange for RangeTo { } => result : T { - // Either error or incomplete after the end - (s, 0, _) => s.ret(result), + // First state or reached max => do not restore to mark since it is from last + // iteration + (s, 0, _, _) => s.ret(result), // Inside of range, never outside - (s, _, EndState::Error(_, _)) => s.ret(result), - // Nested parser incomplete, propagate if not at end - (s, _, EndState::Incomplete(n)) => if s.is_last_slice() { - s.ret(result) - } else { - s.incomplete(n) - } + (s, _, m, Some(_)) => s.restore(m).ret(result), + (_, _, _, None) => unreachable!(), } } } #[inline] - fn skip_many<'a, I, T, E, F>(self, mut i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + fn skip_many(self, mut i: I, mut f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { // [0, n) let mut max = max(self.end, 1) - 1; @@ -510,19 +482,20 @@ impl BoundedRange for RangeTo { break; } - match f(i.clone()).into_inner() { - State::Data(b, _) => { + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(_)) => { max -= 1; i = b }, // Always ok to end iteration - State::Error(_, _) => break, - State::Incomplete(n) => if i.is_last_slice() { + (b, Err(_)) => { + i = b.restore(m); + break; - } else { - return i.incomplete(n); - } + }, } } @@ -530,14 +503,11 @@ impl BoundedRange for RangeTo { } #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + fn many_till(self, i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { run_iter_till!{ input: i, parser: p, @@ -551,12 +521,27 @@ impl BoundedRange for RangeTo { next(self) { pre { - // Can end at any time - iter_till_end_test!(self); - - // Maximum reached, stop iteration and check error state - if self.data == 0 { - return None; + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + let m = i.mark(); + + match (self.data, (self.end)(i).into_inner()) { + // We can always end + (_, (b, Ok(_))) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + + return None + }, + // We have reached end, end must match or it is an error + (0, (b, Err(e))) => { + self.buf = Some(b); + self.state = EndStateTill::Error(From::from(e)); + + return None; + }, + // Failed to end, restore and continue since we can parse more + (_, (b, Err(_))) => self.buf = Some(b.restore(m)), } } on { @@ -565,25 +550,21 @@ impl BoundedRange for RangeTo { } => result : T { - // Got all occurrences of the parser - (s, 0, EndStateTill::EndSuccess) => s.ret(result), + // Got all occurrences of the parser since we have no minimum bound + (s, _, EndStateTill::EndSuccess) => s.ret(result), // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(b, e)) => s.replace(b).err(e), - (s, _, EndStateTill::Incomplete(n)) => s.incomplete(n), - // We cannot reach this since we only run the end test once we have reached the - // minimum number of matches - (_, _, EndStateTill::EndSuccess) => unreachable!() + (s, _, EndStateTill::Error(e)) => s.err(e), + (_, _, EndStateTill::Incomplete) => unreachable!(), } } } } impl BoundedRange for usize { + // TODO: Any way to avoid marking for backtracking here? #[inline] - fn parse_many<'a, I, T, E, F, U>(self, i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, + fn parse_many(self, i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { run_iter!{ input: i, @@ -608,19 +589,17 @@ impl BoundedRange for usize { => result : T { // Got exact - (s, 0, _) => s.ret(result), + (s, 0, _, _) => s.ret(result), // We have got too few items, propagate error - (s, _, EndState::Error(b, e)) => s.replace(b).err(e), - // Nested parser incomplete, propagate - (s, _, EndState::Incomplete(n)) => s.incomplete(n) + (s, _, _, Some(e)) => s.err(e), + (_, _, _, None) => unreachable!(), } } } #[inline] - fn skip_many<'a, I, T, E, F>(self, mut i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + fn skip_many(self, mut i: I, mut f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { let mut n = self; loop { @@ -628,23 +607,18 @@ impl BoundedRange for usize { break; } - match f(i.clone()).into_inner() { - State::Data(b, _) => { + match f(i).into_inner() { + (b, Ok(_)) => { n -= 1; i = b }, - State::Error(b, e) => if n == 0 { - break; + (b, Err(e)) => if n == 0 { + unreachable!(); } else { - // Not enough iterations - return i.replace(b).err(e); + // Not enough iterations, propagate + return b.err(e); }, - State::Incomplete(n) => if n == 0 { - break; - } else { - return i.incomplete(n); - } } } @@ -652,14 +626,11 @@ impl BoundedRange for usize { } #[inline] - fn many_till<'a, I, T, E, R, F, U, N, V>(self, i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + fn many_till(self, i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { run_iter_till!{ input: i, parser: p, @@ -673,8 +644,20 @@ impl BoundedRange for usize { next(self) { pre { if self.data == 0 { - // Attempt to make a successful end - iter_till_end_test!(self); + // TODO: Remove the branches here (ie. take + unwrap) + let i = self.buf.take().expect("Iter.buf was None"); + + match (self.end)(i).into_inner() { + (b, Ok(_)) => { + self.buf = Some(b); + self.state = EndStateTill::EndSuccess; + }, + // Failed to end, restore and continue + (b, Err(e)) => { + self.buf = Some(b); + self.state = EndStateTill::Error(From::from(e)); + }, + } return None; } @@ -688,8 +671,8 @@ impl BoundedRange for usize { // Got all occurrences of the parser (s, 0, EndStateTill::EndSuccess) => s.ret(result), // Did not reach minimum or a failure, propagate - (s, _, EndStateTill::Error(b, e)) => s.replace(b).err(e), - (s, _, EndStateTill::Incomplete(n)) => s.incomplete(n), + (s, _, EndStateTill::Error(e)) => s.err(e), + (_, _, EndStateTill::Incomplete) => unreachable!(), // We cannot reach this since we only run the end test once we have reached the // minimum number of matches (_, _, EndStateTill::EndSuccess) => unreachable!() @@ -711,14 +694,10 @@ impl BoundedRange for usize { /// /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. -/// * If the last parser succeeds on the last input item then this parser is still considered -/// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. #[inline] -pub fn many<'a, I, T, E, F, U, R>(i: Input<'a, I>, r: R, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - R: BoundedRange, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, +pub fn many(i: I, r: R, f: F) -> ParseResult + where R: BoundedRange, + F: FnMut(I) -> ParseResult, T: FromIterator { BoundedRange::parse_many(r, i, f) } @@ -735,16 +714,14 @@ pub fn many<'a, I, T, E, F, U, R>(i: Input<'a, I>, r: R, f: F) -> ParseResult<'a /// # Notes /// /// * Will never yield more items than the upper bound of the range. -/// * If the last parser succeeds on the last input item then this parser is still considered -/// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. #[inline] -pub fn skip_many<'a, I, T, E, F, R>(i: Input<'a, I>, r: R, f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - R: BoundedRange, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { +pub fn skip_many(i: I, r: R, f: F) -> ParseResult + where R: BoundedRange, + F: FnMut(I) -> ParseResult { BoundedRange::skip_many(r, i, f) } +// TODO: Update documentation regarding incomplete behaviour /// Applies the parser `P` multiple times until the parser `F` succeeds and returns a value /// populated by the values yielded by `P`. Consumes the matched part of `F`. If `F` does not /// succeed within the given range `R` this combinator will propagate any failure from `P`. @@ -757,18 +734,13 @@ pub fn skip_many<'a, I, T, E, F, R>(i: Input<'a, I>, r: R, f: F) -> ParseResult< /// /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. -/// * If the last parser succeeds on the last input item then this combinator is still considered -/// incomplete unless the parser `F` matches or the lower bound has not been met. #[inline] -pub fn many_till<'a, I, T, E, R, F, U, N, P, V>(i: Input<'a, I>, r: R, p: P, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - R: BoundedRange, +pub fn many_till(i: I, r: R, p: P, end: F) -> ParseResult + where R: BoundedRange, T: FromIterator, - P: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + E: From, + P: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { BoundedRange::many_till(r, i, p, end) } @@ -785,19 +757,13 @@ pub fn many_till<'a, I, T, E, R, F, U, N, P, V>(i: Input<'a, I>, r: R, p: P, end /// /// * Will allocate depending on the `FromIterator` implementation. /// * Will never yield more items than the upper bound of the range. -/// * If the last parser succeeds on the last input item then this combinator is still considered -/// incomplete unless the parser `F` matches or the lower bound has not been met. #[inline] -pub fn sep_by<'a, I, T, E, R, F, U, N, P, V>(i: Input<'a, I>, r: R, mut p: P, mut sep: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, +pub fn sep_by(i: I, r: R, mut p: P, mut sep: F) -> ParseResult + where T: FromIterator, E: From, R: BoundedRange, - P: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + P: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { // If we have parsed at least one item let mut item = false; // Add sep in front of p if we have read at least one item @@ -814,10 +780,9 @@ pub fn sep_by<'a, I, T, E, R, F, U, N, P, V>(i: Input<'a, I>, r: R, mut p: P, mu #[cfg(test)] mod test { - use ParseResult; - use parsers::{any, token}; - use primitives::input::*; - use primitives::{IntoInner, State}; + use types::ParseResult; + use parsers::{Error, any, token, string}; + use primitives::IntoInner; use super::{ many, @@ -827,471 +792,319 @@ mod test { #[test] fn many_range_full() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"b"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"ab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"b"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"ab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], .., any); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + + // Test where we error inside of the inner parser + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aba"[..], .., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..]]))); } #[test] fn many_range_to() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"b"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"ab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"b"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"ab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), vec![b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); + + // Test where we error inside of the inner parser + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aba"[..], ..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..]]))); } #[test] fn many_range_from() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaa"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"b"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"ab"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), 2.., any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), 2.., any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), 2.., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaa"), 2.., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"b"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"ab"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a', b'a']))); + + let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); + + // Test where we error inside of the inner parser + let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2.., |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } #[test] fn many_range() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![b'a', b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaaa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![b'a', b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"b"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"ab"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), vec![b'a', b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), 2..4, any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), 2..4, any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaaa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![b'a', b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"b"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"ab"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), vec![b'a', b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); + + let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); + + // Test where we error inside of the inner parser + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 1..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 1..3, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); } #[test] fn many_exact() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b""), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"a"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"b"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"ab"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![b'a', b'a'])); - - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"b"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"ab"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); - let r: ParseResult<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aaab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), vec![b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"aa"[..], Ok(vec![]))); + + let r: ParseResult<_, Vec<_>, _> = many(&b""[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"a"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![b'a', b'a']))); + + let r: ParseResult<_, Vec<_>, _> = many(&b"b"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(vec![b'a', b'a']))); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a']))); + + // Test where we error inside of the inner parser + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"abac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababac"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"ac"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many(&b"ababa"[..], 2, |i| string(i, b"ab")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + } + + #[test] + fn many_till_range_full() { + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], .., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + } + + #[test] + fn many_till_range_from() { + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 1.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 1.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], 2.., |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + } + + #[test] + fn many_till_range_to() { + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"b"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], ..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], ..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ba"[..], Err(Error::expected(b'c')))); + } + + #[test] + fn many_till_range() { + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"cd")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abc"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'a')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababa"[..], 0..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ba"[..], Err(Error::expected(b'c')))); + + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..], 1..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 1..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..], 2..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b')))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2..3, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..], 2..2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]]))); + } + + #[test] + fn many_till_exact() { + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![])) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"aca"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"a"[..], Ok(vec![])) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"acab"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![])) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 0, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c'))) ); + + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"aba"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abab"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 1, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..]])) ); + + let r: ParseResult<_, Vec<_>, _> = many_till(&b""[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"a"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"aba"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"c"[..], Err(Error::expected(b'b'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababa"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababac"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b""[..], Ok(vec![&b"ab"[..], &b"ab"[..]])) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"ababab"[..] , 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'c'))) ); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abababac"[..], 2, |i| string(i, b"ab"), |i| string(i, b"ac")); assert_eq!(r.into_inner(), (&b"bac"[..], Err(Error::expected(b'c'))) ); } #[test] fn skip_range_full() { - let r = skip_many(new(DEFAULT, b""), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"a"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aa"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - - let r = skip_many(new(DEFAULT, b"b"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"ab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"aab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - - let r = skip_many(new(END_OF_INPUT, b""), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aa"), .., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - - let r = skip_many(new(END_OF_INPUT, b"b"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"ab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aab"), .., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); + let r = skip_many(&b""[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"a"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aa"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + + let r = skip_many(&b"b"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"ab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aab"[..], .., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); } #[test] fn skip_range_to() { - let r = skip_many(new(DEFAULT, b""), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"a"), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - let r = skip_many(new(END_OF_INPUT, b""), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), ..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b""), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"a"), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - let r = skip_many(new(END_OF_INPUT, b""), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), ..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b""), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"a"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"aaa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b"b"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"ab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"aab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - - let r = skip_many(new(END_OF_INPUT, b""), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aa"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - - let r = skip_many(new(END_OF_INPUT, b"b"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"ab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aaab"), ..3, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), ())); + let r = skip_many(&b""[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"b"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"a"[..], ..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + + let r = skip_many(&b""[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"a"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaa"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + + let r = skip_many(&b"b"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"ab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aaab"[..], ..3, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); } #[test] fn skip_range_from() { - let r = skip_many(new(DEFAULT, b""), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"a"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aa"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aaa"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - - let r = skip_many(new(DEFAULT, b"b"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"ab"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"aab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - - let r = skip_many(new(END_OF_INPUT, b""), 2.., any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"a"), 2.., any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"aa"), 2.., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aaa"), 2.., any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - - let r = skip_many(new(END_OF_INPUT, b"b"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"ab"), 2.., |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"aab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aaab"), 2.., |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); + let r = skip_many(&b""[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"a"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aa"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + + let r = skip_many(&b""[..], 1.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 0.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + + let r = skip_many(&b""[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaa"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + + let r = skip_many(&b"b"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"ab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aaab"[..], 2.., |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); } #[test] fn skip_range() { - let r = skip_many(new(DEFAULT, b""), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"a"), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - let r = skip_many(new(END_OF_INPUT, b""), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), 0..0, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b""), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"a"), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - let r = skip_many(new(END_OF_INPUT, b""), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"a"), 0..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b""), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"a"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aaa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"aaaa"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b"b"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"ab"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"aab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"aaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"aaaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), ())); - - let r = skip_many(new(END_OF_INPUT, b""), 2..4, any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"a"), 2..4, any); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"aa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aaa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aaaa"), 2..4, any); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(END_OF_INPUT, b"b"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"ab"), 2..4, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"aab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aaaab"), 2..4, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), ())); + let r = skip_many(&b""[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"a"[..], 0..0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + + let r = skip_many(&b""[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaa"[..], 2..2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + + let r = skip_many(&b""[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaaa"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + + let r = skip_many(&b"b"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"ab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"aaaab"[..], 2..4, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); } #[test] fn skip_exact() { - let r = skip_many(new(DEFAULT, b""), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"a"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(DEFAULT, b"aa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b""), ())); - let r = skip_many(new(DEFAULT, b"aaa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"a"), ())); - - let r = skip_many(new(DEFAULT, b"b"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"ab"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(DEFAULT, b"aab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"b"), ())); - let r = skip_many(new(DEFAULT, b"aaab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), ())); - - let r = skip_many(new(END_OF_INPUT, b""), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"a"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Incomplete(1)); - let r = skip_many(new(END_OF_INPUT, b"aa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), ())); - let r = skip_many(new(END_OF_INPUT, b"aaa"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"a"), ())); - - let r = skip_many(new(END_OF_INPUT, b"b"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"ab"), 2, |i| token(i, b'a').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "token_err")); - let r = skip_many(new(END_OF_INPUT, b"aab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"b"), ())); - let r = skip_many(new(END_OF_INPUT, b"aaab"), 2, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b"ab"), ())); + let r = skip_many(&b""[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"a"[..], 0, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + let r = skip_many(&b""[..], 1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 1, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b""[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"a"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"aa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b""[..], Ok(()))); + let r = skip_many(&b"aaa"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"a"[..], Ok(()))); + let r = skip_many(&b"aaab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"ab"[..], Ok(()))); + let r = skip_many(&b"aab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Ok(()))); + let r = skip_many(&b"ab"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + let r = skip_many(&b"b"[..], 2, |i| token(i, b'a')); assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); } #[test] #[should_panic] fn panic_many_range_lt() { - let r: ParseResult<_, Vec<_>, _> = many(new(DEFAULT, b"aaaab"), 2..1, |i| token(i, b'a')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), vec![b'a', b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many(&b"aaaab"[..], 2..1, |i| token(i, b'a')); + assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] #[should_panic] fn panic_skip_many_range_lt() { - assert_eq!(skip_many(new(DEFAULT, b"aaaab"), 2..1, |i| token(i, b'a')).into_inner(), State::Data(new(DEFAULT, b"ab"), ())); + assert_eq!(skip_many(&b"aaaab"[..], 2..1, |i| token(i, b'a')).into_inner(), (&b"ab"[..], Ok(()))); } #[test] #[should_panic] fn panic_many_till_range_lt() { - let r: ParseResult<_, Vec<_>, _> = many_till(new(DEFAULT, b"aaaab"), 2..1, |i| token(i, b'a'), |i| token(i, b'b')); - assert_eq!(r.into_inner(), State::Data(new(DEFAULT, b"ab"), vec![b'a', b'a', b'a'])); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"aaaab"[..], 2..1, |i| token(i, b'a'), |i| token(i, b'b')); + assert_eq!(r.into_inner(), (&b"ab"[..], Ok(vec![b'a', b'a', b'a']))); } } diff --git a/src/combinators/macros.rs b/src/combinators/macros.rs index b7462ed0..11c2722f 100644 --- a/src/combinators/macros.rs +++ b/src/combinators/macros.rs @@ -14,47 +14,39 @@ macro_rules! run_iter { } => $result:ident : $t:ty { - $($pat:pat => $arm:expr),* + $($pat:pat => $arm:expr),*$(,)* } ) => { { - enum EndState<'a, I, E> - where I: 'a { - Error(&'a [I], E), - Incomplete(usize), - } - - struct Iter<'a, I, T, E, F> - where I: 'a, - T: 'a, - E: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + struct Iter + where F: FnMut(I) -> ParseResult { /// Last state of the parser - state: EndState<'a, I, E>, + state: Option, /// Parser to execute once for each iteration parser: F, /// Remaining buffer - buf: Input<'a, I>, + /// + /// Wrapped in option to prevent two calls to destructors. + buf: Option, + /// Last good state. + /// + /// Wrapped in option to prevent two calls to destructors. + mark: I::Marker, /// Nested state data: $data_ty, _t: PhantomData, } - impl<'a, I, T, E, F> Iter<'a, I, T, E, F> - where I: 'a, - T: 'a, - E: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + impl Iter + where F: FnMut(I) -> ParseResult { #[inline] - fn end_state(self) -> (Input<'a, I>, $data_ty, EndState<'a, I, E>) { - (self.buf, self.data, self.state) + fn end_state(self) -> (I, $data_ty, I::Marker, Option) { + // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) + (self.buf.expect("Iter.buf was None"), self.data, self.mark, self.state) } } - impl<'a, I, T, E, F> Iterator for Iter<'a, I, T, E, F> - where I: 'a, - T: 'a, - E: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { + impl Iterator for Iter + where F: FnMut(I) -> ParseResult { type Item = T; #[inline] @@ -66,21 +58,23 @@ macro_rules! run_iter { fn next(&mut $next_self) -> Option { $pre_next - match ($next_self.parser)($next_self.buf.clone()).into_inner() { - State::Data(b, v) => { - $next_self.buf = b; + // TODO: Remove the branches here (ie. take + unwrap) + let i = $next_self.buf.take().expect("Iter.buf was None"); + + // TODO: Any way to prevent marking here since it is not used at all times? + $next_self.mark = i.mark(); + + match ($next_self.parser)(i).into_inner() { + (b, Ok(v)) => { + $next_self.buf = Some(b); $on_next Some(v) }, - State::Error(b, e) => { - $next_self.state = EndState::Error(b, e); - - None - }, - State::Incomplete(n) => { - $next_self.state = EndState::Incomplete(n); + (b, Err(e)) => { + $next_self.buf = Some(b); + $next_self.state = Some(e); None }, @@ -88,10 +82,14 @@ macro_rules! run_iter { } } + // TODO: Not always used + let mark = $input.mark(); + let mut iter = Iter { - state: EndState::Incomplete(1), + state: None, parser: $parser, - buf: $input, + buf: Some($input), + mark: mark, data: $data, _t: PhantomData, }; @@ -120,57 +118,45 @@ macro_rules! run_iter_till { } => $result:ident : $t:ty { - $($pat:pat => $arm:expr),* + $($pat:pat => $arm:expr),*$(,)* } ) => { { - enum EndStateTill<'a, I, E> - where I: 'a { - Error(&'a [I], E), - Incomplete(usize), + enum EndStateTill { + Error(E), + Incomplete, EndSuccess, } - /// Iterator used by ``many_till`` and ``many1``. - struct IterTill<'a, I, T, U, E, F, P, N> - where I: 'a, - T: 'a, - E: 'a, - U: 'a, - N: 'a, - P: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, N> { - state: EndStateTill<'a, I, E>, + /// Iterator used by `many_till` and `many1`. + struct IterTill + where E: From, + P: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { + state: EndStateTill, parser: P, end: F, - buf: Input<'a, I>, + buf: Option, data: $data_ty, _t: PhantomData<(T, U, N)>, } - impl<'a, I, T, U, E, F, P, N> IterTill<'a, I, T, U, E, F, P, N> - where I: 'a, - T: 'a, - E: 'a, - U: 'a, - N: 'a, - P: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, N> { + impl IterTill + where E: From, + P: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { /// Destructures the iterator returning the position just after the last successful parse as /// well as the state of the last attempt to parse data. #[inline] - fn end_state(self) -> (Input<'a, I>, $data_ty, EndStateTill<'a, I, E>) { - (self.buf, self.data, self.state) + fn end_state(self) -> (I, $data_ty, EndStateTill) { + // TODO: Avoid branch, check if this can be guaranteed to always be Some(T) + (self.buf.expect("Iter.buf was None"), self.data, self.state) } } - impl<'a, I, T, U, E, F, P, N> Iterator for IterTill<'a, I, T, U, E, F, P, N> - where I: 'a, - T: 'a, - E: 'a, - U: 'a, - N: 'a, - P: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, N> { + impl Iterator for IterTill + where E: From, + P: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { type Item = T; #[inline] @@ -182,21 +168,20 @@ macro_rules! run_iter_till { fn next(&mut $next_self) -> Option { $pre_next - match ($next_self.parser)($next_self.buf.clone()).into_inner() { - State::Data(b, v) => { - $next_self.buf = b; + // TODO: Remove the branches here (ie. take + unwrap) + let i = $next_self.buf.take().expect("Iter.buf was None"); + + match ($next_self.parser)(i).into_inner() { + (b, Ok(v)) => { + $next_self.buf = Some(b); $on_next Some(v) }, - State::Error(b, e) => { - $next_self.state = EndStateTill::Error(b, e); - - None - }, - State::Incomplete(n) => { - $next_self.state = EndStateTill::Incomplete(n); + (b, Err(e)) => { + $next_self.buf = Some(b); + $next_self.state = EndStateTill::Error(e); None }, @@ -205,10 +190,10 @@ macro_rules! run_iter_till { } let mut iter = IterTill { - state: EndStateTill::Incomplete(1), + state: EndStateTill::Incomplete, parser: $parser, end: $end, - buf: $input, + buf: Some($input), data: $data, _t: PhantomData, }; @@ -226,11 +211,19 @@ macro_rules! run_iter_till { /// will be returned, stopping the iteration. If the test fails execution continues. macro_rules! iter_till_end_test { ( $the_self:ident ) => { { - if let State::Data(b, _) = ($the_self.end)($the_self.buf.clone()).into_inner() { - $the_self.buf = b; - $the_self.state = EndStateTill::EndSuccess; - - return None + // TODO: Remove the branches here (ie. take + unwrap) + let i = $the_self.buf.take().expect("Iter.buf was None"); + let m = i.mark(); + + match ($the_self.end)(i).into_inner() { + (b, Ok(_)) => { + $the_self.buf = Some(b); + $the_self.state = EndStateTill::EndSuccess; + + return None + }, + // Failed to end, restore and continue + (b, Err(_)) => $the_self.buf = Some(b.restore(m)), } } } } diff --git a/src/combinators/mod.rs b/src/combinators/mod.rs index c716c9e5..6f52ccbf 100644 --- a/src/combinators/mod.rs +++ b/src/combinators/mod.rs @@ -7,21 +7,26 @@ pub mod bounded; use std::iter::FromIterator; -use {ParseResult, Input}; +use types::{ + ParseResult, + Input, +}; -use primitives::State; -use primitives::{IntoInner, InputBuffer, InputClone}; +use primitives::{ + IntoInner, + Primitives, +}; -/// Applies the parser ``p`` exactly ``num`` times collecting all items into `T: FromIterator`. +/// Applies the parser `p` exactly `num` times collecting all items into `T: FromIterator`. /// /// ``` -/// use chomp::{U8Result, ParseError, Error, Input, parse_only, count, token, take_remainder}; +/// use chomp::prelude::*; /// -/// fn parse(i: Input) -> U8Result> { +/// fn parse(i: I) -> SimpleResult> { /// count(i, 2, |i| token(i, b'a')) /// } /// -/// assert_eq!(parse_only(parse, b"a "), Err(ParseError::Error(b" ", Error::expected(b'a')))); +/// assert_eq!(parse_only(parse, b"a "), Err((&b" "[..], Error::expected(b'a')))); /// assert_eq!(parse_only(parse, b"aa "), Ok(vec![b'a', b'a'])); /// /// let with_remainder = |i| parse(i).bind(|i, d| take_remainder(i).map(|r| (r, d))); @@ -29,23 +34,21 @@ use primitives::{IntoInner, InputBuffer, InputClone}; /// assert_eq!(parse_only(with_remainder, b"aaa"), Ok((&b"a"[..], vec![b'a', b'a']))); /// ``` #[inline] -pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, +pub fn count(i: I, num: usize, p: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { bounded::many(i, num, p) } -/// Tries the parser ``f``, on success it yields the parsed value, on failure ``default`` will be +/// Tries the parser `f`, on success it yields the parsed value, on failure `default` will be /// yielded instead. /// /// Incomplete state is propagated. Backtracks on error. /// /// ``` -/// use chomp::{Input, U8Result, parse_only, option, token}; +/// use chomp::prelude::{U8Input, SimpleResult, parse_only, option, token}; /// -/// fn f(i: Input) -> U8Result { +/// fn f(i: I) -> SimpleResult { /// option(i, |i| token(i, b'a'), b'd') /// } /// @@ -53,21 +56,17 @@ pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResul /// assert_eq!(parse_only(f, b"bbc"), Ok(b'd')); /// ``` #[inline] -pub fn option<'a, I, T, E, F>(i: Input<'a, I>, f: F, default: T) -> ParseResult<'a, I, T, E> - where I: 'a + Copy, - F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { - match f(i.clone()).into_inner() { - State::Data(b, d) => b.ret(d), - State::Error(_, _) => i.ret(default), - State::Incomplete(n) => if i.is_last_slice() { - i.ret(default) - } else { - i.incomplete(n) - }, +pub fn option(i: I, f: F, default: T) -> ParseResult + where F: FnOnce(I) -> ParseResult { + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(d)) => b.ret(d), + (b, Err(_)) => b.restore(m).ret(default), } } -/// Tries to match the parser ``f``, if ``f`` fails it tries ``g``. Returns the success value of +/// Tries to match the parser `f`, if `f` fails it tries `g`. Returns the success value of /// the first match, otherwise the error of the last one if both fail. /// /// Incomplete state is propagated from the first one to report incomplete. @@ -76,7 +75,7 @@ pub fn option<'a, I, T, E, F>(i: Input<'a, I>, f: F, default: T) -> ParseResult< /// and its alternation operator (`<|>`). /// /// ``` -/// use chomp::{ParseError, Error, parse_only, or, token}; +/// use chomp::prelude::{Error, parse_only, or, token}; /// /// let p = |i| or(i, /// |i| token(i, b'a'), @@ -84,33 +83,27 @@ pub fn option<'a, I, T, E, F>(i: Input<'a, I>, f: F, default: T) -> ParseResult< /// /// assert_eq!(parse_only(&p, b"abc"), Ok(b'a')); /// assert_eq!(parse_only(&p, b"bbc"), Ok(b'b')); -/// assert_eq!(parse_only(&p, b"cbc"), Err(ParseError::Error(b"cbc", Error::expected(b'b')))); +/// assert_eq!(parse_only(&p, b"cbc"), Err((&b"cbc"[..], Error::expected(b'b')))); /// ``` #[inline] -pub fn or<'a, I, T, E, F, G>(i: Input<'a, I>, f: F, g: G) -> ParseResult<'a, I, T, E> - where F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E>, - G: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { - match f(i.clone()).into_inner() { - State::Data(b, d) => b.ret(d), - State::Error(_, _) => g(i), - State::Incomplete(n) => if i.is_last_slice() { - g(i) - } else { - i.incomplete(n) - }, +pub fn or(i: I, f: F, g: G) -> ParseResult + where F: FnOnce(I) -> ParseResult, + G: FnOnce(I) -> ParseResult { + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(d)) => b.ret(d), + (b, Err(_)) => g(b.restore(m)), } } -/// Parses many instances of ``f`` until it does no longer match, collecting all matches into the +/// Parses many instances of `f` until it does no longer match, collecting all matches into the /// type `T: FromIterator`. /// -/// Note: If the last parser succeeds on the last input item then this parser is still considered -/// incomplete if the input flag END_OF_INPUT is not set as there might be more data to fill. -/// /// Note: Allocates data. /// /// ``` -/// use chomp::{parse_only, token, many, take_while1}; +/// use chomp::prelude::{parse_only, token, many, take_while1}; /// /// let r: Result, _> = parse_only(|i| many(i, /// |i| take_while1(i, |c| c != b',' && c != b' ') @@ -121,15 +114,13 @@ pub fn or<'a, I, T, E, F, G>(i: Input<'a, I>, f: F, g: G) -> ParseResult<'a, I, /// assert_eq!(r, Ok(vec![&b"a"[..], &b"bc"[..]])); /// ``` #[inline] -pub fn many<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, +pub fn many(i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { bounded::many(i, .., f) } -/// Parses at least one instance of ``f`` and continues until it does no longer match, collecting +/// Parses at least one instance of `f` and continues until it does no longer match, collecting /// all matches into the type `T: FromIterator`. /// /// Note: If the last parser succeeds on the last input item then this parser is still considered @@ -138,20 +129,18 @@ pub fn many<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E /// Note: Allocates data. /// /// ``` -/// use chomp::{ParseError, Error, parse_only, token, many1, take_while1}; +/// use chomp::prelude::{Error, parse_only, token, many1, take_while1}; /// /// let p = |i| many1(i, |i| take_while1(i, |c| c != b',' && c != b' ') /// .bind(|i, c| token(i, b',') /// .map(|_| c))); /// -/// assert_eq!(parse_only(&p, b"a "), Err(ParseError::Error(b" ", Error::expected(b',')))); +/// assert_eq!(parse_only(&p, b"a "), Err((&b" "[..], Error::expected(b',')))); /// assert_eq!(parse_only(&p, b"a, "), Ok(vec![&b"a"[..]])); /// ``` #[inline] -pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, +pub fn many1(i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult, T: FromIterator { bounded::many(i, 1.., f) } @@ -165,7 +154,7 @@ pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, /// Incomplete will be propagated from `R` if end of input has not been read. /// /// ``` -/// use chomp::{parse_only, sep_by, token}; +/// use chomp::prelude::{parse_only, sep_by, token}; /// use chomp::ascii::decimal; /// /// let r: Result, _> = parse_only(|i| sep_by(i, decimal, |i| token(i, b';')), b"91;03;20"); @@ -173,15 +162,11 @@ pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, /// assert_eq!(r, Ok(vec![91, 03, 20])); /// ``` #[inline] -pub fn sep_by<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, sep: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, +pub fn sep_by(i: I, p: R, sep: F) -> ParseResult + where T: FromIterator, E: From, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { bounded::sep_by(i, .., p, sep) } @@ -195,7 +180,7 @@ pub fn sep_by<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, sep: F) -> Pars /// Incomplete will be propagated from `R` if end of input has not been read. /// /// ``` -/// use chomp::{parse_only, sep_by1, token}; +/// use chomp::prelude::{parse_only, sep_by1, token}; /// use chomp::ascii::decimal; /// /// let r: Result, _> = parse_only(|i| sep_by1(i, decimal, |i| token(i, b';')), b"91;03;20"); @@ -203,15 +188,11 @@ pub fn sep_by<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, sep: F) -> Pars /// assert_eq!(r, Ok(vec![91, 03, 20])); /// ``` #[inline] -pub fn sep_by1<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, sep: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, +pub fn sep_by1(i: I, p: R, sep: F) -> ParseResult + where T: FromIterator, E: From, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { bounded::sep_by(i, 1.., p, sep) } @@ -223,21 +204,18 @@ pub fn sep_by1<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, sep: F) -> Par /// Errors from `R` are propagated. /// /// ``` -/// use chomp::{parse_only, many_till, any, token}; +/// use chomp::prelude::{parse_only, many_till, any, token}; /// /// let r: Result, _> = parse_only(|i| many_till(i, any, |i| token(i, b';')), b"abc;def"); /// /// assert_eq!(r, Ok(vec![b'a', b'b', b'c'])); /// ``` #[inline] -pub fn many_till<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, end: F) -> ParseResult<'a, I, T, E> - where I: Copy, - U: 'a, - V: 'a, - N: 'a, - T: FromIterator, - R: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, V, N> { +pub fn many_till(i: I, p: R, end: F) -> ParseResult + where T: FromIterator, + E: From, + R: FnMut(I) -> ParseResult, + F: FnMut(I) -> ParseResult { bounded::many_till(i, .., p, end) } @@ -245,20 +223,19 @@ pub fn many_till<'a, I, T, E, R, F, U, N, V>(i: Input<'a, I>, p: R, end: F) -> P /// /// Incomplete state will be propagated. /// -/// This is more efficient compared to using ``many`` and then just discarding the result as -/// ``many`` allocates a separate data structure to contain the data before proceeding. +/// This is more efficient compared to using `many` and then just discarding the result as +/// `many` allocates a separate data structure to contain the data before proceeding. /// /// ``` -/// use chomp::{parse_only, skip_many, token}; +/// use chomp::prelude::{parse_only, skip_many, token}; /// /// let r = parse_only(|i| skip_many(i, |i| token(i, b'a')).then(|i| token(i, b'b')), b"aaaabc"); /// /// assert_eq!(r, Ok(b'b')); /// ``` #[inline] -pub fn skip_many<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, (), E> - where T: 'a, - F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { +pub fn skip_many(i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { bounded::skip_many(i, .., f) } @@ -267,56 +244,52 @@ pub fn skip_many<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, () /// Incomplete state will be propagated. Will propagate the error if it occurs during the first /// attempt. /// -/// This is more efficient compared to using ``many1`` and then just discarding the result as -/// ``many1`` allocates a separate data structure to contain the data before proceeding. +/// This is more efficient compared to using `many1` and then just discarding the result as +/// `many1` allocates a separate data structure to contain the data before proceeding. /// /// ``` -/// use chomp::{ParseError, Error, parse_only, skip_many1, token}; +/// use chomp::prelude::{Error, parse_only, skip_many1, token}; /// /// let p = |i| skip_many1(i, |i| token(i, b'a')).bind(|i, _| token(i, b'b')); /// /// assert_eq!(parse_only(&p, b"aaaabc"), Ok(b'b')); /// assert_eq!(parse_only(&p, b"abc"), Ok(b'b')); /// -/// assert_eq!(parse_only(&p, b"bc"), Err(ParseError::Error(b"bc", Error::expected(b'a')))); +/// assert_eq!(parse_only(&p, b"bc"), Err((&b"bc"[..], Error::expected(b'a')))); /// ``` #[inline] -pub fn skip_many1<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, (), E> - where T: 'a, F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> { +pub fn skip_many1(i: I, f: F) -> ParseResult + where F: FnMut(I) -> ParseResult { bounded::skip_many(i, 1.., f) } /// Returns the result of the given parser as well as the slice which matched it. /// /// ``` -/// use chomp::{parse_only, matched_by}; +/// use chomp::prelude::{parse_only, matched_by}; /// use chomp::ascii::decimal; /// /// assert_eq!(parse_only(|i| matched_by(i, decimal), b"123"), Ok((&b"123"[..], 123u32))); /// ``` #[inline] -pub fn matched_by<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, (&'a [I], T), E> - where T: 'a, - F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { - let buf = i.buffer(); +pub fn matched_by(i: I, f: F) -> ParseResult + where F: FnOnce(I) -> ParseResult { + let m = i.mark(); - match f(i.clone()).into_inner() { - State::Data(b, t) => { - // b is remainder, find out how much the parser used - let diff = buf.len() - b.buffer().len(); - let n = &buf[..diff]; + match f(i).into_inner() { + (mut b, Ok(t)) => { + let n = b.consume_from(m); b.ret((n, t)) }, - State::Error(b, e) => i.replace(b).err(e), - State::Incomplete(n) => i.incomplete(n), + (b, Err(e)) => b.err(e), } } /// Applies the parser `F` without consuming any input. /// /// ``` -/// use chomp::{parse_only, take}; +/// use chomp::prelude::{parse_only, take}; /// use chomp::combinators::look_ahead; /// /// let p = |i| look_ahead(i, |i| take(i, 4)).bind(|i, t| take(i, 7).map(|u| (t, u))); @@ -324,260 +297,229 @@ pub fn matched_by<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, ( /// assert_eq!(parse_only(p, b"testing"), Ok((&b"test"[..], &b"testing"[..]))); /// ``` #[inline] -pub fn look_ahead<'a, I, T, E, F>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E> - where F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { - match f(i.clone()).into_inner() { - State::Data(_, t) => i.ret(t), - State::Error(b, t) => i.replace(b).err(t), - State::Incomplete(n) => i.incomplete(n), +pub fn look_ahead(i: I, f: F) -> ParseResult + where F: FnOnce(I) -> ParseResult { + let m = i.mark(); + + match f(i).into_inner() { + (b, Ok(t)) => b.restore(m).ret(t), + (b, Err(t)) => b.restore(m).err(t), } } #[cfg(test)] mod test { - use ParseResult; - use primitives::State; - use primitives::input::{new, DEFAULT, END_OF_INPUT}; + use types::{Input, ParseResult}; use primitives::IntoInner; use super::*; - use parsers::{any, take, token, string}; + use parsers::{Error, any, take, token, string}; #[test] fn option_test() { - assert_eq!(option(new(DEFAULT, b""), any, b'-').into_inner(), State::Incomplete(1)); - assert_eq!(option(new(DEFAULT, b"a"), any, b'-').into_inner(), State::Data(new(DEFAULT, b""), b'a')); - assert_eq!(option(new(DEFAULT, b""), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Incomplete(2)); - assert_eq!(option(new(DEFAULT, b"a"), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Incomplete(1)); - assert_eq!(option(new(DEFAULT, b"ab"), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Data(new(DEFAULT, b""), vec![b'a', b'b'])); + assert_eq!(option(&b""[..], any, b'-').into_inner(), (&b""[..], Ok(b'-'))); + assert_eq!(option(&b"a"[..], any, b'-').into_inner(), (&b""[..], Ok(b'a'))); + assert_eq!(option(&b""[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b""[..], Ok(vec![]))); + assert_eq!(option(&b"a"[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b"a"[..], Ok(vec![]))); + assert_eq!(option(&b"ab"[..], |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), (&b""[..], Ok(vec![b'a', b'b']))); - assert_eq!(option(new(DEFAULT, b"a"), |i| token(i, b' ').map_err(|_| "token_err"), b'-').into_inner(), State::Data(new(DEFAULT, b"a"), b'-')); - - assert_eq!(option(new(END_OF_INPUT, b""), any, b'-').into_inner(), State::Data(new(END_OF_INPUT, b""), b'-')); - assert_eq!(option(new(END_OF_INPUT, b"a"), any, b'-').into_inner(), State::Data(new(END_OF_INPUT, b""), b'a')); - assert_eq!(option(new(END_OF_INPUT, b""), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - assert_eq!(option(new(END_OF_INPUT, b"a"), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Data(new(END_OF_INPUT, b"a"), vec![])); - assert_eq!(option(new(END_OF_INPUT, b"ab"), |i| take(i, 2).map(ToOwned::to_owned), vec![]).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'b'])); - - assert_eq!(option(new(END_OF_INPUT, b"a"), |i| token(i, b' ').map_err(|_| "token_err"), b'-').into_inner(), State::Data(new(END_OF_INPUT, b"a"), b'-')); + assert_eq!(option(&b"a"[..], |i| token(i, b' ').map_err(|_| "token_err"), b'-').into_inner(), (&b"a"[..], Ok(b'-'))); } #[test] fn or_test() { - assert_eq!(or(new(DEFAULT, b""), any, any).into_inner(), State::Incomplete(1)); - assert_eq!(or(new(DEFAULT, b"a"), any, any).into_inner(), State::Data(new(DEFAULT, b""), b'a')); - assert_eq!(or(new(DEFAULT, b"a"), |i| take(i, 2), |i| take(i, 1)).into_inner(), State::Incomplete(1)); - assert_eq!(or(new(DEFAULT, b"ab"), |i| take(i, 2), |i| take(i, 1)).into_inner(), State::Data(new(DEFAULT, b""), &b"ab"[..])); - assert_eq!(or(new(DEFAULT, b"a"), |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), State::Data(new(DEFAULT, b""), b'a')); - assert_eq!(or(new(DEFAULT, b"b"), |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), State::Data(new(DEFAULT, b""), b'b')); - assert_eq!(or(new(DEFAULT, b"c"), |i| token(i, b'a').map_err(|_| "a err"), |i| token(i, b'b').map_err(|_| "b err")).into_inner(), State::Error(b"c", "b err")); - - assert_eq!(or(new(END_OF_INPUT, b""), any, any).into_inner(), State::Incomplete(1)); - assert_eq!(or(new(END_OF_INPUT, b"a"), any, any).into_inner(), State::Data(new(END_OF_INPUT, b""), b'a')); - assert_eq!(or(new(END_OF_INPUT, b"a"), |i| take(i, 2), |i| take(i, 1)).into_inner(), State::Data(new(END_OF_INPUT, b""), &b"a"[..])); - assert_eq!(or(new(END_OF_INPUT, b"ab"), |i| take(i, 2), |i| take(i, 1)).into_inner(), State::Data(new(END_OF_INPUT, b""), &b"ab"[..])); - assert_eq!(or(new(END_OF_INPUT, b"a"), |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), State::Data(new(END_OF_INPUT, b""), b'a')); - assert_eq!(or(new(END_OF_INPUT, b"b"), |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), State::Data(new(END_OF_INPUT, b""), b'b')); - assert_eq!(or(new(END_OF_INPUT, b"c"), |i| token(i, b'a').map_err(|_| "a err"), |i| token(i, b'b').map_err(|_| "b err")).into_inner(), State::Error(b"c", "b err")); + assert_eq!(or(&b""[..], any, any).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(or(&b"a"[..], any, any).into_inner(), (&b""[..], Ok(b'a'))); + assert_eq!(or(&b"a"[..], |i| take(i, 2), |i| take(i, 1)).into_inner(), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(or(&b"ab"[..], |i| take(i, 2), |i| take(i, 1)).into_inner(), (&b""[..], Ok(&b"ab"[..]))); + assert_eq!(or(&b"a"[..], |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), (&b""[..], Ok(b'a'))); + assert_eq!(or(&b"b"[..], |i| token(i, b'a'), |i| token(i, b'b')).into_inner(), (&b""[..], Ok(b'b'))); + assert_eq!(or(&b"c"[..], |i| token(i, b'a').map_err(|_| "a err"), |i| token(i, b'b').map_err(|_| "b err")).into_inner(), (&b"c"[..], Err("b err"))); } #[test] fn many_test() { - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b""), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b"a"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b"aa"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b"bbb"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"bbb"), vec![])); - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b"abb"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"bb"), vec![b'a'])); - let r: State<_, Vec<_>, _> = many(new(DEFAULT, b"aab"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - - let r: State<_, Vec<_>, _> = many(new(END_OF_INPUT, b""), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![])); - let r: State<_, Vec<_>, _> = many(new(END_OF_INPUT, b"a"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - let r: State<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aa"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - - let r: State<_, Vec<_>, _> = many(new(END_OF_INPUT, b"aab"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); + let r: (_, Result, _>) = many(&b""[..], |i| i.err("the error")).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many(&b"abc"[..], |i| i.err("the error")).into_inner(); + assert_eq!(r, (&b"abc"[..], Ok(vec![]))); + + let r: (_, Result, _>) = many(&b""[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![]))); + let r: (_, Result, _>) = many(&b"a"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many(&b"aa"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + + let r: (_, Result, _>) = many(&b"bbb"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"bbb"[..], Ok(vec![]))); + let r: (_, Result, _>) = many(&b"abb"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many(&b"aab"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); } #[test] fn many1_test() { - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b""), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b"a"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b"aa"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b"bbb"), |i| token(i, b'a').map_err(|_| "token_error")).into_inner(); - assert_eq!(r, State::Error(b"bbb", "token_error")); - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b"abb"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"bb"), vec![b'a'])); - let r: State<_, Vec<_>, _> = many1(new(DEFAULT, b"aab"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"b"), vec![b'a', b'a'])); - - let r: State<_, Vec<_>, _> = many1(new(END_OF_INPUT, b""), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = many1(new(END_OF_INPUT, b"a"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - let r: State<_, Vec<_>, _> = many1(new(END_OF_INPUT, b"aa"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a'])); - - let r: State<_, Vec<_>, _> = many1(new(END_OF_INPUT, b"aab"), |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b"b"), vec![b'a', b'a'])); + let r: (_, Result, _>) = many1(&b""[..], |i| i.err("the error")).into_inner(); + assert_eq!(r, (&b""[..], Err("the error"))); + let r: (_, Result, _>) = many1(&b"abc"[..], |i| i.err("the error")).into_inner(); + assert_eq!(r, (&b"abc"[..], Err("the error"))); + + let r: (_, Result, _>) = many1(&b""[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many1(&b"a"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many1(&b"aa"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a']))); + + let r: (_, Result, _>) = many1(&b"bbb"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"bbb"[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = many1(&b"abb"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"bb"[..], Ok(vec![b'a']))); + let r: (_, Result, _>) = many1(&b"aab"[..], |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"b"[..], Ok(vec![b'a', b'a']))); } #[test] fn count_test() { - let r: State<_, Vec<_>, _> = count(new(DEFAULT, b""), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(DEFAULT, b"a"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(DEFAULT, b"aa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(DEFAULT, b"aaa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b""), vec![b'a', b'a', b'a'])); - let r: State<_, Vec<_>, _> = count(new(DEFAULT, b"aaaa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(DEFAULT, b"a"), vec![b'a', b'a', b'a'])); - - let r: State<_, Vec<_>, _> = count(new(END_OF_INPUT, b""), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(END_OF_INPUT, b"a"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(END_OF_INPUT, b"aa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Incomplete(1)); - let r: State<_, Vec<_>, _> = count(new(END_OF_INPUT, b"aaa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b""), vec![b'a', b'a', b'a'])); - let r: State<_, Vec<_>, _> = count(new(END_OF_INPUT, b"aaaa"), 3, |i| token(i, b'a')).into_inner(); - assert_eq!(r, State::Data(new(END_OF_INPUT, b"a"), vec![b'a', b'a', b'a'])); + let r: (_, Result, _>) = count(&b""[..], 3, |i| i.err("the error")).into_inner(); + assert_eq!(r, (&b""[..], Err("the error"))); + + let r: (_, Result, _>) = count(&b""[..], 3, |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(&b"a"[..], 3, |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(&b"aa"[..], 3, |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Err(Error::expected(b'a')))); + let r: (_, Result, _>) = count(&b"aaa"[..], 3, |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b""[..], Ok(vec![b'a', b'a', b'a']))); + let r: (_, Result, _>) = count(&b"aaaa"[..], 3, |i| token(i, b'a')).into_inner(); + assert_eq!(r, (&b"a"[..], Ok(vec![b'a', b'a', b'a']))); } #[test] fn skip_many1_test() { - assert_eq!(skip_many1(new(DEFAULT, b"aabc"), |i| token(i, b'a')).into_inner(), State::Data(new(DEFAULT, b"bc"), ())); - assert_eq!(skip_many1(new(DEFAULT, b"abc"), |i| token(i, b'a')).into_inner(), State::Data(new(DEFAULT, b"bc"), ())); - assert_eq!(skip_many1(new(DEFAULT, b"bc"), |i| i.err::<(), _>("error")).into_inner(), State::Error(b"bc", "error")); - assert_eq!(skip_many1(new(DEFAULT, b"aaa"), |i| token(i, b'a')).into_inner(), State::Incomplete(1)); - assert_eq!(skip_many1(new(END_OF_INPUT, b"aabc"), |i| token(i, b'a')).into_inner(), State::Data(new(END_OF_INPUT, b"bc"), ())); - assert_eq!(skip_many1(new(END_OF_INPUT, b"abc"), |i| token(i, b'a')).into_inner(), State::Data(new(END_OF_INPUT, b"bc"), ())); - assert_eq!(skip_many1(new(END_OF_INPUT, b"bc"), |i| i.err::<(), _>("error")).into_inner(), State::Error(b"bc", "error")); - assert_eq!(skip_many1(new(END_OF_INPUT, b"aaa"), |i| token(i, b'a')).into_inner(), State::Data(new(END_OF_INPUT, b""), ())); + assert_eq!(skip_many1(&b"bc"[..], |i| i.err::<(), _>("error")).into_inner(), (&b"bc"[..], Err("error"))); + + assert_eq!(skip_many1(&b"aabc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Ok(()))); + assert_eq!(skip_many1(&b"abc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Ok(()))); + assert_eq!(skip_many1(&b"bc"[..], |i| token(i, b'a')).into_inner(), (&b"bc"[..], Err(Error::expected(b'a')))); + assert_eq!(skip_many1(&b""[..], |i| token(i, b'a')).into_inner(), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(skip_many1(&b"aaa"[..], |i| token(i, b'a')).into_inner(), (&b""[..], Ok(()))); } #[test] fn many_till_test() { - assert_eq!(many_till(new(DEFAULT, b"abcd"), any, |i| token(i, b'c')).into_inner(), State::Data(new(DEFAULT, b"d"), vec![b'a', b'b'])); - let r: ParseResult<_, Vec<_>, _> = many_till(new(DEFAULT, b"abd"), any, |i| token(i, b'c')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + assert_eq!(many_till(&b"abcd"[..], any, |i| token(i, b'c')).into_inner(), (&b"d"[..], Ok(vec![b'a', b'b']))); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abd"[..], any, |i| token(i, b'c')); + assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); - let r: ParseResult<_, Vec, _> = many_till(new(DEFAULT, b"abcd"), |i| i.err(()), |i| token(i, b'c')); - assert_eq!(r.into_inner(), State::Error(b"abcd", ())); + let r: ParseResult<_, Vec, _> = many_till(&b"abcd"[..], |i| i.err(Error::expected(b'@')), |i| token(i, b'c')); + assert_eq!(r.into_inner(), (&b"abcd"[..], Err(Error::expected(b'@')))); // Variant to make sure error slice is propagated let mut n = 0; - let r: ParseResult<_, Vec<_>, _> = many_till(new(DEFAULT, b"abcd"), |i| if n == 0 { n += 1; any(i).map_err(|_| "any err") } else { i.err("the error") }, |i| token(i, b'c')); - assert_eq!(r.into_inner(), State::Error(b"bcd", "the error")); + let r: ParseResult<_, Vec<_>, _> = many_till(&b"abcd"[..], |i| if n == 0 { n += 1; any(i).map_err(|_| Error::expected(b'i')) } else { i.err(Error::expected(b'@')) }, |i| token(i, b'c')); + assert_eq!(r.into_inner(), (&b"bcd"[..], Err(Error::expected(b'@')))); } #[test] fn matched_by_test() { - assert_eq!(matched_by(new(DEFAULT, b"abc"), any).into_inner(), State::Data(new(DEFAULT, b"bc"), (&b"a"[..], b'a'))); - assert_eq!(matched_by(new(DEFAULT, b"abc"), |i| i.err::<(), _>("my error")).into_inner(), State::Error(&b"abc"[..], "my error")); - assert_eq!(matched_by(new(DEFAULT, b"abc"), |i| any(i).map_err(|_| "any error").then(|i| i.err::<(), _>("my error"))).into_inner(), State::Error(&b"bc"[..], "my error")); - assert_eq!(matched_by(new(DEFAULT, b""), any).into_inner(), State::Incomplete(1)); + assert_eq!(matched_by(&b"abc"[..], any).into_inner(), (&b"bc"[..], Ok((&b"a"[..], b'a')))); + assert_eq!(matched_by(&b"abc"[..], |i| i.err::<(), _>("my error")).into_inner(), (&b"abc"[..], Err("my error"))); + assert_eq!(matched_by(&b"abc"[..], |i| any(i).map_err(|_| "any error").then(|i| i.err::<(), _>("my error"))).into_inner(), (&b"bc"[..], Err("my error"))); + assert_eq!(matched_by(&b""[..], any).into_inner(), (&b""[..], Err(Error::unexpected()))); } #[test] fn sep_by_test() { - assert_eq!(sep_by(new(END_OF_INPUT, b""), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![])); - assert_eq!(sep_by(new(END_OF_INPUT, b"b"), |i| token(i, b'a'), |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b"b"), vec![])); - assert_eq!(sep_by(new(END_OF_INPUT, b"a"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - assert_eq!(sep_by(new(END_OF_INPUT, b"a;c"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'c'])); - assert_eq!(sep_by(new(END_OF_INPUT, b"a;c;"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b";"), vec![b'a', b'c'])); - assert_eq!(sep_by(new(END_OF_INPUT, b"a--c-"), any, |i| string(i, b"--")).into_inner(), State::Data(new(END_OF_INPUT, b"-"), vec![b'a', b'c'])); - assert_eq!(sep_by(new(END_OF_INPUT, b"abc"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b"bc"), vec![b'a'])); - assert_eq!(sep_by(new(END_OF_INPUT, b"a;bc"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b"c"), vec![b'a', b'b'])); - - assert_eq!(sep_by(new(DEFAULT, b"abc"), any, |i| token(i, b';')).into_inner(), State::Data(new(DEFAULT, b"bc"), vec![b'a'])); - assert_eq!(sep_by(new(DEFAULT, b"a;bc"), any, |i| token(i, b';')).into_inner(), State::Data(new(DEFAULT, b"c"), vec![b'a', b'b'])); + assert_eq!(sep_by(&b""[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![]))); + assert_eq!(sep_by(&b"a"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a']))); + assert_eq!(sep_by(&b"a;c"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by(&b"a;c;"[..], any, |i| token(i, b';')).into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); + assert_eq!(sep_by(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); + + assert_eq!(sep_by(&b"b"[..], |i| token(i, b'a'), |i| token(i, b';')).into_inner(), (&b"b"[..], Ok(vec![]))); + assert_eq!(sep_by(&b"a--c-"[..], any, |i| string(i, b"--")).into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); // Incomplete becasue there might be another separator or item to be read - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b""), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b""[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Ok(vec![]))); - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"a"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"a;"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"a;c"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;c"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"a;c;"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a;c;"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"a--c-"), any, |i| string(i, b"--")); - assert_eq!(r.into_inner(), State::Incomplete(1)); - - let r: ParseResult<_, Vec<_>, _> = sep_by(new(DEFAULT, b"aaa--a"), |i| string(i, b"aaa"), |i| string(i, b"--")); - assert_eq!(r.into_inner(), State::Incomplete(2)); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"a--c-"[..], any, |i| string(i, b"--")); + assert_eq!(r.into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); + let r: ParseResult<_, Vec<_>, _> = sep_by(&b"aaa--a"[..], |i| string(i, b"aaa"), |i| string(i, b"--")); + assert_eq!(r.into_inner(), (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); } #[test] fn sep_by1_test() { - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(END_OF_INPUT, b""), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); + + let r: ParseResult<_, Vec<()>, _> = sep_by1(&b"b"[..], |i| i.err("my err"), |i| token(i, b';').map_err(|_| "token_err")); + assert_eq!(r.into_inner(), (&b"b"[..], Err("my err"))); + + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); - let r: ParseResult<_, Vec<()>, _> = sep_by1(new(END_OF_INPUT, b"b"), |i| i.err("my err"), |i| token(i, b';').map_err(|_| "token_err")); - assert_eq!(r.into_inner(), State::Error(b"b", "my err")); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"b"[..], |i| token(i, b'a'), |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); - assert_eq!(sep_by1(new(END_OF_INPUT, b"a"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a'])); - assert_eq!(sep_by1(new(END_OF_INPUT, b"a;c"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b""), vec![b'a', b'c'])); - assert_eq!(sep_by1(new(END_OF_INPUT, b"a;c;"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b";"), vec![b'a', b'c'])); - assert_eq!(sep_by1(new(END_OF_INPUT, b"a--c-"), any, |i| string(i, b"--")).into_inner(), State::Data(new(END_OF_INPUT, b"-"), vec![b'a', b'c'])); - assert_eq!(sep_by1(new(END_OF_INPUT, b"abc"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b"bc"), vec![b'a'])); - assert_eq!(sep_by1(new(END_OF_INPUT, b"a;bc"), any, |i| token(i, b';')).into_inner(), State::Data(new(END_OF_INPUT, b"c"), vec![b'a', b'b'])); + assert_eq!(sep_by1(&b"a"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(&b"a;c"[..], any, |i| token(i, b';')).into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(&b"a;c;"[..], any, |i| token(i, b';')).into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(&b"a--c-"[..], any, |i| string(i, b"--")).into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); + assert_eq!(sep_by1(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); - assert_eq!(sep_by1(new(DEFAULT, b"abc"), any, |i| token(i, b';')).into_inner(), State::Data(new(DEFAULT, b"bc"), vec![b'a'])); - assert_eq!(sep_by1(new(DEFAULT, b"a;bc"), any, |i| token(i, b';')).into_inner(), State::Data(new(DEFAULT, b"c"), vec![b'a', b'b'])); + assert_eq!(sep_by1(&b"abc"[..], any, |i| token(i, b';')).into_inner(), (&b"bc"[..], Ok(vec![b'a']))); + assert_eq!(sep_by1(&b"a;bc"[..], any, |i| token(i, b';')).into_inner(), (&b"c"[..], Ok(vec![b'a', b'b']))); // Incomplete becasue there might be another separator or item to be read - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b""), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b""[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Err(Error::unexpected()))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"a"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"a;"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"a;c"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;c"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b""[..], Ok(vec![b'a', b'c']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"a;c;"), any, |i| token(i, b';')); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a;c;"[..], any, |i| token(i, b';')); + assert_eq!(r.into_inner(), (&b";"[..], Ok(vec![b'a', b'c']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"a--c-"), any, |i| string(i, b"--")); - assert_eq!(r.into_inner(), State::Incomplete(1)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"a--c-"[..], any, |i| string(i, b"--")); + assert_eq!(r.into_inner(), (&b"-"[..], Ok(vec![b'a', b'c']))); - let r: ParseResult<_, Vec<_>, _> = sep_by1(new(DEFAULT, b"aaa--a"), |i| string(i, b"aaa"), |i| string(i, b"--")); - assert_eq!(r.into_inner(), State::Incomplete(2)); + let r: ParseResult<_, Vec<_>, _> = sep_by1(&b"aaa--a"[..], |i| string(i, b"aaa"), |i| string(i, b"--")); + assert_eq!(r.into_inner(), (&b"--a"[..], Ok(vec![&b"aaa"[..]]))); } #[test] fn look_ahead_test() { - assert_eq!(look_ahead(new(DEFAULT, b"abc"), any).into_inner(), State::Data(new(DEFAULT, b"abc"), b'a')); - assert_eq!(look_ahead(new(DEFAULT, b"a"), |i| string(i, b"abc")).into_inner(), State::Incomplete(2)); - assert_eq!(look_ahead(new(DEFAULT, b"aa"), |i| token(i, b'a').then(|i| token(i, b'b')).map_err(|_| "err")).into_inner(), State::Error(b"a", "err")); + assert_eq!(look_ahead(&b"abc"[..], any).into_inner(), (&b"abc"[..], Ok(b'a'))); + assert_eq!(look_ahead(&b"a"[..], |i| string(i, b"abc")).into_inner(), (&b"a"[..], Err(Error::expected(b'b')))); + assert_eq!(look_ahead(&b"aa"[..], |i| token(i, b'a').then(|i| token(i, b'b')).map_err(|_| "err")).into_inner(), (&b"aa"[..], Err("err"))); } } diff --git a/src/input.rs b/src/input.rs deleted file mode 100644 index 3c2443de..00000000 --- a/src/input.rs +++ /dev/null @@ -1,297 +0,0 @@ -use parse_result::{ParseResult, State}; -use parse_result; - -bitflags!{ - pub flags InputMode: u32 { - /// Default (empty) input state. - const DEFAULT = 0, - /// If set the current slice of input is the last one. - const END_OF_INPUT = 1, - } -} - -/// **Primitive:** Trait limiting the use of `Clone` for `Input`. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -pub trait InputClone { - /// Creates a clone of the instance. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn clone(&self) -> Self; -} - -/// **Primitive:** Trait exposing the buffer of `Input`. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -pub trait InputBuffer<'a> { - /// The type of each element of the buffer. - type Item: 'a; - - /// Reveals the internal buffer containig the remainder of the input. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn buffer(&self) -> &'a [Self::Item]; - - /// Modifies the inner data without leaving the `Input` context. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn replace(self, &'a [Self::Item]) -> Self; - - /// Returns true if this is the last available slice of the input. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn is_last_slice(&self) -> bool; -} - -/// Linear type containing the parser state, this type is threaded though `bind` and is also the -/// initial type passed to a parser. -/// -/// Coupled with the `ParseResult` type it forms the parser monad: -/// -/// ```ignore -/// Fn*(Input, ...) -> ParseResult; -/// ``` -/// -/// where ``Fn*`` is the appropriate closure/function trait, `I` the input token type (usually -/// something like `u8`), `...` additional parameters to the parser, `T` the carried type and `E` -/// the potential error type. -#[must_use] -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct Input<'a, I: 'a>(InputMode, &'a [I]); - -/// **Primitive:** Creates a new input from the given state and buffer. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -pub fn new(state: InputMode, buffer: &[I]) -> Input { - Input(state, buffer) -} - -impl<'a, I> Input<'a, I> { - /// Returns `t` as a success value in the parsing context. - /// - /// Equivalent to Haskell's `return` function in the `Monad` typeclass. - /// - /// # Example - /// - /// ``` - /// use chomp::parse_only; - /// - /// let r = parse_only(|i| - /// // Annotate the error type - /// i.ret::<_, ()>("Wohoo, success!"), - /// b"some input"); - /// - /// assert_eq!(r, Ok("Wohoo, success!")); - /// ``` - #[inline] - pub fn ret(self, t: T) -> ParseResult<'a, I, T, E> { - parse_result::new(State::Data(self, t)) - } - - /// Returns `e` as an error value in the parsing context. - /// - /// A more general version of Haskell's `fail` function in the `Monad` typeclass. - /// - /// # Example - /// - /// ``` - /// use chomp::{ParseError, parse_only}; - /// - /// let r = parse_only(|i| - /// // Annotate the value type - /// i.err::<(), _>("Something went wrong"), - /// b"some input"); - /// - /// assert_eq!(r, Err(ParseError::Error(b"some input", "Something went wrong"))); - /// ``` - #[inline] - pub fn err(self, e: E) -> ParseResult<'a, I, T, E> { - parse_result::new(State::Error(self.1, e)) - } - - /// Notifies that a parser has reached the end of the currently supplied slice but requires - /// more data. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline] - pub fn incomplete(self, n: usize) -> ParseResult<'a, I, T, E> { - parse_result::new(State::Incomplete(n)) - } - - /// Converts a `Result` into a `ParseResult`, preserving parser state. - /// - /// To convert an `Option` into a `ParseResult` it is recommended to use - /// [`Option::ok_or`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or) - /// or [`Option::ok_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or_else) - /// in combination with this method. - /// - /// # Examples - /// - /// ``` - /// use chomp::{ParseError, parse_only}; - /// - /// let r = parse_only(|i| i.from_result::<_, ()>(Ok("foo")), b"test"); - /// - /// assert_eq!(r, Ok("foo")); - /// - /// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); - /// - /// assert_eq!(r, Err(ParseError::Error(&b"test"[..], "error message"))); - /// ``` - #[inline] - pub fn from_result(self, r: Result) -> ParseResult<'a, I, T, E> { - match r { - Ok(t) => parse_result::new(State::Data(self, t)), - Err(e) => parse_result::new(State::Error(self.1, e)), - } - } -} - -/// Trait limiting the use of `Clone` for `Input`. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -/// # Motivation -/// -/// The `Input` type is supposed to be an approximation of a linear type when observed in the -/// monadic parser context. This means that it should not be possible to duplicate or accidentally -/// throw it away as well as restrict when and where an `Input` can be constructed. Not -/// implementing `Clone` or `Copy` solves the first issue. -/// -/// However, cloning an `Input` is necessary for backtracking and also allows for slightly more -/// efficient iteration in combinators. This trait allows us to enable cloning selectively. -impl<'a, I: 'a> InputClone for Input<'a, I> { - #[inline(always)] - fn clone(&self) -> Self { - Input(self.0, self.1) - } -} - -/// Trait exposing the buffer of `Input`. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -/// # Motivation -/// -/// The `Input` type is supposed to be an approximation of a linear type when observed in the -/// monadic parser context. This means that it should not be possible to duplicate or accidentally -/// throw it away as well as restrict when and where an `Input` can be constructed. Not exposing -/// the constructor (to allow destructuring) as well as using `#[must_use]` solves the second -/// issue. -/// -/// But to be able to parse data the contents of the `Input` type must be exposed in at least one -/// point, so that data can be examined, and this trait that makes it possible. -/// -/// # Example -/// -/// ``` -/// use chomp::take; -/// use chomp::primitives::input; -/// use chomp::primitives::{InputBuffer, IntoInner, State}; -/// -/// let i = input::new(input::END_OF_INPUT, b"Testing"); -/// -/// assert_eq!(i.buffer(), b"Testing"); -/// assert_eq!(i.is_last_slice(), true); -/// -/// let b = i.buffer(); -/// let j = i.replace(&b[..4]); -/// -/// let r = take(j, 4); -/// -/// assert_eq!(r.into_inner(), State::Data(input::new(input::END_OF_INPUT, b""), &b"Test"[..])); -/// ``` -impl<'a, I: 'a> InputBuffer<'a> for Input<'a, I> { - type Item = I; - - #[inline(always)] - fn buffer(&self) -> &'a [Self::Item] { - self.1 - } - - #[inline(always)] - fn replace(self, b: &'a [Self::Item]) -> Self { - Input(self.0, b) - } - - #[inline(always)] - fn is_last_slice(&self) -> bool { - self.0.contains(END_OF_INPUT) - } -} - -#[cfg(test)] -mod test { - use super::{new, Input, InputBuffer, DEFAULT, END_OF_INPUT}; - use parse_result::ParseResult; - use primitives::{IntoInner, State}; - - #[test] - fn make_ret() { - let i1: Input = new(END_OF_INPUT, b"in1"); - let i2: Input = new(DEFAULT, b"in2"); - - let r1: ParseResult = i1.ret::<_, ()>(23u32); - let r2: ParseResult = i2.ret::<_, ()>(23i32); - - assert_eq!(r1.into_inner(), State::Data(Input(END_OF_INPUT, b"in1"), 23u32)); - assert_eq!(r2.into_inner(), State::Data(Input(DEFAULT, b"in2"), 23i32)); - } - - #[test] - fn make_err() { - let i1: Input = new(END_OF_INPUT, b"in1"); - let i2: Input = new(DEFAULT, b"in2"); - - let r1: ParseResult = i1.err::<(), _>(23u32); - let r2: ParseResult = i2.err::<(), _>(23i32); - - assert_eq!(r1.into_inner(), State::Error(b"in1", 23u32)); - assert_eq!(r2.into_inner(), State::Error(b"in2", 23i32)); - } - - #[test] - fn make_incomplete() { - let i1: Input = new(END_OF_INPUT, b"in1"); - let i2: Input = new(DEFAULT, b"in2"); - - let r1: ParseResult = i1.incomplete::<(), _>(23); - let r2: ParseResult = i2.incomplete::<(), _>(23); - - assert_eq!(r1.into_inner(), State::Incomplete(23)); - assert_eq!(r2.into_inner(), State::Incomplete(23)); - } - - #[test] - fn last_slice() { - let i = new(END_OF_INPUT, &b"foo"[..]); - - assert_eq!(i.is_last_slice(), true); - } -} diff --git a/src/lib.rs b/src/lib.rs index 747334fe..b6f3b2da 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,23 +9,22 @@ //! For its current capabilities, you will find that Chomp performs consistently as well, if not //! better, than optimized C parsers, while being vastly more expressive. For an example that //! builds a performant HTTP parser out of smaller parsers, see -//! [http_parser.rs](examples/http_parser.rs). +//! [`http_parser.rs`](examples/http_parser.rs). //! //! # Example //! //! ``` //! # #[macro_use] extern crate chomp; //! # fn main() { -//! use chomp::{Input, U8Result, parse_only}; -//! use chomp::{take_while1, token}; +//! use chomp::prelude::*; //! //! #[derive(Debug, Eq, PartialEq)] -//! struct Name<'a> { -//! first: &'a [u8], -//! last: &'a [u8], +//! struct Name { +//! first: B, +//! last: B, //! } //! -//! fn name(i: Input) -> U8Result { +//! fn name(i: I) -> SimpleResult> { //! parse!{i; //! let first = take_while1(|c| c != b' '); //! token(b' '); // skipping this char @@ -39,7 +38,7 @@ //! } //! //! assert_eq!(parse_only(name, "Martin Wernstål\n".as_bytes()), Ok(Name{ -//! first: b"Martin", +//! first: &b"Martin"[..], //! last: "Wernstål".as_bytes() //! })); //! # } @@ -61,7 +60,7 @@ //! `token` parser, which matches a particular input. //! //! ```ignore -//! fn token(i: Input, t: I) -> SimpleResult {...} +//! fn token(i: I, t: I::Token) -> ParseResult> { ... } //! ``` //! //! Notice that the first argument is an `Input`, and the second argument is some `I`. @@ -82,8 +81,8 @@ //! A very useful parser is the `satisfy` parser: //! //! ```ignore -//! fn satisfy(i: Input, f: F) -> SimpleResult -//! where F: FnOnce(I) -> bool { ... } +//! fn satisfy(mut i: I, f: F) -> ParseResult> +//! where F: FnOnce(I::Token) -> bool { ... } //! ``` //! //! Besides the input state, satisfy's only parameter is a predicate function and will succeed only @@ -93,7 +92,7 @@ //! ``` //! # #[macro_use] extern crate chomp; //! # fn main() { -//! # use chomp::{satisfy, parse_only}; +//! # use chomp::prelude::*; //! # let r = parse_only(parser!{ //! satisfy(|c| { //! match c { @@ -112,10 +111,8 @@ //! times on its input. //! //! ```ignore -//! pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResult<'a, I, T, E> -//! where I: Copy, -//! U: 'a, -//! F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>, +//! pub fn count(i: I, num: usize, p: F) -> ParseResult +//! where F: FnMut(I) -> ParseResult, //! T: FromIterator { ... } //! ``` //! @@ -144,8 +141,8 @@ //! //! ``` //! # #[macro_use] extern crate chomp; -//! # use chomp::{Input, parse_only, satisfy, string, U8Result}; -//! fn f(i: Input) -> U8Result<(u8, u8, u8)> { +//! # use chomp::prelude::*; +//! fn f(i: I) -> SimpleResult { //! parse!{i; //! let a = digit(); //! let b = digit(); @@ -154,7 +151,7 @@ //! } //! } //! -//! fn digit(i: Input) -> U8Result { +//! fn digit(i: I) -> SimpleResult { //! satisfy(i, |c| b'0' <= c && c <= b'9').map(|c| c - b'0') //! } //! # fn main() { @@ -201,6 +198,27 @@ //! The built-in `chomp::parsers::Error` type is zero-sized and carry no error-information. This //! increases performance somewhat. +#![warn(missing_docs, + trivial_casts, + unused_import_braces, + unused_qualifications)] + +#![cfg_attr(feature="clippy", feature(plugin))] +#![cfg_attr(feature="clippy", plugin(clippy))] +#![cfg_attr(feature="clippy", warn( + nonminimal_bool, + option_unwrap_used, + print_stdout, + result_unwrap_used, + shadow_reuse, + shadow_same, + shadow_unrelated, + single_match_else))] +#![cfg_attr(feature="clippy", allow(inline_always, many_single_char_names))] + +#[cfg(feature = "tendril")] +extern crate tendril; + #[macro_use] extern crate bitflags; extern crate conv; @@ -208,93 +226,64 @@ extern crate debugtrace; #[macro_use] mod macros; -mod input; mod parse; -mod parse_result; pub mod ascii; pub mod buffer; -pub mod parsers; pub mod combinators; +pub mod parsers; +pub mod primitives; +pub mod types; -pub use combinators::{ - count, - option, - or, - many, - many1, - sep_by, - sep_by1, - many_till, - skip_many, - skip_many1, - matched_by, -}; -pub use parsers::{ - any, - eof, - not_token, - peek, - peek_next, - satisfy, - satisfy_with, - scan, - string, - run_scanner, - take, - take_remainder, - take_till, - take_while, - take_while1, - token, -}; -pub use parsers::Error; -pub use input::Input; -pub use parse::{ - ParseError, - parse_only, -}; -pub use parse_result::{ - ParseResult, - SimpleResult, - U8Result, -}; +pub use parse::parse_only; +pub use parse::parse_only_str; +pub use parse::run_parser; -/// Module used to construct fundamental parsers and combinators. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -pub mod primitives { - pub use input::{ - InputBuffer, - InputClone, +/// Basic prelude. +pub mod prelude { + pub use parsers::{ + any, + eof, + not_token, + peek, + peek_next, + run_scanner, + satisfy, + satisfy_with, + scan, + skip_while, + string, + take, + take_remainder, + take_till, + take_while, + take_while1, + token, }; - pub use parse_result::{ - IntoInner, - State, + pub use parsers::{ + Error, + SimpleResult, }; - /// Input utilities. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - pub mod input { - pub use input::{DEFAULT, END_OF_INPUT, new}; - } - - /// ParseResult utilities. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - /// - /// # Note - /// - /// Prefer to use ``Input::ret``, ``Input::err`` or ``Input::incomplete`` instead of using - /// ``parse_result::new``. - pub mod parse_result { - pub use parse_result::new; - } + pub use combinators::{ + count, + option, + or, + many, + many1, + sep_by, + sep_by1, + many_till, + skip_many, + skip_many1, + matched_by, + }; + pub use types::{ + Buffer, + Input, + U8Input, + ParseResult, + }; + pub use parse_only; + pub use parse_only_str; } diff --git a/src/macros.rs b/src/macros.rs index 4da176cc..3bc8042f 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1,16 +1,28 @@ /// Macro emulating `do`-notation for the parser monad, automatically threading the linear type. /// -/// ```ignore +/// ``` +/// # #[macro_use] extern crate chomp; +/// # fn main() { +/// # use chomp::prelude::*; +/// # fn parser(i: I, _s: &str) -> ParseResult { i.ret(()) } +/// # fn other_parser(i: I) -> ParseResult { i.ret(23) } +/// # fn do_something(_i: u8) -> u32 { 23 } +/// # let input = &b"foo"[..]; +/// # let _r: ParseResult<_, _, ()> = /// parse!{input; /// parser("parameter"); /// let value = other_parser(); /// -/// ret do_something(value); +/// ret do_something(value) /// } +/// # ; +/// # let _r: ParseResult<_, _, ()> = /// // is equivalent to: /// parser(input, "parameter").bind(|i, _| /// other_parser(i).bind(|i, value| /// i.ret(do_something(value)))) +/// # ; +/// # } /// ``` /// /// # Examples @@ -20,28 +32,29 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{Error, parse_only}; -/// use chomp::{take_while1, token}; +/// use chomp::prelude::{Buffer, Error, Input, ParseResult, parse_only, take_while1, token}; /// /// #[derive(Debug, Eq, PartialEq)] -/// struct Name<'a> { -/// first: &'a [u8], -/// last: &'a [u8], +/// struct Name { +/// first: B, +/// last: B, /// } /// -/// let r = |i| parse!{i; -/// let first = take_while1(|c| c != b' '); -/// token(b' '); -/// let last = take_while1(|c| c != b'\n'); -/// -/// ret @ _, Error<_>: Name{ -/// first: first, -/// last: last, +/// fn parser>(i: I) -> ParseResult, Error> { +/// parse!{i; +/// let first = take_while1(|c| c != b' '); +/// token(b' '); +/// let last = take_while1(|c| c != b'\n'); +/// +/// ret @ _, Error: Name{ +/// first: first, +/// last: last, +/// } /// } -/// }; +/// } /// -/// assert_eq!(parse_only(r, "Martin Wernstål\n".as_bytes()), Ok(Name{ -/// first: b"Martin", +/// assert_eq!(parse_only(parser, "Martin Wernstål\n".as_bytes()), Ok(Name{ +/// first: &b"Martin"[..], /// last: "Wernstål".as_bytes() /// })); /// # } @@ -53,10 +66,10 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{Input, U8Result, parse_only, string, token}; +/// use chomp::prelude::{U8Input, Input, SimpleResult, parse_only, string, token}; /// use chomp::ascii::decimal; /// -/// fn parse_ip(i: Input) -> U8Result<(u8, u8, u8, u8)> { +/// fn parse_ip(i: I) -> SimpleResult { /// parse!{i; /// string(b"ip:"); /// let a = decimal() <* token(b'.'); @@ -77,7 +90,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{parse_only, string}; +/// use chomp::prelude::{parse_only, string}; /// /// #[derive(Debug, Eq, PartialEq)] /// enum Log { @@ -143,8 +156,8 @@ /// # #[macro_use] extern crate chomp; /// # fn main() { /// # use chomp::ascii::decimal; -/// # use chomp::{parse_only, Input, token, U8Result}; -/// # fn my_parser(i: Input) -> U8Result { +/// # use chomp::prelude::{parse_only, U8Input, Input, token, SimpleResult}; +/// # fn my_parser(i: I) -> SimpleResult { /// parse!{i; /// token(b':'); /// let n: u32 = decimal(); @@ -186,9 +199,9 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, Input, U8Result}; -/// # fn my_parser(i: Input) -> U8Result<&'static str> { -/// fn do_it<'i, 'a>(i: Input<'i, u8>, s: &'a str) -> U8Result<'i, &'a str> { i.ret(s) } +/// # use chomp::prelude::{parse_only, U8Input, SimpleResult}; +/// # fn my_parser(i: I) -> SimpleResult { +/// fn do_it<'a, I: U8Input>(i: I, s: &'a str) -> SimpleResult { i.ret(s) } /// /// parse!{i; /// do_it("second parameter") @@ -206,8 +219,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, ParseError}; -/// let r: Result<_, ParseError<_, ()>> = parse_only( +/// # use chomp::prelude::{parse_only, Input}; +/// let r: Result<_, (_, ())> = parse_only( /// parser!{ ret "some success data" }, /// b"input data" /// ); @@ -216,7 +229,7 @@ /// # } /// ``` /// -/// In the example above the `Result<_, ParseError<_, ()>>` type-annotation is required since `ret` +/// In the example above the `Result<_, (_, ())>` type-annotation is required since `ret` /// leaves the error type `E` free which means that the `parser!` expression above cannot infer the /// error type without the annotation. `ret` and `end` both provide a mechanism to supply this /// information inline: @@ -224,10 +237,10 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, ParseError}; +/// # use chomp::prelude::{parse_only, Input}; /// let r = parse_only(parser!{ err @ u32, _: "some error data" }, b"input data"); /// -/// assert_eq!(r, Err(ParseError::Error(b"input data", "some error data"))); +/// assert_eq!(r, Err((&b"input data"[..], "some error data"))); /// # } /// ``` /// @@ -243,8 +256,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, Input, ParseResult}; -/// fn other_parser(i: Input) -> ParseResult { +/// # use chomp::prelude::{parse_only, Input, ParseResult}; +/// fn other_parser(i: I) -> ParseResult { /// i.ret("Success!") /// } /// @@ -253,7 +266,7 @@ /// let p = parser!{ /// state -> match condition { /// true => other_parser(state), -/// false => state.err("failure"), +/// false => Input::err(state, "failure"), /// } /// }; /// @@ -278,7 +291,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::ascii::decimal; use chomp::{parse_only, token}; +/// # use chomp::ascii::decimal; use chomp::prelude::{parse_only, token}; /// let p = parser!{ decimal() <* token(b';') }; /// /// assert_eq!(parse_only(p, b"123;"), Ok(123u32)); @@ -293,7 +306,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, token}; +/// # use chomp::prelude::{parse_only, token}; /// let p = parser!{ token(b'a') <|> token(b'b') }; /// /// assert_eq!(parse_only(p, b"b"), Ok(b'b')); @@ -308,7 +321,7 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only, token}; +/// # use chomp::prelude::{parse_only, token}; /// let p = parser!{ token(b'a') >> token(b';') }; /// /// assert_eq!(parse_only(p, b"a;"), Ok(b';')); @@ -325,8 +338,8 @@ /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// # use chomp::{parse_only}; -/// let p = parser!{ (i -> i.err("foo")) <|> (i -> i.ret("bar")) }; +/// # use chomp::prelude::{Input, parse_only}; +/// let p = parser!{ (i -> Input::err(i, "foo")) <|> (i -> Input::ret(i, "bar")) }; /// /// assert_eq!(parse_only(p, b"a;"), Ok("bar")); /// # } @@ -482,21 +495,21 @@ macro_rules! __parse_internal { // recurse until >> or end // unrolled: // ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1) $($tail)*} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt >> $($tail:tt)* ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}.bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; - ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt ) => { __parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7} }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt >> $($tail:tt)* ) => { (__parse_internal!{@EXPR_ALT($input;) $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7}).bind(|i, _| __parse_internal!{@EXPR(i;) $($tail)*}) }; + ( @EXPR($input:expr; $($lhs:tt)*) $t1:tt $t2:tt $t3:tt $t4:tt $t5:tt $t6:tt $t7:tt $t8:tt $($tail:tt)* ) => { __parse_internal!{@EXPR($input; $($lhs)* $t1 $t2 $t3 $t4 $t5 $t6 $t7 $t8) $($tail)*} }; // ExprAlt ::= ExprSkip ( @EXPR_ALT($input:expr; $($lhs:tt)*) ) => { __parse_internal!{@EXPR_SKIP($input;) $($lhs)*} }; @@ -589,7 +602,7 @@ macro_rules! __parse_internal { /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{parse_only, string}; +/// use chomp::prelude::{parse_only, string}; /// /// let r = parser!{ string(b"ab") <|> string(b"ac") }; /// diff --git a/src/parse.rs b/src/parse.rs index b911cafe..4eacea0a 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -1,29 +1,27 @@ -use {Input, ParseResult}; -use primitives::{IntoInner, State}; -use primitives::input; - -/// Simple error type returned from `parse_only`. -#[derive(Debug, Eq, PartialEq)] -pub enum ParseError<'a, I, E> - where I: 'a { - /// A parse error occurred. - Error(&'a [I], E), - /// The parser attempted to read more data than available. - Incomplete(usize), +use types::{Input, ParseResult}; +use primitives::{ + IntoInner, + Primitives, +}; + +/// Runs the supplied parser over the input. +pub fn run_parser(input: I, parser: F) -> (I, Result) + where I: Input, + F: FnOnce(I) -> ParseResult { + parser(input).into_inner() } /// Runs the given parser on the supplied finite input. /// /// ``` -/// use chomp::{ParseError, Error}; -/// use chomp::parse_only; +/// use chomp::prelude::{parse_only, Error}; /// use chomp::ascii::decimal; /// /// assert_eq!(parse_only(decimal, b"123foobar"), Ok(123u32)); /// /// // Annotation because `decimal` is generic over number types /// let r: Result = parse_only(decimal, b"foobar"); -/// assert_eq!(r, Err(ParseError::Error(&b"foobar"[..], Error::new()))); +/// assert_eq!(r, Err((&b"foobar"[..], Error::new()))); /// ``` /// /// This will not force the parser to consume all available input, any remainder will be @@ -32,10 +30,9 @@ pub enum ParseError<'a, I, E> /// ``` /// # #[macro_use] extern crate chomp; /// # fn main() { -/// use chomp::{Input, ParseError, Error, U8Result}; -/// use chomp::{parse_only, string, eof}; +/// use chomp::prelude::{U8Input, Input, Error, SimpleResult, parse_only, string, eof}; /// -/// fn my_parser(i: Input) -> U8Result<&[u8]> { +/// fn my_parser(i: I) -> SimpleResult { /// parse!{i; /// let r = string(b"pattern"); /// eof(); @@ -46,56 +43,74 @@ pub enum ParseError<'a, I, E> /// /// assert_eq!(parse_only(my_parser, b"pattern"), Ok(&b"pattern"[..])); /// assert_eq!(parse_only(my_parser, b"pattern and more"), -/// Err(ParseError::Error(&b" and more"[..], Error::new()))); +/// Err((&b" and more"[..], Error::new()))); /// # } /// ``` -pub fn parse_only<'a, I, T, E, F>(parser: F, input: &'a [I]) -> Result> - where T: 'a, - E: 'a, - F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { - match parser(input::new(input::END_OF_INPUT, input)).into_inner() { - State::Data(_, t) => Ok(t), - State::Error(b, e) => Err(ParseError::Error(b, e)), - State::Incomplete(n) => Err(ParseError::Incomplete(n)), +pub fn parse_only<'a, I, T, E, F>(parser: F, input: &'a [I]) -> Result + where I: Copy + PartialEq, + F: FnOnce(&'a [I]) -> ParseResult<&'a [I], T, E> { + match parser(input).into_inner() { + (_, Ok(t)) => Ok(t), + (mut b, Err(e)) => Err((b.consume_remaining(), e)), + } +} + +/// Runs the given parser on the supplied string. +pub fn parse_only_str<'a, T, E, F>(parser: F, input: &'a str) -> Result + where F: FnOnce(&'a str) -> ParseResult<&'a str, T, E> { + match parser(input).into_inner() { + (_, Ok(t)) => Ok(t), + (mut b, Err(e)) => Err((b.consume_remaining(), e)), } } #[cfg(test)] mod test { - use primitives::InputBuffer; - - use super::{ - ParseError, - parse_only, - }; + use types::Input; + use primitives::Primitives; + use super::*; #[test] fn inspect_input() { - let mut state = None; let mut input = None; assert_eq!(parse_only(|i| { - state = Some(i.is_last_slice()); - input = Some(i.buffer()); + input = Some(i.iter().cloned().collect()); i.ret::<_, ()>("the result") }, b"the input"), Ok("the result")); - assert_eq!(input, Some(&b"the input"[..])); - assert_eq!(state, Some(true)); + assert_eq!(input, Some(b"the input".to_vec())); } #[test] fn err() { - assert_eq!(parse_only(|i| { - let buf = i.buffer(); + assert_eq!(parse_only(|mut i| { + i.consume(4); - i.replace(&buf[4..]).err::<(), _>("my error") - }, b"the input"), Err(ParseError::Error(&b"input"[..], "my error"))); + i.err::<(), _>("my error") + }, b"the input"), Err((&b"input"[..], "my error"))); } #[test] - fn incomplete() { - assert_eq!(parse_only(|i| i.incomplete::<(), ()>(23), b"the input"), Err(ParseError::Incomplete(23))); + fn inspect_input_str() { + let mut input = None; + + assert_eq!(parse_only_str(|i| { + input = Some(i.to_owned()); + + i.ret::<_, ()>("the result") + }, "the input"), Ok("the result")); + + assert_eq!(input, Some("the input".to_owned())); + } + + #[test] + fn err_str() { + assert_eq!(parse_only_str(|mut i| { + i.consume(4); + + i.err::<(), _>("my error") + }, "the input"), Err(("input", "my error"))); } } diff --git a/src/parse_result.rs b/src/parse_result.rs deleted file mode 100644 index 84393ff2..00000000 --- a/src/parse_result.rs +++ /dev/null @@ -1,434 +0,0 @@ -use parsers::Error; -use input::Input; - -/// Result for dealing with the basic parsers when parsing a stream of `u8`. -pub type U8Result<'a, T> = ParseResult<'a, u8, T, Error>; -/// Result returned from the basic parsers. -pub type SimpleResult<'a, I, T> = ParseResult<'a, I, T, Error>; - -/// **Primitive:** Primitive inner type containing the parse-state. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -#[must_use] -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub enum State<'a, I: 'a, T, E> - where I: 'a, - T: 'a, - E: 'a { - /// Successful parser state, first item is the input state and the second item is the contained - /// value. - Data(Input<'a, I>, T), - /// Parse error state, first item is a slice from where the error occurred in the input buffer - /// to the end of the input buffer and the second item is the error value. - Error(&'a [I], E), - /// Incomplete state, a parser attempted to request more data than available in the slice, the - /// provided number is a guess at how many items are needed. - Incomplete(usize), -} - -/// **Primitive:** Consumes self and reveals the inner state. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -pub trait IntoInner { - /// The inner type to be revealed. - type Inner; - - /// **Primitive:** Consumes self and reveals the inner state. - /// - /// # Primitive - /// - /// Only used by fundamental parsers and combinators. - #[inline(always)] - fn into_inner(self) -> Self::Inner; -} - -/// The basic return type of a parser. -/// -/// This type satisfies a variant of the ``Monad`` typeclass. Due to the limitations of Rust's -/// return types closures cannot be returned without boxing which has an unacceptable performance -/// impact. -/// -/// To get around this issue and still provide a simple to use and safe (as in hard to accidentally -/// violate the monad laws or the assumptions taken by the parser type) an `Input` wrapper is -/// provided which ensures that the parser state is carried properly through every call to `bind`. -/// This is also known as a Linear Type (emulated through hiding destructors and using the -/// annotation ``#[must_use]``). -/// -/// Do-notation is provided by the macro ``parse!``. -/// -/// # Equivalence with Haskell's ``Monad`` typeclass: -/// -/// ```text -/// f >>= g ≡ f(m).bind(g) -/// f >> g ≡ f(m).then(g) -/// return a ≡ m.ret(a) -/// fail a ≡ m.err(a) -/// ``` -/// -/// It also satisfies the monad laws: -/// -/// ```text -/// return a >>= f ≡ f a -/// m >>= return ≡ m -/// (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) -/// ``` -#[must_use] -#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub struct ParseResult<'a, I: 'a, T: 'a, E: 'a>(State<'a, I, T, E>); - -/// **Primitive:** Creates a new `ParseResult`. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -/// # Note -/// -/// Prefer to use ``Input::ret``, ``Input::err`` or ``Input::incomplete`` instead of using -pub fn new(s: State) -> ParseResult { - ParseResult(s) -} - -impl<'a, I, T, E> ParseResult<'a, I, T, E> { - /// Sequentially composes the result with a parse action ``f``, passing any produced value as - /// the second parameter. - /// - /// The first parameter to the supplied function ``f`` is the parser state (``Input``). This - /// state is then passed on to other parsers or used to return a value or an error. - /// - /// # Automatic conversion of ``E`` - /// - /// The error value ``E`` will automatically be converted using the ``From`` trait to the - /// desired type. The downside with this using the current stable version of Rust (1.4) is that - /// the type inferrence will currently not use the default value for the generic ``V`` and will - /// therefore require extra type hint for the error. - /// - /// # Examples - /// - /// ``` - /// use chomp::parse_only; - /// - /// let r = parse_only(|i| { - /// i.ret("data".to_owned()) - /// // Explicitly state the error type - /// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) - /// }, - /// b"test"); - /// - /// assert_eq!(r, Ok("data here!".to_owned())); - /// ``` - /// - /// Wrapping the expression in a function will both make it easier to compose and also provides - /// the type-hint for the error in the function signature: - /// - /// ``` - /// use chomp::{Input, ParseResult, parse_only}; - /// - /// fn parser(i: Input, n: i32) -> ParseResult { - /// i.ret(n + 10) - /// } - /// - /// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); - /// - /// assert_eq!(r, Ok(33)); - /// ``` - #[inline] - pub fn bind(self, f: F) -> ParseResult<'a, I, U, V> - where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>, - V: From { - match self.0 { - State::Data(i, t) => f(i, t).map_err(From::from), - State::Error(i, e) => ParseResult(State::Error(i, From::from(e))), - State::Incomplete(n) => ParseResult(State::Incomplete(n)), - } - } - - /// Sequentially composes the result with a parse action ``f``, discarding any produced value. - /// - /// The first parameter to the supplied function ``f`` is the parser state (``Input``). This - /// state is then passed on to other parsers or used to return a value or an error. - /// - /// # Relation to ``bind`` - /// - /// ```text - /// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) - /// ``` - /// - /// # Example - /// - /// ``` - /// use chomp::{Input, U8Result, parse_only}; - /// - /// fn g(i: Input) -> U8Result<&'static str> { - /// i.ret("testing!") - /// } - /// - /// let r1 = parse_only(|i| i.ret("initial state").bind(|i, _| g(i)), b"data"); - /// let r2 = parse_only(|i| i.ret("initial state").then(g), b"data"); - /// - /// assert_eq!(r1, Ok("testing!")); - /// assert_eq!(r2, Ok("testing!")); - /// ``` - #[inline] - pub fn then(self, f: F) -> ParseResult<'a, I, U, V> - where F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, U, V>, - V: From { - self.bind(|i, _| f(i)) - } - - /// Applies the function `f` on the contained data if the parser is in a success state. - /// - /// # Example - /// - /// ``` - /// use chomp::{parse_only, any}; - /// - /// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); - /// - /// assert_eq!(r, Ok(b'm')); - /// ``` - #[inline] - pub fn map(self, f: F) -> ParseResult<'a, I, U, E> - where F: FnOnce(T) -> U { - match self.0 { - State::Data(i, t) => ParseResult(State::Data(i, f(t))), - State::Error(i, e) => ParseResult(State::Error(i, e)), - State::Incomplete(n) => ParseResult(State::Incomplete(n)), - } - } - - /// Applies the function `f` on the contained error if the parser is in an error state. - /// - /// # Example - /// - /// ``` - /// use chomp::{ParseError, parse_only}; - /// - /// let r = parse_only(|i| i.err::<(), _>("this is") - /// .map_err(|e| e.to_owned() + " an error"), - /// b"foo"); - /// - /// assert_eq!(r, Err(ParseError::Error(b"foo", "this is an error".to_owned()))); - /// ``` - #[inline] - pub fn map_err(self, f: F) -> ParseResult<'a, I, T, V> - where F: FnOnce(E) -> V { - match self.0 { - State::Data(i, t) => ParseResult(State::Data(i, t)), - State::Error(i, e) => ParseResult(State::Error(i, f(e))), - State::Incomplete(n) => ParseResult(State::Incomplete(n)), - } - } - - /// Calls the function `f` with a reference of the contained data if the parser is in a success - /// state. - /// - /// # Example - /// - /// ``` - /// use chomp::{parse_only, take_while}; - /// - /// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { - /// println!("{:?}", b); // Prints "test" - /// }), b"test and more"); - /// - /// assert_eq!(r, Ok(&b"test"[..])); - /// ``` - #[inline] - pub fn inspect(self, f: F) -> ParseResult<'a, I, T, E> - where F: FnOnce(&T) { - if let State::Data(_, ref t) = self.0 { - f(t) - } - - self - } -} - -/// **Primitive:** Consumes the `ParseResult` and exposes the internal state. -/// -/// # Primitive -/// -/// Only used by fundamental parsers and combinators. -/// -/// # Motivation -/// -/// The `ParseResult` type is a semi-linear type, supposed to act like a linear type while used in -/// a parsing context to carry the state. Normally it should be as restrictive as the `Input` type -/// in terms of how much it exposes its internals, but the `IntoInner` trait implementation -/// allows fundamental parsers and combinators to expose the inner `State` of the `ParseResult` -/// and act on this. -/// -/// # Example -/// -/// ``` -/// use chomp::{Input, ParseResult, parse_only, take}; -/// use chomp::primitives::{InputClone, IntoInner, State}; -/// -/// // Version of option() which also catches incomplete -/// fn my_combinator<'a, I, T, E, F>(i: Input<'a, I>, f: F, default: T) -> ParseResult<'a, I, T, E> -/// where F: FnOnce(Input<'a, I>) -> ParseResult<'a, I, T, E> { -/// match f(i.clone()).into_inner() { -/// // Data, preserve the buffer and return -/// State::Data(b, d) => b.ret(d), -/// // Not data, use original buffer and return default -/// _ => i.ret(default), -/// } -/// } -/// -/// let r = parse_only(|i| my_combinator(i, |i| take(i, 10), &b"test"[..]), b"foo"); -/// -/// assert_eq!(r, Ok(&b"test"[..])); -/// ``` -impl<'a, I, T, E> IntoInner for ParseResult<'a, I, T, E> { - type Inner = State<'a, I, T, E>; - - #[inline(always)] - fn into_inner(self) -> Self::Inner { - self.0 - } -} - -#[cfg(test)] -mod test { - use input; - use input::{Input, DEFAULT, END_OF_INPUT}; - use primitives::State; - - use super::ParseResult; - - #[test] - fn monad_left_identity() { - fn f(i: Input, n: u32) -> ParseResult { - i.ret(n + 1) - } - - let m1 = input::new(END_OF_INPUT, b"test"); - let m2 = input::new(END_OF_INPUT, b"test"); - - let a = 123; - // return a >>= f - let lhs = m1.ret(a).bind(f); - // f a - let rhs = f(m2, a); - - assert_eq!(lhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 124)); - assert_eq!(rhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 124)); - } - - #[test] - fn monad_right_identity() { - let m1 = input::new(END_OF_INPUT, b"test").ret::<_, ()>(1); - let m2 = input::new(END_OF_INPUT, b"test").ret::<_, ()>(1); - - // m1 >>= ret === m2 - let lhs = m1.bind::<_, _, ()>(Input::ret); - let rhs = m2; - - assert_eq!(lhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 1)); - assert_eq!(rhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 1)); - } - - #[test] - fn monad_associativity() { - fn f(i: Input, num: u32) -> ParseResult { - i.ret((num + 1) as u64) - } - - fn g(i: Input, num: u64) -> ParseResult { - i.ret(num * 2) - } - - let lhs_m = input::new(END_OF_INPUT, b"test").ret::<_, ()>(2); - let rhs_m = input::new(END_OF_INPUT, b"test").ret::<_, ()>(2); - - // (m >>= f) >>= g - let lhs = lhs_m.bind(f).bind(g); - // m >>= (\x -> f x >>= g) - let rhs = rhs_m.bind(|i, x| f(i, x).bind(g)); - - assert_eq!(lhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 6)); - assert_eq!(rhs.0, State::Data(input::new(END_OF_INPUT, b"test"), 6)); - } - - #[test] - fn parse_result_inspect() { - use primitives::IntoInner; - - let mut n1 = 0; - let mut n2 = 0; - let i1 = input::new(DEFAULT, b"test ").ret::(23); - let i2 = input::new(END_OF_INPUT, b"test ").ret::(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(), State::Data(input::new(DEFAULT, b"test "), 23)); - assert_eq!(n1, 1); - assert_eq!(r2.into_inner(), State::Data(input::new(END_OF_INPUT, b"test "), 23)); - assert_eq!(n2, 1); - } - - #[test] - fn input_propagation() { - let mut n1_calls = 0; - let mut n2_calls = 0; - - let i1 = input::new(DEFAULT, b"test1").ret::<_, ()>(23); - let i2 = input::new(END_OF_INPUT, b"test2").ret::<_, ()>(24); - - let r1: ParseResult<_, _, ()> = i1.bind(|i, t| { n1_calls += 1; i.ret(t) }); - let r2: ParseResult<_, _, ()> = i2.bind(|i, t| { n2_calls += 1; i.ret(t) }); - - assert_eq!(r1.0, State::Data(input::new(DEFAULT, b"test1"), 23)); - assert_eq!(r2.0, State::Data(input::new(END_OF_INPUT, b"test2"), 24)); - assert_eq!(n1_calls, 1); - assert_eq!(n2_calls, 1); - } - - #[test] - fn error_propagation() { - let mut n1_calls = 0; - let mut n2_calls = 0; - - let i1 = input::new(DEFAULT, b"test1").err::<(), _>(23); - let i2 = input::new(END_OF_INPUT, b"test2").err::<(), _>(24); - - let r1 = i1.bind(|i, t| { n1_calls += 1; i.ret(t) }); - let r2 = i2.bind(|i, t| { n2_calls += 1; i.ret(t) }); - - assert_eq!(r1.0, State::Error(b"test1", 23)); - assert_eq!(r2.0, State::Error(b"test2", 24)); - assert_eq!(n1_calls, 0); - assert_eq!(n2_calls, 0); - } - - #[test] - fn incomplete_propagation() { - let mut n1_calls = 0; - let mut n2_calls = 0; - - let i1 = input::new(DEFAULT, b"test1").incomplete::<(), ()>(23); - let i2 = input::new(END_OF_INPUT, b"test2").incomplete::<(), ()>(24); - - let r1: ParseResult<_, _, ()> = i1.bind(|i, t| { n1_calls += 1; i.ret(t) }); - let r2: ParseResult<_, _, ()> = i2.bind(|i, t| { n2_calls += 1; i.ret(t) }); - - assert_eq!(r1.0, State::Incomplete(23)); - assert_eq!(r2.0, State::Incomplete(24)); - assert_eq!(n1_calls, 0); - assert_eq!(n2_calls, 0); - } -} diff --git a/src/parsers.rs b/src/parsers.rs index 84cc1393..10f6f962 100644 --- a/src/parsers.rs +++ b/src/parsers.rs @@ -2,12 +2,18 @@ use std::mem; -use input::Input; -use parse_result::SimpleResult; -use primitives::InputBuffer; +use types::{ + Buffer, + Input, + ParseResult, +}; +use primitives::Primitives; pub use self::error::Error; +/// Result returned from the basic parsers. +pub type SimpleResult = ParseResult::Token>>; + // Only export if we have backtraces enabled, in debug/test profiles the StackFrame is only used // to debug-print. #[cfg(feature="backtrace")] @@ -18,17 +24,15 @@ pub use debugtrace::StackFrame; /// If the buffer length is 0 this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, any}; +/// use chomp::prelude::{parse_only, any}; /// /// assert_eq!(parse_only(any, b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn any(i: Input) -> SimpleResult { - let b = i.buffer(); - - match b.first() { - None => i.incomplete(1), - Some(&c) => i.replace(&b[1..]).ret(c), +pub fn any(mut i: I) -> SimpleResult { + match i.pop() { + Some(c) => i.ret(c), + None => i.err(Error::unexpected()), } } @@ -38,19 +42,16 @@ pub fn any(i: Input) -> SimpleResult { /// If the buffer length is 0 this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, satisfy}; +/// use chomp::prelude::{parse_only, satisfy}; /// /// assert_eq!(parse_only(|i| satisfy(i, |c| c == b'a'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn satisfy(i: Input, f: F) -> SimpleResult - where F: FnOnce(I) -> bool { - let b = i.buffer(); - - match b.first() { - None => i.incomplete(1), - Some(&c) if f(c) => i.replace(&b[1..]).ret(c), - Some(_) => i.err(Error::unexpected()), +pub fn satisfy(mut i: I, f: F) -> SimpleResult + where F: FnOnce(I::Token) -> bool { + match i.peek() { + Some(c) if f(c) => { i.pop(); i.ret(c) }, + _ => i.err(Error::unexpected()), } } @@ -60,7 +61,7 @@ pub fn satisfy(i: Input, f: F) -> SimpleResult /// ``` /// use std::ascii::AsciiExt; /// -/// use chomp::{parse_only, satisfy_with}; +/// use chomp::prelude::{parse_only, satisfy_with}; /// /// let r = parse_only( /// |i| satisfy_with(i, |c| AsciiExt::to_ascii_uppercase(&c), |c| c == b'T'), @@ -69,22 +70,20 @@ pub fn satisfy(i: Input, f: F) -> SimpleResult /// assert_eq!(r, Ok(b'T')); /// ``` #[inline] -pub fn satisfy_with(i: Input, f: F, p: P) -> SimpleResult - where F: FnOnce(I) -> T, +pub fn satisfy_with(mut i: I, f: F, p: P) -> SimpleResult + where F: FnOnce(I::Token) -> T, P: FnOnce(T) -> bool { - let b = i.buffer(); + match i.peek().map(f) { + Some(c) => { + if p(c.clone()) { + i.pop(); - match b.first().cloned() { - Some(n) => { - let t = f(n); - - if p(t.clone()) { - i.replace(&b[1..]).ret(t) + i.ret(c) } else { i.err(Error::unexpected()) } }, - None => i.incomplete(1), + _ => i.err(Error::unexpected()), } } @@ -93,18 +92,15 @@ pub fn satisfy_with(i: Input, f: F, p: P) -> SimpleR /// If the buffer length is 0 this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, token}; +/// use chomp::prelude::{parse_only, token}; /// /// assert_eq!(parse_only(|i| token(i, b'a'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn token(i: Input, t: I) -> SimpleResult { - let b = i.buffer(); - - match b.first() { - None => i.incomplete(1), - Some(&c) if t == c => i.replace(&b[1..]).ret(c), - Some(_) => i.err(Error::expected(t)), +pub fn token(mut i: I, t: I::Token) -> SimpleResult { + match i.peek() { + Some(c) if c == t => { i.pop(); i.ret(c) }, + _ => i.err(Error::expected(t)), } } @@ -113,18 +109,15 @@ pub fn token(i: Input, t: I) -> SimpleResult { /// If the buffer length is 0 this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, not_token}; +/// use chomp::prelude::{parse_only, not_token}; /// /// assert_eq!(parse_only(|i| not_token(i, b'b'), b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn not_token(i: Input, t: I) -> SimpleResult { - let b = i.buffer(); - - match b.first() { - None => i.incomplete(1), - Some(&c) if t != c => i.replace(&b[1..]).ret(c), - Some(_) => i.err(Error::unexpected()), +pub fn not_token(mut i: I, t: I::Token) -> SimpleResult { + match i.peek() { + Some(c) if c != t => { i.pop(); i.ret(c) }, + _ => i.err(Error::unexpected()), } } @@ -134,17 +127,17 @@ pub fn not_token(i: Input, t: I) -> SimpleResult { /// This parser is never considered incomplete. /// /// ``` -/// use chomp::{parse_only, peek}; +/// use chomp::prelude::{parse_only, peek}; /// /// assert_eq!(parse_only(peek, b"abc"), Ok(Some(b'a'))); /// /// assert_eq!(parse_only(peek, b""), Ok(None)); /// ``` #[inline] -pub fn peek(i: Input) -> SimpleResult> { - let d = i.buffer().first().cloned(); +pub fn peek(mut i: I) -> SimpleResult> { + let t = i.peek(); - i.ret(d) + i.ret(t) } /// Matches any item but does not consume it. @@ -152,15 +145,15 @@ pub fn peek(i: Input) -> SimpleResult> { /// If the buffer length is 0 this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, peek_next}; +/// use chomp::prelude::{parse_only, peek_next}; /// /// assert_eq!(parse_only(peek_next, b"abc"), Ok(b'a')); /// ``` #[inline] -pub fn peek_next(i: Input) -> SimpleResult { - match i.buffer().first().cloned() { - None => i.incomplete(1), +pub fn peek_next(mut i: I) -> SimpleResult { + match i.peek() { Some(c) => i.ret(c), + None => i.err(Error::unexpected()), } } @@ -169,18 +162,16 @@ pub fn peek_next(i: Input) -> SimpleResult { /// If the buffer length is less than ``num`` this parser is considered incomplete. /// /// ``` -/// use chomp::{parse_only, take}; +/// use chomp::prelude::{parse_only, take}; /// /// assert_eq!(parse_only(|i| take(i, 3), b"abcd"), Ok(&b"abc"[..])); /// ``` #[inline] -pub fn take(i: Input, num: usize) -> SimpleResult { - let b = i.buffer(); - - if num <= b.len() { - i.replace(&b[num..]).ret(&b[..num]) - } else { - i.incomplete(num - b.len()) +pub fn take(mut i: I, num: usize) -> SimpleResult { + match i.consume(num) { + Some(b) => i.ret(b), + // TODO: Proper incomplete error here? + None => i.err(Error::unexpected()), } } @@ -190,7 +181,7 @@ pub fn take(i: Input, num: usize) -> SimpleResult { /// more input which needs to be matched. /// /// ``` -/// use chomp::{parse_only, take_while}; +/// use chomp::prelude::{parse_only, take_while}; /// /// let r = parse_only(|i| take_while(i, |c| c == b'a' || c == b'b'), b"abcdcba"); /// @@ -200,30 +191,18 @@ pub fn take(i: Input, num: usize) -> SimpleResult { /// Without managing to match anything: /// /// ``` -/// use chomp::{parse_only, take_while}; +/// use chomp::prelude::{parse_only, take_while}; /// /// let r = parse_only(|i| take_while(i, |c| c == b'z'), b"abcdcba"); /// /// assert_eq!(r, Ok(&b""[..])); /// ``` #[inline] -pub fn take_while(i: Input, f: F) -> SimpleResult - where F: Fn(I) -> bool { - let b = i.buffer(); - - match b.iter().position(|c| f(*c) == false) { - Some(n) => i.replace(&b[n..]).ret(&b[..n]), - // TODO: Should this following 1 be something else, seeing as take_while1 is potentially - // infinite? - None => if i.is_last_slice() { - // Last slice and we have just read everything of it, replace with zero-sized slice: - // Hack to avoid branch and overflow, does not matter where this zero-sized slice is - // allocated - i.replace(&b[..0]).ret(b) - } else { - i.incomplete(1) - }, - } +pub fn take_while(mut i: I, f: F) -> SimpleResult + where F: FnMut(I::Token) -> bool { + let b = i.consume_while(f); + + i.ret(b) } /// Matches all items while ``f`` returns true, if at least one item matched this parser succeeds @@ -233,33 +212,39 @@ pub fn take_while(i: Input, f: F) -> SimpleResult /// more input which needs to be matched. If zero items were matched an error will be returned. /// /// ``` -/// use chomp::{parse_only, take_while1}; +/// use chomp::prelude::{parse_only, take_while1}; /// /// let r = parse_only(|i| take_while1(i, |c| c == b'a' || c == b'b'), b"abcdcba"); /// /// assert_eq!(r, Ok(&b"ab"[..])); /// ``` #[inline] -pub fn take_while1(i: Input, f: F) -> SimpleResult - where F: Fn(I) -> bool { - let b = i.buffer(); - - match b.iter().position(|c| f(*c) == false) { - Some(0) => i.err(Error::unexpected()), - Some(n) => i.replace(&b[n..]).ret(&b[..n]), - // TODO: Should this following 1 be something else, seeing as take_while1 is potentially - // infinite? - None => if b.len() > 0 && i.is_last_slice() { - // Last slice and we have just read everything of it, replace with zero-sized slice: - // Hack to avoid branch and overflow, does not matter where this zero-sized slice is - // allocated - i.replace(&b[..0]).ret(b) - } else { - i.incomplete(1) - }, +pub fn take_while1(mut i: I, f: F) -> SimpleResult + where F: FnMut(I::Token) -> bool { + let b = i.consume_while(f); + + if b.is_empty() { + i.err(Error::unexpected()) + } else { + i.ret(b) } } +/// Skips over tokens in the input until `f` returns false. +/// +/// ``` +/// use chomp::prelude::{parse_only, skip_while}; +/// +/// assert_eq!(parse_only(|i| skip_while(i, |c| c == b'a'), &b"aaabc"[..]), Ok(())); +/// ``` +#[inline] +pub fn skip_while(mut i: I, f: F) -> SimpleResult + where F: FnMut(I::Token) -> bool { + i.skip_while(f); + + i.ret(()) +} + /// Matches all items until ``f`` returns true, all items to that point will be returned as a slice /// upon success. /// @@ -267,22 +252,31 @@ pub fn take_while1(i: Input, f: F) -> SimpleResult /// more input which needs to be matched. /// /// ``` -/// use chomp::{parse_only, take_till}; +/// use chomp::prelude::{parse_only, take_till}; /// /// let r = parse_only(|i| take_till(i, |c| c == b'd'), b"abcdef"); /// /// assert_eq!(r, Ok(&b"abc"[..])); /// ``` #[inline] -pub fn take_till(i: Input, f: F) -> SimpleResult - where F: Fn(I) -> bool { - let b = i.buffer(); +pub fn take_till(mut i: I, mut f: F) -> SimpleResult + where F: FnMut(I::Token) -> bool { + let mut ok = false; + + let b = i.consume_while(|c| { + if f(c) { + ok = true; + + false + } else { + true + } + }); - match b.iter().cloned().position(f) { - Some(n) => i.replace(&b[n..]).ret(&b[0..n]), - // TODO: Should this following 1 be something else, seeing as take_while1 is potentially - // infinite? - None => i.incomplete(1), + if ok { + i.ret(b) + } else { + i.err(Error::unexpected()) } } @@ -290,7 +284,7 @@ pub fn take_till(i: Input, f: F) -> SimpleResult /// the predicate returns `None`. /// /// ``` -/// use chomp::{parse_only, scan}; +/// use chomp::prelude::{parse_only, scan}; /// /// let p = |i| scan(i, false, |s, c| match (s, c) { /// (true, b'/') => None, @@ -301,23 +295,19 @@ pub fn take_till(i: Input, f: F) -> SimpleResult /// assert_eq!(parse_only(p, b"/*test*of*scan*/ foo"), Ok(&b"/*test*of*scan*"[..])); /// ``` #[inline] -pub fn scan(i: Input, s: S, mut f: F) -> SimpleResult - where F: FnMut(S, I) -> Option { - let b = i.buffer(); +pub fn scan(mut i: I, s: S, mut f: F) -> SimpleResult + where F: FnMut(S, I::Token) -> Option { let mut state = Some(s); - match b.iter().position(|&c| { state = f(mem::replace(&mut state, None).unwrap(), c); state.is_none()}) { - Some(n) => i.replace(&b[n..]).ret(&b[0..n]), - // TODO: Should this following 1 be something else, seeing as take_while1 is potentially - // infinite? - None => i.incomplete(1), - } + let b = i.consume_while(|c| { state = f(mem::replace(&mut state, None).expect("scan: Failed to obtain state, consume_while most likely called closure after end"), c); state.is_some() }); + + i.ret(b) } /// Like `scan` but generalized to return the final state of the scanner. /// /// ``` -/// use chomp::{parse_only, run_scanner}; +/// use chomp::prelude::{parse_only, run_scanner}; /// /// let p = |i| run_scanner(i, 0, |s, c| match (s, c) { /// (b'*', b'/') => None, @@ -328,34 +318,33 @@ pub fn scan(i: Input, s: S, mut f: F) -> SimpleResult /// ``` #[inline] // TODO: Remove Copy bound on S -pub fn run_scanner(i: Input, s: S, mut f: F) -> SimpleResult - where F: FnMut(S, I) -> Option { - let b = i.buffer(); +pub fn run_scanner(mut i: I, s: S, mut f: F) -> SimpleResult + where F: FnMut(S, I::Token) -> Option { let mut state = s; - match b.iter().position(|&c| { let t = f(state, c); match t { None => true, Some(v) => { state = v; false } } }) { - Some(n) => i.replace(&b[n..]).ret((&b[0..n], state)), - // TODO: Should this following 1 be something else, seeing as take_while1 is potentially - // infinite? - None => i.incomplete(1), - } + let b = i.consume_while(|c| { + let t = f(state, c); + match t { + None => false, + Some(v) => { state = v; true } + } + }); + + i.ret((b, state)) } /// Matches the remainder of the buffer and returns it, always succeeds. /// /// ``` -/// use chomp::{parse_only, take_remainder}; +/// use chomp::prelude::{parse_only, take_remainder}; /// /// assert_eq!(parse_only(take_remainder, b"abcd"), Ok(&b"abcd"[..])); /// ``` #[inline] -pub fn take_remainder(i: Input) -> SimpleResult { - let b = i.buffer(); - // Last slice and we have just read everything of it, replace with zero-sized slice: - // - // Hack to avoid branch and overflow, does not matter where this zero-sized slice is - // allocated as long as it is the same origin slice - i.replace(&b[..0]).ret(b) +pub fn take_remainder(mut i: I) -> SimpleResult { + let b = i.consume_remaining(); + + i.ret(b) } /// Matches the given slice against the parser, returning the matched slice upon success. @@ -364,42 +353,48 @@ pub fn take_remainder(i: Input) -> SimpleResult { /// incomplete. /// /// ``` -/// use chomp::{parse_only, string}; +/// use chomp::prelude::{parse_only, string}; /// /// assert_eq!(parse_only(|i| string(i, b"abc"), b"abcdef"), Ok(&b"abc"[..])); /// ``` +// TODO: Does not actually work with &str yet #[inline] -pub fn string<'a, 'b, I: Copy + PartialEq>(i: Input<'a, I>, s: &'b [I]) - -> SimpleResult<'a, I, &'a [I]> { - let b = i.buffer(); - - if s.len() > b.len() { - return i.incomplete(s.len() - b.len()); - } - - let d = &b[..s.len()]; +pub fn string>(mut i: I, s: &[T]) + -> SimpleResult { + let mut n = 0; + let len = s.len(); + + // TODO: There has to be some more efficient way here + let b = i.consume_while(|c| { + if n >= len || c != s[n] { + false + } + else { + n += 1; - for j in 0..s.len() { - if s[j] != d[j] { - return i.replace(&b[j..]).err(Error::expected(d[j])) + true } - } + }); - i.replace(&b[s.len()..]).ret(d) + if n >= len { + i.ret(b) + } else { + i.err(Error::expected(s[n])) + } } /// Matches the end of the input. /// /// ``` -/// use chomp::{parse_only, token, eof}; +/// use chomp::prelude::{parse_only, token, eof}; /// /// let r = parse_only(|i| token(i, b'a').then(eof), b"a"); /// /// assert_eq!(r, Ok(())); /// ``` #[inline] -pub fn eof(i: Input) -> SimpleResult { - if i.buffer().len() == 0 && i.is_last_slice() { +pub fn eof(mut i: I) -> SimpleResult { + if i.peek() == None { i.ret(()) } else { i.err(Error::unexpected()) @@ -478,8 +473,8 @@ mod error { where I: fmt::Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0.as_ref() { - Some(ref c) => write!(f, "expected {:?}", *c), - None => write!(f, "unexpected"), + Some(c) => write!(f, "expected {:?}", *c), + None => write!(f, "unexpected"), } } } @@ -533,8 +528,9 @@ mod error { /// /// Should be used when a specific token was expected. #[inline(always)] - pub fn expected(_i: I) -> Self { - create_error!(Some(_i)) + #[allow(unused_variables)] + pub fn expected(i: I) -> Self { + create_error!(Some(i)) } /// Returns `Some(&I)` if a specific token was expected, `None` otherwise. @@ -563,11 +559,9 @@ mod error { #[cfg(test)] mod test { - use primitives::input::{new, DEFAULT, END_OF_INPUT}; use primitives::IntoInner; - use primitives::State; use super::*; - use {Input, SimpleResult}; + use types::{Input, ParseResult}; #[test] fn parse_decimal() { @@ -575,118 +569,114 @@ mod test { c >= b'0' && c <= b'9' } - fn decimal(i: Input) -> SimpleResult { + fn decimal<'i, I: Input>(i: I) -> SimpleResult { take_while1(i, is_digit).bind(|i, bytes| i.ret(bytes.iter().fold(0, |a, b| a * 10 + (b - b'0') as usize))) } - let i = new(END_OF_INPUT, b"123.4567 "); + let i = &b"123.4567 "[..]; let p = decimal(i).bind(|i, real| token(i, b'.').bind(|i, _| decimal(i).bind(|i, frac| i.ret((real, frac))))); - let d: SimpleResult<_, _> = p.bind(|i, num| take_remainder(i) + // ParseResult necessary here due to inference, for some reason is + // `Error<::Token>` not specific enough to actually help inference. + let d: ParseResult<_, _, Error> = p.bind(|i, num| take_remainder(i) .bind(|i, r| i.ret((r, num)))); - assert_eq!(d.into_inner(), State::Data(new(END_OF_INPUT, b""), (&b" "[..], (123, 4567)))); + assert_eq!(d.into_inner(), (&b""[..], Ok((&b" "[..], (123, 4567))))); } #[test] fn parse_remainder_empty() { - let i = new(END_OF_INPUT, b""); - - let r = take_remainder(i); - - assert_eq!(r.into_inner(), State::Data(new(END_OF_INPUT, b""), &b""[..])); + assert_eq!(take_remainder(&b""[..]).into_inner(), (&b""[..], Ok(&b""[..]))); } #[test] fn take_while1_empty() { - let n = new(END_OF_INPUT, b""); - - let r = take_while1(n, |_| true); - - assert_eq!(r.into_inner(), State::Incomplete(1)); + assert_eq!(take_while1(&b""[..], |_| true).into_inner(), (&b""[..], Err(Error::unexpected()))); } #[test] fn token_test() { - assert_eq!(token(new(DEFAULT, b""), b'a').into_inner(), State::Incomplete(1)); - assert_eq!(token(new(DEFAULT, b"ab"), b'a').into_inner(), State::Data(new(DEFAULT, b"b"), b'a')); - assert_eq!(token(new(DEFAULT, b"bb"), b'a').into_inner(), State::Error(b"bb", Error::expected(b'a'))); + assert_eq!(token(&b""[..], b'a').into_inner(), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(token(&b"ab"[..], b'a').into_inner(), (&b"b"[..], Ok(b'a'))); + assert_eq!(token(&b"bb"[..], b'a').into_inner(), (&b"bb"[..], Err(Error::expected(b'a')))); } #[test] fn take_test() { - assert_eq!(take(new(DEFAULT, b"a"), 1).into_inner(), State::Data(new(DEFAULT, b""), &b"a"[..])); - assert_eq!(take(new(DEFAULT, b"a"), 2).into_inner(), State::Incomplete(1)); - assert_eq!(take(new(DEFAULT, b"a"), 3).into_inner(), State::Incomplete(2)); - assert_eq!(take(new(DEFAULT, b"ab"), 1).into_inner(), State::Data(new(DEFAULT, b"b"), &b"a"[..])); - assert_eq!(take(new(DEFAULT, b"ab"), 2).into_inner(), State::Data(new(DEFAULT, b""), &b"ab"[..])); + assert_eq!(take(&b""[..], 0).into_inner(), (&b""[..], Ok(&b""[..]))); + assert_eq!(take(&b"a"[..], 0).into_inner(), (&b"a"[..], Ok(&b""[..]))); + assert_eq!(take(&b"a"[..], 1).into_inner(), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take(&b"a"[..], 2).into_inner(), (&b"a"[..], Err(Error::unexpected()))); + assert_eq!(take(&b"a"[..], 3).into_inner(), (&b"a"[..], Err(Error::unexpected()))); + assert_eq!(take(&b"ab"[..], 1).into_inner(), (&b"b"[..], Ok(&b"a"[..]))); + assert_eq!(take(&b"ab"[..], 2).into_inner(), (&b""[..], Ok(&b"ab"[..]))); } #[test] fn take_while_test() { - assert_eq!(take_while(new(DEFAULT, b"abc"), |c| c != b'b').into_inner(), State::Data(new(DEFAULT, b"bc"), &b"a"[..])); - assert_eq!(take_while(new(DEFAULT, b"bbc"), |c| c != b'b').into_inner(), State::Data(new(DEFAULT, b"bbc"), &b""[..])); - assert_eq!(take_while(new(END_OF_INPUT, b"bbc"), |c| c != b'b').into_inner(), State::Data(new(END_OF_INPUT, b"bbc"), &b""[..])); - assert_eq!(take_while(new(END_OF_INPUT, b"abc"), |c| c != b'b').into_inner(), State::Data(new(END_OF_INPUT, b"bc"), &b"a"[..])); - // TODO: Update when the incomplete type has been updated - assert_eq!(take_while(new(DEFAULT, b"acc"), |c| c != b'b').into_inner(), State::Incomplete(1)); - assert_eq!(take_while(new(END_OF_INPUT, b"acc"), |c| c != b'b').into_inner(), State::Data(new(END_OF_INPUT, b""), &b"acc"[..])); + assert_eq!(take_while(&b""[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b""[..]))); + assert_eq!(take_while(&b"a"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take_while(&b"b"[..], |c| c != b'b').into_inner(), (&b"b"[..], Ok(&b""[..]))); + assert_eq!(take_while(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Ok(&b""[..]))); + assert_eq!(take_while(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Ok(&b""[..]))); + assert_eq!(take_while(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while(&b"acc"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"acc"[..]))); } #[test] fn take_while1_test() { - assert_eq!(take_while1(new(DEFAULT, b"abc"), |c| c != b'b').into_inner(), State::Data(new(DEFAULT, b"bc"), &b"a"[..])); - assert_eq!(take_while1(new(DEFAULT, b"bbc"), |c| c != b'b').into_inner(), State::Error(&b"bbc"[..], Error::unexpected())); - assert_eq!(take_while1(new(END_OF_INPUT, b"bbc"), |c| c != b'b').into_inner(), State::Error(&b"bbc"[..], Error::unexpected())); - assert_eq!(take_while1(new(END_OF_INPUT, b"abc"), |c| c != b'b').into_inner(), State::Data(new(END_OF_INPUT, b"bc"), &b"a"[..])); - // TODO: Update when the incomplete type has been updated - assert_eq!(take_while1(new(DEFAULT, b"acc"), |c| c != b'b').into_inner(), State::Incomplete(1)); - assert_eq!(take_while1(new(END_OF_INPUT, b"acc"), |c| c != b'b').into_inner(), State::Data(new(END_OF_INPUT, b""), &b"acc"[..])); + assert_eq!(take_while1(&b""[..], |c| c != b'b').into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(take_while1(&b"a"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(&b"b"[..], |c| c != b'b').into_inner(), (&b"b"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(&b"ab"[..], |c| c != b'b').into_inner(), (&b"b"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(&b"bbc"[..], |c| c != b'b').into_inner(), (&b"bbc"[..], Err(Error::unexpected()))); + assert_eq!(take_while1(&b"abc"[..], |c| c != b'b').into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(take_while1(&b"acc"[..], |c| c != b'b').into_inner(), (&b""[..], Ok(&b"acc"[..]))); } #[test] fn peek_next_test() { - assert_eq!(peek_next(new(DEFAULT, b"abc")).into_inner(), State::Data(new(DEFAULT, b"abc"), b'a')); - assert_eq!(peek_next(new(END_OF_INPUT, b"abc")).into_inner(), State::Data(new(END_OF_INPUT, b"abc"), b'a')); - assert_eq!(peek_next(new(DEFAULT, b"")).into_inner(), State::Incomplete(1)); - assert_eq!(peek_next(new(END_OF_INPUT, b"")).into_inner(), State::Incomplete(1)); + assert_eq!(peek_next(&b"abc"[..]).into_inner(), (&b"abc"[..], Ok(b'a'))); + assert_eq!(peek_next(&b"abc"[..]).into_inner(), (&b"abc"[..], Ok(b'a'))); + assert_eq!(peek_next(&b""[..]).into_inner(), (&b""[..], Err(Error::unexpected()))); + assert_eq!(peek_next(&b""[..]).into_inner(), (&b""[..], Err(Error::unexpected()))); } #[test] fn satisfy_with_test() { let mut m1 = 0; let mut n1 = 0; - assert_eq!(satisfy_with(new(DEFAULT, b"abc"), |m| { m1 += 1; m % 8 }, |n| { n1 += 1; n == 1 }).into_inner(), State::Data(new(DEFAULT, b"bc"), 1)); + assert_eq!(satisfy_with(&b"abc"[..], |m| { m1 += 1; m % 8 }, |n| { n1 += 1; n == 1 }).into_inner(), (&b"bc"[..], Ok(1))); assert_eq!(m1, 1); assert_eq!(n1, 1); let mut m2 = 0; let mut n2 = 0; - assert_eq!(satisfy_with(new(DEFAULT, b""), |m| { m2 += 1; m % 8 }, |n| { n2 += 1; n == 1 }).into_inner(), State::Incomplete(1)); + assert_eq!(satisfy_with(&b""[..], |m| { m2 += 1; m % 8 }, |n| { n2 += 1; n == 1 }).into_inner(), (&b""[..], Err(Error::unexpected()))); assert_eq!(m2, 0); assert_eq!(n2, 0); } #[test] fn string_test() { - assert_eq!(string(new(DEFAULT, b"abc"), b"a").into_inner(), State::Data(new(DEFAULT, b"bc"), &b"a"[..])); - assert_eq!(string(new(DEFAULT, b"abc"), b"ab").into_inner(), State::Data(new(DEFAULT, b"c"), &b"ab"[..])); - assert_eq!(string(new(DEFAULT, b"abc"), b"abc").into_inner(), State::Data(new(DEFAULT, b""), &b"abc"[..])); - assert_eq!(string(new(DEFAULT, b"abc"), b"abcd").into_inner(), State::Incomplete(1)); - assert_eq!(string(new(DEFAULT, b"abc"), b"abcde").into_inner(), State::Incomplete(2)); - assert_eq!(string(new(DEFAULT, b"abc"), b"ac").into_inner(), State::Error(b"bc", Error::expected(b'b'))); - - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"a").into_inner(), State::Data(new(END_OF_INPUT, b"bc"), &b"a"[..])); - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"ab").into_inner(), State::Data(new(END_OF_INPUT, b"c"), &b"ab"[..])); - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"abc").into_inner(), State::Data(new(END_OF_INPUT, b""), &b"abc"[..])); - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"abcd").into_inner(), State::Incomplete(1)); - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"abcde").into_inner(), State::Incomplete(2)); - assert_eq!(string(new(END_OF_INPUT, b"abc"), b"ac").into_inner(), State::Error(b"bc", Error::expected(b'b'))); + assert_eq!(string(&b""[..], b"").into_inner(), (&b""[..], Ok(&b""[..]))); + assert_eq!(string(&b""[..], b"a").into_inner(), (&b""[..], Err(Error::expected(b'a')))); + assert_eq!(string(&b"a"[..], b"a").into_inner(), (&b""[..], Ok(&b"a"[..]))); + assert_eq!(string(&b"b"[..], b"a").into_inner(), (&b"b"[..], Err(Error::expected(b'a')))); + assert_eq!(string(&b"abc"[..], b"a").into_inner(), (&b"bc"[..], Ok(&b"a"[..]))); + assert_eq!(string(&b"abc"[..], b"ab").into_inner(), (&b"c"[..], Ok(&b"ab"[..]))); + assert_eq!(string(&b"abc"[..], b"abc").into_inner(), (&b""[..], Ok(&b"abc"[..]))); + assert_eq!(string(&b"abc"[..], b"abcd").into_inner(), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string(&b"abc"[..], b"abcde").into_inner(), (&b""[..], Err(Error::expected(b'd')))); + assert_eq!(string(&b"abc"[..], b"ac").into_inner(), (&b"bc"[..], Err(Error::expected(b'c')))); } #[test] diff --git a/src/primitives.rs b/src/primitives.rs new file mode 100644 index 00000000..23879928 --- /dev/null +++ b/src/primitives.rs @@ -0,0 +1,125 @@ +//! Module used to construct fundamental parsers and combinators. +//! +//! The `Primitives` trait allows access to the primitive methods of the `Input` trait. These +//! methods are hidden in the documentation to make it easier to read the documentation since the +//! methods are not useful when using the library or writing primitive parsers. + +use types::Input; + +/// Consumes self and reveals the inner state. +/// +/// # Primitive +/// +/// Only used by fundamental parsers and combinators. +pub trait IntoInner { + /// The inner type to be revealed. + type Inner; + + /// **Primitive:** Consumes self and reveals the inner state. + /// + /// # Primitive + /// + /// Only used by fundamental parsers and combinators. + #[inline(always)] + fn into_inner(self) -> Self::Inner; +} + +/// This is a zero-sized type used by the `Primitives` trait implementation to guarantee that +/// access to primitive methods on `Input` only happens when the `Primitives` trait has been +/// imported. +/// +/// It cannot be instantiated outside of the `Primitives` trait blanket implementation. +pub struct Guard(()); + +/// Trait enabling primitive actions on an `Input` type. +/// +/// This trait is automatically implemented for all types implementing `Input` and acts as a +/// gatekeeper to the state-modifying methods of `Input`. +pub trait Primitives: Input { + /// Peeks at the next token in the input without consuming it. `None` if no more input is + /// available. + /// + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. + #[inline(always)] + fn peek(&mut self) -> Option { + self._peek(Guard(())) + } + + /// Pops a token off the start of the input. `None` if no more input is available. + /// + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. + #[inline(always)] + fn pop(&mut self) -> Option { + self._pop(Guard(())) + } + + /// Attempt to consume `n` tokens, if it fails do not advance the position but return `None`. + /// + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. + #[inline(always)] + fn consume(&mut self, n: usize) -> Option { + self._consume(Guard(()), n) + } + + /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that + /// token will be returned as a buffer and discarded from the current input. MUST never run the + /// closure more than once on the exact same token. + /// + /// If the end of the input is reached, the whole input is returned. + /// + /// Note: Is allowed to refill automatically or any other appropriate action if the input does + /// not contain any more data. + #[inline(always)] + fn consume_while(&mut self, f: F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool { + self._consume_while(Guard(()), f) + } + + /// Returns the buffer from the marker to the current position, discarding the + /// backtracking position carried by the marker. + #[inline(always)] + fn consume_from(&mut self, m: Self::Marker) -> Self::Buffer { + self._consume_from(Guard(()), m) + } + + /// Returns the remainder of the input in a buffer. + /// + /// Note: Will refill the intenal buffer until no more data is available if the underlying + /// implementation supports it. + #[inline(always)] + fn consume_remaining(&mut self) -> Self::Buffer { + self._consume_remaining(Guard(())) + } + + /// Runs the closure `F` on the tokens *in order* until it returns false, all tokens up to that + /// token will be discarded from the current input. + /// + /// MUST never run the closure more than once on the exact same token. + /// + /// If the end of the input is reached, the whole input is discarded. + /// + /// Note: Default implementation uses `consume_while` and makes the assumption that it will + /// optimize away the resulting `Self::Buffer`. + #[inline(always)] + fn skip_while(&mut self, f: F) + where F: FnMut(Self::Token) -> bool { + self._skip_while(Guard(()), f) + } + + /// Marks the current position to be able to backtrack to it using `restore`. + #[inline(always)] + fn mark(&self) -> Self::Marker { + self._mark(Guard(())) + } + + /// Resumes from a previously marked state. + #[inline(always)] + fn restore(self, m: Self::Marker) -> Self { + self._restore(Guard(()), m) + } +} + +impl Primitives for I {} diff --git a/src/types/mod.rs b/src/types/mod.rs new file mode 100644 index 00000000..ca333554 --- /dev/null +++ b/src/types/mod.rs @@ -0,0 +1,903 @@ +//! Types which facillitates the chaining of parsers and their results. + +pub mod numbering; +#[cfg(feature = "tendril")] +pub mod tendril; + +use primitives::{Guard, IntoInner}; + +/// The buffers yielded parsers consuming a sequence of the input. +/// +/// This could either be an owned type or a slice reference depending on the `Input` +/// implementation. +pub trait Buffer: PartialEq { + /// The token type of this buffer. + type Token: Copy + PartialEq; + + /// Applies a function in order on all tokens present in the buffer carrying an accumulator + /// value `B` between invocations. The buffer is consumed as part of the folding and the last + /// value of the accumulator is returned. + // Would be prefereable if there was a &self -> Iterator method, but that does not work for + // owned or maybe owned since the lifetimes will be wrong for one or the other. Higher Ranked + // Trait Bounds (HRTB) does not seem to work either since it is not possible to later + // instantiate the type in a function signature with a concrete lifetime without running into + // an "expected bound lifetime but found concrete lifetime" error. Instantiation for HRTBs seem + // to only take place in the actual code, not when a type is used in eg. a where clause. + fn fold(self, B, F) -> B + where F: FnMut(B, Self::Token) -> B; + + /// Runs the supplied function on a borrow of each token present in the buffer. Invoked in + /// order and once per token. + // Same reason for above for not returning an iterator. + fn iterate(&self, F) + where F: FnMut(Self::Token); + + /// The number of tokens present in this buffer. + fn len(&self) -> usize; + + /// Copies all the tokens in this buffer to a new `Vec`. + fn to_vec(&self) -> Vec; + + /// Consumes self to create an owned vector of tokens. + /// + /// Will allocate if the implementation borrows storage or does not use an owned type + /// compatible with `Vec` internally. + fn into_vec(self) -> Vec; + + /// Returns true if this buffer is empty. + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl<'a, I: Copy + PartialEq> Buffer for &'a [I] { + type Token = I; + + fn fold(self, init: B, f: F) -> B + where F: FnMut(B, Self::Token) -> B { + (&self[..]).iter().cloned().fold(init, f) + } + + fn iterate(&self, mut f: F) + where F: FnMut(Self::Token) { + for c in (&self[..]).iter().cloned() { + f(c) + } + } + + fn len(&self) -> usize { + // Slice to reach inherent method to prevent infinite recursion + (&self[..]).len() + } + + fn to_vec(&self) -> Vec { + (&self[..]).to_vec() + } + + fn into_vec(self) -> Vec { + (&self[..]).to_vec() + } +} + +impl<'a> Buffer for &'a str { + type Token = char; + + fn fold(self, init: B, f: F) -> B + where F: FnMut(B, Self::Token) -> B { + self.chars().fold(init, f) + } + + fn iterate(&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() + } + + fn to_vec(&self) -> Vec { + (&self[..]).chars().collect() + } + + fn into_vec(self) -> Vec { + (&self[..]).chars().collect() + } +} + +/// Linear type containing the parser state, this type is threaded though `bind` and is also the +/// initial type passed to a parser. +/// +/// Coupled with the `ParseResult` type it forms the parser monad: +/// +/// ```ignore +/// Fn*(I, ...) -> ParseResult; +/// ``` +/// +/// where ``Fn*`` is the appropriate closure/function trait, `I` the input type (can be something +/// like `[u8]`), `...` additional parameters to the parser, `T` the carried success type and `E` +/// the potential error type. +pub trait Input: Sized { + /// The token type of the input. + type Token: Copy + PartialEq; + + /// A marker type which is used to backtrack using `_mark` and `_restore`. + /// + /// It should also be possible to use this type to consume the data from the marked position to + /// the current position. + #[doc(hidden)] + type Marker; + + /// The buffer type yielded by this input when multiple tokens are consumed in sequence. + /// + /// Can eg. provide zero-copy parsing if the input type is built to support it. + type Buffer: Buffer; + + /// Returns `t` as a success value in the parsing context. + /// + /// Equivalent to Haskell's `return` function in the `Monad` typeclass. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| + /// // Annotate the error type + /// i.ret::<_, ()>("Wohoo, success!"), + /// b"some input"); + /// + /// assert_eq!(r, Ok("Wohoo, success!")); + /// ``` + #[inline] + fn ret(self, t: T) -> ParseResult { + ParseResult(self, Ok(t)) + } + + /// Returns `e` as an error value in the parsing context. + /// + /// A more general version of Haskell's `fail` function in the `Monad` typeclass. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| + /// // Annotate the value type + /// i.err::<(), _>("Something went wrong"), + /// b"some input"); + /// + /// assert_eq!(r, Err((&b"some input"[..], "Something went wrong"))); + /// ``` + #[inline] + fn err(self, e: E) -> ParseResult { + ParseResult(self, Err(e)) + } + + /// Converts a `Result` into a `ParseResult`, preserving parser state. + /// + /// To convert an `Option` into a `ParseResult` it is recommended to use + /// [`Option::ok_or`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or) + /// or [`Option::ok_or_else`](https://doc.rust-lang.org/std/option/enum.Option.html#method.ok_or_else) + /// in combination with this method. + /// + /// # Examples + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| i.from_result::<_, ()>(Ok("foo")), b"test"); + /// + /// assert_eq!(r, Ok("foo")); + /// + /// let r = parse_only(|i| i.from_result::<(), _>(Err("error message")), b"test"); + /// + /// assert_eq!(r, Err((&b"test"[..], "error message"))); + /// ``` + #[inline] + fn from_result(self, r: Result) -> ParseResult { + ParseResult(self, r) + } + + // Primitive methods + + /// **Primitive:** See `Primitives::peek` for documentation. + #[inline] + #[doc(hidden)] + fn _peek(&mut self, Guard) -> Option; + + /// **Primitive:** See `Primitives::pop` for documentation. + #[inline] + #[doc(hidden)] + fn _pop(&mut self, Guard) -> Option; + + /// **Primitive:** See `Primitives::consume` for documentation. + #[inline] + #[doc(hidden)] + fn _consume(&mut self, Guard, usize) -> Option; + + /// **Primitive:** See `Primitives::consume_while` for documentation. + #[inline] + #[doc(hidden)] + fn _consume_while(&mut self, Guard, F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool; + + /// **Primitive:** See `Primitives::consume_from for documentation. + #[inline] + #[doc(hidden)] + fn _consume_from(&mut self, Guard, Self::Marker) -> Self::Buffer; + + /// **Primitive:** See `Primitives::consume_remaining` for documentation. + #[inline] + #[doc(hidden)] + fn _consume_remaining(&mut self, Guard) -> Self::Buffer; + + /// **Primitive:** See `Primitives::skip_while` for documentation. + #[inline] + #[doc(hidden)] + fn _skip_while(&mut self, g: Guard, f: F) + where F: FnMut(Self::Token) -> bool { + self._consume_while(g, f); + } + + /// **Primitive:** See `Primitives::mark` for documentation. + #[inline] + #[doc(hidden)] + fn _mark(&self, Guard) -> Self::Marker; + + /// **Primitive:** See `Primitives::restore` for documentation. + #[inline] + #[doc(hidden)] + fn _restore(self, Guard, Self::Marker) -> Self; +} + +impl<'a, I: Copy + PartialEq> Input for &'a [I] { + type Token = I; + type Marker = &'a [I]; + type Buffer = &'a [I]; + + #[inline] + fn _peek(&mut self, _g: Guard) -> Option { + self.first().cloned() + } + + #[inline] + fn _pop(&mut self, _g: Guard) -> Option { + self.first().cloned().map(|c| { + *self = &self[1..]; + + c + }) + } + + #[inline] + fn _consume(&mut self, _g: Guard, n: usize) -> Option { + if n > self.len() { + None + } else { + let b = &self[..n]; + + *self = &self[n..]; + + Some(b) + } + } + + #[inline] + fn _consume_while(&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 { + let b = &self[..]; + + *self = &self[..0]; + + b + } + } + + #[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[..0]; + + 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 Token = char; + type Marker = &'a str; + type Buffer = &'a str; + + #[inline] + fn _peek(&mut self, _g: Guard) -> Option { + self.chars().next() + } + + #[inline] + fn _pop(&mut self, _g: Guard) -> Option { + let mut iter = self.char_indices(); + + iter.next().map(|(_, c)| { + match iter.next().map(|(p, _)| p) { + Some(n) => *self = &self[n..], + None => *self = &self[..0], + } + + c + }) + } + + #[inline] + fn _consume(&mut self, _g: Guard, n: usize) -> Option { + match self.char_indices().enumerate().take(n + 1).last() { + // num always equal to n if self contains more than n characters + Some((num, (pos, _))) if n == num => { + let b = &self[..pos]; + + *self = &self[pos..]; + + Some(b) + }, + // num always equal to n - 1 if self contains exactly n characters + Some((num, _)) if n == num + 1 => { + let b = &self[..]; + + *self = &self[..0]; + + Some(b) + }, + _ => None, + } + } + + #[inline] + fn _consume_while(&mut self, _g: Guard, mut f: F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool { + // We need to find the character following the one which did not match + if let Some((pos, _)) = self.char_indices().skip_while(|&(_, c)| f(c)).next() { + let b = &self[..pos]; + + *self = &self[pos..]; + + b + } else { + let b = &self[..]; + + *self = &self[..0]; + + b + } + } + + #[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[..0]; + + b + } + + #[inline] + fn _mark(&self, _g: Guard) -> Self::Marker { + self + } + + #[inline] + fn _restore(self, _g: Guard, m: Self::Marker) -> Self { + m + } +} + +/// A type alias for an `Input` with a token type of `u8`. +pub trait U8Input: Input {} + +impl U8Input for T + where T: Input {} + +/// The basic return type of a parser. +/// +/// This type satisfies a variant of the `Monad` typeclass. Due to the limitations of Rust's +/// return types closures cannot be returned without boxing which has an unacceptable performance +/// impact. +/// +/// To get around this issue and still provide a simple to use and safe (as in hard to accidentally +/// violate the monad laws or the assumptions taken by the parser type) an `Input` wrapper is +/// provided which ensures that the parser state is carried properly through every call to `bind`. +/// This is also known as a Linear Type (emulated through hiding destructors and using the +/// annotation `#[must_use]`). +/// +/// Do-notation is provided by the macro `parse!`. +/// +/// # Equivalence with Haskell's `Monad` typeclass: +/// +/// ```text +/// f >>= g ≡ f(m).bind(g) +/// f >> g ≡ f(m).then(g) +/// return a ≡ m.ret(a) +/// fail a ≡ m.err(a) +/// ``` +/// +/// It also satisfies the monad laws: +/// +/// ```text +/// return a >>= f ≡ f a +/// m >>= return ≡ m +/// (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g) +/// ``` +#[must_use] +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct ParseResult(I, Result); + +impl ParseResult { + /// Sequentially composes the result with a parse action `f`, passing any produced value as + /// the second parameter. + /// + /// The first parameter to the supplied function `f` is the parser state (`Input`). This + /// state is then passed on to other parsers or used to return a value or an error. + /// + /// # Automatic conversion of `E` + /// + /// The error value `E` will automatically be converted using the `From` trait to the + /// desired type. The downside with this using the current stable version of Rust (1.4) is that + /// the type inferrence will currently not use the default value for the generic `V` and will + /// therefore require extra type hint for the error. + /// + /// # Examples + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| { + /// i.ret("data".to_owned()) + /// // Explicitly state the error type + /// .bind::<_, _, ()>(|i, x| i.ret(x + " here!")) + /// }, + /// b"test"); + /// + /// assert_eq!(r, Ok("data here!".to_owned())); + /// ``` + /// + /// Wrapping the expression in a function will both make it easier to compose and also provides + /// the type-hint for the error in the function signature: + /// + /// ``` + /// use chomp::prelude::{Input, ParseResult, parse_only}; + /// + /// fn parser(i: I, n: i32) -> ParseResult { + /// i.ret(n + 10) + /// } + /// + /// let r = parse_only(|i| i.ret(23).bind(parser), b"test"); + /// + /// assert_eq!(r, Ok(33)); + /// ``` + #[inline] + pub fn bind(self, f: F) -> ParseResult + where F: FnOnce(I, T) -> ParseResult, + V: From { + match self.1 { + Ok(t) => f(self.0, t).map_err(From::from), + Err(e) => ParseResult(self.0, Err(From::from(e))), + } + } + + /// Sequentially composes the result with a parse action `f`, discarding any produced value. + /// + /// The first parameter to the supplied function `f` is the parser state (`Input`). This + /// state is then passed on to other parsers or used to return a value or an error. + /// + /// # Relation to `bind` + /// + /// ```text + /// ParseResult::then(g) ≡ ParseResult::bind(|i, _| g(i)) + /// ``` + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, SimpleResult, parse_only}; + /// + /// fn g(i: I) -> SimpleResult { + /// i.ret("testing!") + /// } + /// + /// let r1 = parse_only(|i| i.ret("initial state").bind(|i, _| g(i)), b"data"); + /// let r2 = parse_only(|i| i.ret("initial state").then(g), b"data"); + /// + /// assert_eq!(r1, Ok("testing!")); + /// assert_eq!(r2, Ok("testing!")); + /// ``` + #[inline] + pub fn then(self, f: F) -> ParseResult + where F: FnOnce(I) -> ParseResult, + V: From { + self.bind(|i, _| f(i)) + } + + /// Applies the function `f` on the contained data if the parser is in a success state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{parse_only, any}; + /// + /// let r = parse_only(|i| any(i).map(|c| c + 12), b"abc"); + /// + /// assert_eq!(r, Ok(b'm')); + /// ``` + #[inline] + pub fn map(self, f: F) -> ParseResult + where F: FnOnce(T) -> U { + match self { + ParseResult(i, Ok(t)) => ParseResult(i, Ok(f(t))), + ParseResult(i, Err(e)) => ParseResult(i, Err(e)), + } + } + + /// Applies the function `f` on the contained error if the parser is in an error state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{Input, parse_only}; + /// + /// let r = parse_only(|i| i.err::<(), _>("this is") + /// .map_err(|e| e.to_owned() + " an error"), + /// b"foo"); + /// + /// assert_eq!(r, Err((&b"foo"[..], "this is an error".to_owned()))); + /// ``` + #[inline] + pub fn map_err(self, f: F) -> ParseResult + where F: FnOnce(E) -> V { + match self { + ParseResult(i, Ok(t)) => ParseResult(i, Ok(t)), + ParseResult(i, Err(e)) => ParseResult(i, Err(f(e))), + } + } + + /// Calls the function `f` with a reference of the contained data if the parser is in a success + /// state. + /// + /// # Example + /// + /// ``` + /// use chomp::prelude::{parse_only, take_while}; + /// + /// let r = parse_only(|i| take_while(i, |c| c != b' ').inspect(|b| { + /// println!("{:?}", b); // Prints "test" + /// }), b"test and more"); + /// + /// assert_eq!(r, Ok(&b"test"[..])); + /// ``` + #[inline] + pub fn inspect(self, f: F) -> ParseResult + where F: FnOnce(&T) { + if let Ok(ref t) = self.1 { + f(t) + } + + self + } +} + +/// **Primitive:** Consumes the `ParseResult` and exposes the internal state. +/// +/// # Primitive +/// +/// Only used by fundamental parsers and combinators. +/// +/// # Motivation +/// +/// The `ParseResult` type is a semi-linear type, supposed to act like a linear type while used in +/// a parsing context to carry the state. Normally it should be as restrictive as the `Input` type +/// in terms of how much it exposes its internals, but the `IntoInner` trait implementation +/// allows fundamental parsers and combinators to expose the inner `Result` of the `ParseResult` +/// and act on this. +impl IntoInner for ParseResult { + type Inner = (I, Result); + + #[inline(always)] + fn into_inner(self) -> Self::Inner { + (self.0, self.1) + } +} + +#[cfg(test)] +pub mod test { + use super::{Buffer, Input, ParseResult}; + use primitives::IntoInner; + use std::fmt::Debug; + + #[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 = 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: I, n: u32) -> ParseResult { + i.ret(n + 1) + } + + let a = 123; + // return a >>= f + let lhs = b"test".ret(a).bind(f); + // f a + 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); + + // m1 >>= ret === m2 + 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: I, num: u32) -> ParseResult { + i.ret((num + 1) as u64) + } + + fn g(i: I, num: u64) -> ParseResult { + i.ret(num * 2) + } + + let lhs_m = b"test".ret::<_, ()>(2); + let rhs_m = b"test".ret::<_, ()>(2); + + // (m >>= f) >>= g + let lhs = lhs_m.bind(f).bind(g); + // m >>= (\x -> f x >>= 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 primitives::IntoInner; + + let mut n1 = 0; + let mut n2 = 0; + let i1 = b"test ".ret::(23); + let i2 = b"test ".ret::(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: I, n: u32) -> ParseResult { 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_slice() { + run_primitives_test(&b"abc"[..], |x| x); + } + + #[test] + fn test_string() { + run_primitives_test(&"abc"[..], |c| c as char); + } + + /// Should recieve an Input with the tokens 'a', 'b' and 'c' remaining. + pub fn run_primitives_test I::Token>(mut s: I, f: F) + where I::Token: Debug, + I::Buffer: Clone { + use primitives::Primitives; + + fn buffer_eq_slice 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.iter().count()); + assert_eq!(b.to_vec(), s.iter().cloned().map(f).collect::>()); + } + + 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_eq!(b.is_some(), true); + 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_eq!(b.is_some(), true); + buffer_eq_slice(b.unwrap(), &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 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); + } +} diff --git a/src/types/numbering.rs b/src/types/numbering.rs new file mode 100644 index 00000000..053ffe9d --- /dev/null +++ b/src/types/numbering.rs @@ -0,0 +1,231 @@ +//! Module containing tools for working with position aware parsers. +//! +//! ``` +//! # #[macro_use] extern crate chomp; +//! # fn main() { +//! use chomp::types::{Input, ParseResult}; +//! use chomp::types::numbering::{InputPosition, LineNumber, Numbering}; +//! use chomp::combinators::many; +//! use chomp::parsers::{Error, any, take_while1, string}; +//! use chomp::run_parser; +//! +//! // Let's count some lines +//! let i = InputPosition::new(&b"test a\ntest b\n\ntest c\n"[..], LineNumber::new()); +//! +//! // We could use a concrete type P too if we want to restrict to a +//! // certain position-aware implementation +//! fn parser, P: Numbering>(i: InputPosition) +//! -> ParseResult, (char, P), Error> { +//! parse!{i; +//! string(b"test"); +//! take_while1(|c| c == b' ' || c == b'\t'); +//! let t_name = any(); +//! i -> { +//! // Obtain current parser position +//! let p = i.position(); +//! +//! i.ret((t_name as char, p)) +//! // We skip the take while below, because we want to determine the line right +//! // after reading the t_name +//! } <* take_while1(|c| c == b'\n'); +//! } +//! } +//! +//! let r = run_parser(i, |i| many(i, parser)).1; +//! +//! assert_eq!(r, Ok(vec![('a', LineNumber(0)), +//! ('b', LineNumber(1)), +//! // Note the two linebreaks in a row +//! ('c', LineNumber(3))])); +//! # } +//! ``` + +use primitives::Guard; +use types::{Buffer, Input}; + +/// Trait for managing some kind of numbering over the parsed data. +pub trait Numbering: Clone { + /// The token type accepted by the numbering. + type Token: Copy + PartialEq; + + /// Updates the numbering based on the contents of the buffer, adding it to the current + /// numbering. + fn update<'a, B>(&mut self, &'a B) + where B: Buffer; + + /// Adds the token to the numbering. + fn add(&mut self, Self::Token); +} + +/// Struct counting the number of newlines (`b'\n'`). +#[derive(Debug, PartialEq, Eq, Ord, PartialOrd, Hash)] +pub struct LineNumber( + /// The current line, zero-indexed. + pub u64, +); + +impl Clone for LineNumber { + fn clone(&self) -> Self { + LineNumber(self.0) + } +} + +impl LineNumber { + /// Creates a new line-number counter with zero. + pub fn new() -> Self { + LineNumber(0) + } +} + +impl Default for LineNumber { + fn default() -> Self { + LineNumber::new() + } +} + +impl Numbering for LineNumber { + type Token = u8; + + fn update<'a, B>(&mut self, b: &'a B) + where B: Buffer { + let mut n = 0; + + b.iterate(|c| if c == b'\n' { + n += 1; + }); + + self.0 += n + } + + fn add(&mut self, t: Self::Token) { + if t == b'\n' { + self.0 += 1 + } + } +} + +/// Wrapper around an `Input` implementation providing numbering support. +#[derive(Debug)] +pub struct InputPosition> { + input: I, + num: N, +} + +impl> InputPosition { + /// Creates a new input position instance. + pub fn new(i: I, n: N) -> Self { + InputPosition { + input: i, + num: n, + } + } + + /// Obtains the current position of the numbering. + pub fn position(&self) -> N { + self.num.clone() + } +} + +impl> Input for InputPosition { + type Token = I::Token; + type Marker = (N, I::Marker); + type Buffer = I::Buffer; + + #[inline] + fn _peek(&mut self, g: Guard) -> Option { + self.input._peek(g) + } + + #[inline] + fn _pop(&mut self, g: Guard) -> Option { + self.input._pop(g).map(|t| { + self.num.add(t); + + t + }) + } + + #[inline] + fn _consume(&mut self, g: Guard, n: usize) -> Option { + self.input._consume(g, n).map(|b| { + self.num.update(&b); + + b + }) + } + + #[inline] + fn _consume_while(&mut self, g: Guard, f: F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool { + let b = self.input._consume_while(g, f); + + self.num.update(&b); + + b + } + + #[inline] + fn _consume_from(&mut self, g: Guard, m: Self::Marker) -> Self::Buffer { + // We have already counted to current position, no need to update + self.input._consume_from(g, m.1) + } + + #[inline] + fn _consume_remaining(&mut self, g: Guard) -> Self::Buffer { + let b = self.input._consume_remaining(g); + + self.num.update(&b); + + b + } + + #[inline] + fn _mark(&self, g: Guard) -> Self::Marker { + (self.num.clone(), self.input._mark(g)) + } + + #[inline] + fn _restore(self, g: Guard, m: Self::Marker) -> Self { + InputPosition { + input: self.input._restore(g, m.1), + num: m.0, + } + } +} + +#[cfg(test)] +mod test { + use types::{Input, ParseResult}; + use super::{InputPosition, LineNumber}; + use primitives::IntoInner; + + #[test] + fn basic_test() { + use combinators::many; + use parsers::{Error, any, take_while1, string}; + + let i = InputPosition::new(&b"test a\ntest b\n\ntest c\n"[..], Default::default()); + + fn parser>(i: InputPosition) + -> ParseResult, (char, LineNumber), Error> { + parse!{i; + string(b"test"); + take_while1(|c| c == b' ' || c == b'\t'); + let t_name = any(); + i -> { + let p = i.position(); + + i.ret((t_name as char, p)) + // We skip the take while below, because we want to determine the line right + // after reading the t_name + } <* take_while1(|c| c == b'\n'); + } + } + + assert_eq!(many(i, parser).into_inner().1, Ok(vec![ + ('a', LineNumber(0)), + ('b', LineNumber(1)), + // Note the two linebreaks in a row + ('c', LineNumber(3))])); + } +} diff --git a/src/types/tendril.rs b/src/types/tendril.rs new file mode 100644 index 00000000..d3fb45c7 --- /dev/null +++ b/src/types/tendril.rs @@ -0,0 +1,119 @@ +//! Support for the tendril type, this is probably a bad idea since it is actually not a rope and +//! will probably cause excessive reallocations while parsing. + +use std::mem; + +use tendril::ByteTendril; +use primitives::Guard; +use types::{Buffer, Input}; + +// TODO: Impl for more than byte tendril +impl Input for ByteTendril { + type Token = u8; + type Marker = ByteTendril; + type Buffer = ByteTendril; + + #[inline] + fn _peek(&mut self, _g: Guard) -> Option { + self.as_ref().first().cloned() + } + + #[inline] + fn _pop(&mut self, _g: Guard) -> Option { + if self.len32() > 0 { + let t = self.as_ref()[0]; + + self.pop_front(1); + + Some(t) + } else { + None + } + } + + #[inline] + fn _consume(&mut self, _g: Guard, n: usize) -> Option { + if n > self.len32() as usize { + None + } else { + // TODO: How does this work with allocation in the tendril? + let b = self.subtendril(0, n as u32); + + self.pop_front(n as u32); + + Some(b) + } + } + + #[inline] + fn _consume_while(&mut self, g: Guard, mut f: F) -> Self::Buffer + where F: FnMut(Self::Token) -> bool { + match self.iter().position(|c| !f(*c)) { + Some(n) => { + // TODO: How does this work with allocation in the tendril? + let b = self.subtendril(0, n as u32); + + self.pop_front(n as u32); + + b + }, + None => self._consume_remaining(g), + } + } + + #[inline] + fn _consume_from(&mut self, _g: Guard, m: Self::Marker) -> Self::Buffer { + // Just the tendril analogue of the slice version: + m.subtendril(0, m.len32() - self.len32()) + } + + #[inline] + fn _consume_remaining(&mut self, _g: Guard) -> Self::Buffer { + let b = self.subtendril(0, 0); + + mem::replace(self, b) + } + + #[inline] + fn _mark(&self, _g: Guard) -> Self::Marker { + self.clone() + } + + #[inline] + fn _restore(self, _g: Guard, m: Self::Marker) -> Self { + m + } +} + +impl Buffer for ByteTendril { + type Token = u8; + + fn fold(self, init: B, f: F) -> B + where F: FnMut(B, Self::Token) -> B { + (&self[..]).iter().cloned().fold(init, f) + } + + fn len(&self) -> usize { + self.len32() as usize + } + + fn to_vec(self) -> Vec { + (&self[..]).iter().cloned().collect() + } +} + +#[cfg(test)] +mod test { + use tendril::Tendril; + + fn basic() { + use ascii::decimal; + use primitives::IntoInner; + + assert_eq!(decimal(Tendril::from_slice(b"123")).into_inner(), (Tendril::from_slice(b""), Ok(123i32))); + } + + fn primitives() { + ::types::input::test::run_primitives_test(Tendril::from_slice(b"123"), |x| x); + } +} diff --git a/tests/compile-fail/ascii_signed_unsigned_type.rs b/tests/compile-fail/ascii_signed_unsigned_type.rs index dc745afa..0a1777a7 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type.rs @@ -2,11 +2,11 @@ extern crate chomp; -use chomp::{Input, U8Result, parse_only}; +use chomp::prelude::{U8Input, SimpleResult, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: Input) -> U8Result { +fn parser(i: I) -> SimpleResult { signed(i, decimal) } diff --git a/tests/compile-fail/ascii_signed_unsigned_type1.rs b/tests/compile-fail/ascii_signed_unsigned_type1.rs index a383f985..64320b7f 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type1.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type1.rs @@ -2,11 +2,11 @@ extern crate chomp; -use chomp::{Input, U8Result, parse_only}; +use chomp::prelude::{U8Input, SimpleResult, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: Input) -> U8Result { +fn parser(i: I) -> SimpleResult { signed(i, decimal) } diff --git a/tests/compile-fail/ascii_signed_unsigned_type2.rs b/tests/compile-fail/ascii_signed_unsigned_type2.rs index 04d668ce..5ac7cad7 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type2.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type2.rs @@ -2,11 +2,11 @@ extern crate chomp; -use chomp::{Input, U8Result, parse_only}; +use chomp::prelude::{U8Input, SimpleResult, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: Input) -> U8Result { +fn parser(i: I) -> SimpleResult { signed(i, decimal) } diff --git a/tests/compile-fail/ascii_signed_unsigned_type3.rs b/tests/compile-fail/ascii_signed_unsigned_type3.rs index 728210b2..aac295c5 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type3.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type3.rs @@ -2,11 +2,11 @@ extern crate chomp; -use chomp::{Input, U8Result, parse_only}; +use chomp::prelude::{U8Input, SimpleResult, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: Input) -> U8Result { +fn parser(i: I) -> SimpleResult { signed(i, decimal) } diff --git a/tests/compile-fail/ascii_signed_unsigned_type4.rs b/tests/compile-fail/ascii_signed_unsigned_type4.rs index 5ca9aa86..004ea26d 100644 --- a/tests/compile-fail/ascii_signed_unsigned_type4.rs +++ b/tests/compile-fail/ascii_signed_unsigned_type4.rs @@ -2,11 +2,11 @@ extern crate chomp; -use chomp::{Input, U8Result, parse_only}; +use chomp::prelude::{U8Input, SimpleResult, parse_only}; use chomp::ascii::{signed, decimal}; // Should not be possible to use unsigned integers with signed -fn parser(i: Input) -> U8Result { +fn parser(i: I) -> SimpleResult { signed(i, decimal) }