Repository: m4rw3r/chomp (language: rust)

Issue:
EOF and non-finite parsers
## Problem

Currently end of file (EOF) poses an issue for many parsers which allow for an undetermined amount of input data (`many`, `many1`, `take_while`, `take_while1`, `take_till`). There is also the issue of matching end of file conditionally in some cases.
- `many`, `many1`:
  
  If a segment stops at the end of the current input slice `many` will always report incomplete, which is the correct behaviour if the current input slice can be extended with additional input. The issue arises whenever the user tries to parse something which ends with a `many` parser:
  
  ```
  // pretty naive parser which splits everything into chunks of 2 and
  // stores it in a Vec:
  many(parser!{take(2)})
  ```
  
  The parser above will always report incomplete, even when end of input has been reached. The correct behaviour would be to end the repetition provided by `many` exactly at EOF and then report success instead of incomplete. The `take` parser should report incomplete, which is propagated through `many` if take encounters EOF before having read the 2 requested tokens.
- `take_while`, `take_while1`:
  
  Current behaviour will only end parsing when the predicate becomes false, but the parameter to the predicate can not represent EOF and therefore `take_while` reports incomplete whenever the end of the slice is encountered.
  
  Correct behaviour when EOF is encountered would be to succeed with what has been matched so far and then let any following parser report incomplete if they require a minimum number of tokens to parse.
- `eof`:
  
  The current way of determining EOF is to split the parser into several parts and then let a separate piece of code control the invocation of the parsers as well as check for EOF.
  
  A specific `eof` parser would be desireable:
  
  ```
  parse!{i;
      let r = record();
      or(parser!{eof(); ret r},
         parser!{second_part()})}
  ```
## Proposed solution

Store a flag in `Input` which lets the parsers know if the current input slice is finite or if there might be more data "after the end". This flag will enable parsers like `eof` (matches end of input) and `many` to work properly when encountering an end of a slice which is end of input.



Discussion / hints:

Fix patch:
diff --git a/examples/http_parser.rs b/examples/http_parser.rs
index 14b9551f..d10581ef 100644
--- a/examples/http_parser.rs
+++ b/examples/http_parser.rs
@@ -138,7 +138,7 @@ fn main() {
         let _ = file.read_to_end(&mut contents).unwrap();
     }
 
-    let i = Iter::new(&contents, request);
+    let i = Iter::new(Input::new(&contents), request);
 
     println!("num: {}", i.count());
 }
diff --git a/src/combinators.rs b/src/combinators.rs
index 094eb1be..eaeef441 100644
--- a/src/combinators.rs
+++ b/src/combinators.rs
@@ -1,14 +1,14 @@
 //! Basic combinators.
 
+use std::iter::FromIterator;
+
 use {ParseResult, Input};
 
 use iter::{EndState, Iter};
 
 use internal::State;
 use internal::{ParseResultModify, InputModify};
-use internal::{data, error, incomplete};
 
-use std::iter::FromIterator;
 
 /// Applies the parser ``p`` exactly ``num`` times, propagating any error or incomplete state.
 ///
@@ -41,27 +41,25 @@ pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResul
         U: 'a,
         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
         T: FromIterator<U> {
-    i.parse(|i| {
-        // If we have gotten an item, if this is false after from_iter we have failed
-        let mut count = 0;
-        let mut iter  = Iter::new(i, p);
-
-        let result: T      = FromIterator::from_iter(iter.by_ref()
-                                                     .take(num)
-                                                     .inspect(|_| count = count + 1 ));
-        let (buffer, last) = iter.end_state();
-
-        if count == num {
-            data(buffer, result)
-        } else {
-            // Can only be less than num here since take() limits it.
-            // Just propagate the last state from the iterator.
-            match last {
-                EndState::Incomplete(n) => incomplete(n),
-                EndState::Error(b, e)   => error(b, e),
-            }
+    // If we have gotten an item, if this is false after from_iter we have failed
+    let mut count = 0;
+    let mut iter  = Iter::new(i, p);
+
+    let result: T      = FromIterator::from_iter(iter.by_ref()
+                                                 .take(num)
+                                                 .inspect(|_| count = count + 1 ));
+    let (buffer, last) = iter.end_state();
+
+    if count == num {
+        buffer.data(result)
+    } else {
+        // Can only be less than num here since take() limits it.
+        // Just propagate the last state from the iterator.
+        match last {
+            EndState::Incomplete(n) => buffer.incomplete(n),
+            EndState::Error(b, e)     => buffer.replace(b).err(e),
         }
-    })
+    }
 }
 
 /// Tries the parser ``f``, on success it yields the parsed value, on failure ``default`` will be
@@ -82,12 +80,11 @@ pub fn count<'a, I, T, E, F, U>(i: Input<'a, I>, num: usize, p: F) -> ParseResul
 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> {
-    // TODO: That Input::new should be something related to InputModify
-    i.parse(|b| f(Input::new(b)).parse(|s| match s {
-        State::Data(b, t)    => data(b, t),
-        State::Error(_, _)   => data(b, default),
-        State::Incomplete(n) => incomplete(n),
-    }))
+    f(i.clone_input()).parse(|s| match s {
+        State::Data(b, d)    => b.ret(d),
+        State::Error(_, _)   => i.data(default),
+        State::Incomplete(n) => i.incomplete(n),
+    })
 }
 
 /// Tries to match the parser ``f``, if ``f`` fails it tries ``g``. Returns the success value of
@@ -110,11 +107,11 @@ pub fn option<'a, I, T, E, F>(i: Input<'a, I>, f: F, default: T) -> ParseResult<
 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> {
-    i.parse(|b| f(Input::new(b)).parse(|s| match s {
-        State::Data(b, t)    => data(b, t),
-        State::Error(_, _)   => g(Input::new(b)),
-        State::Incomplete(n) => incomplete(n),
-    }))
+    f(i.clone_input()).parse(|s| match s {
+        State::Data(b, d)    => b.ret(d),
+        State::Error(_, _)   => g(i),
+        State::Incomplete(n) => i.incomplete(n),
+    })
 }
 
 /// Parses many instances of ``f`` until it does no longer match, returning all matches.
@@ -144,19 +141,21 @@ pub fn many<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T, E
         U: 'a,
         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
         T: FromIterator<U> {
-    i.parse(|i| {
-        let mut iter = Iter::new(i, f);
+    let mut iter = Iter::new(i, f);
 
-        let result: T = FromIterator::from_iter(iter.by_ref());
+    let result: T = FromIterator::from_iter(iter.by_ref());
 
-        match iter.end_state() {
-            // Ok, last parser failed, we have iterated all.
-            // Return remainder of buffer and the collected result
-            (b, EndState::Error(_, _))   => data(b, result),
-            // Nested parser incomplete, propagate
-            (_, EndState::Incomplete(n)) => incomplete(n),
-        }
-    })
+    match iter.end_state() {
+        // Ok, last parser failed, we have iterated all.
+        // Return remainder of buffer and the collected result
+        (s, EndState::Error(_, _))   => s.data(result),
+        // Nested parser incomplete, propagate
+        (s, EndState::Incomplete(n)) => if s.buffer().len() == 0 && s.is_last_slice() {
+            s.data(result)
+        } else {
+            s.incomplete(n)
+        },
+    }
 }
 
 /// Parses at least one instance of ``f`` and continues until it does no longer match,
@@ -187,27 +186,29 @@ pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T,
         U: 'a,
         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, U, E>,
         T: FromIterator<U> {
-    i.parse(|i| {
-        // If we managed to parse anything
-        let mut item = false;
-        // If we have gotten an item, if this is false after from_iter we have failed
-        let mut iter = Iter::new(i, f);
-
-        let result: T = FromIterator::from_iter(iter.by_ref().inspect(|_| item = true ));
-
-        if !item {
-            match iter.end_state() {
-                (_, EndState::Error(b, e))   => error(b, e),
-                (_, EndState::Incomplete(n)) => incomplete(n),
-            }
-        } else {
-            match iter.end_state() {
-                (b, EndState::Error(_, _))   => data(b, result),
-                // TODO: Indicate potentially more than 1?
-                (_, EndState::Incomplete(n)) => incomplete(n),
-            }
+    // If we managed to parse anything
+    let mut item = false;
+    // If we have gotten an item, if this is false after from_iter we have failed
+    let mut iter = Iter::new(i, f);
+
+    let result: T = FromIterator::from_iter(iter.by_ref().inspect(|_| item = true ));
+
+    if !item {
+        match iter.end_state() {
+            (s, EndState::Error(b, e))   => s.replace(b).error(e),
+            (s, EndState::Incomplete(n)) => s.incomplete(n),
         }
-    })
+    } else {
+        match iter.end_state() {
+            (s, EndState::Error(_, _))   => s.data(result),
+            // TODO: Indicate potentially more than 1?
+            (s, EndState::Incomplete(n)) => if s.buffer().len() == 0 && s.is_last_slice() {
+                s.data(result)
+            } else {
+                s.incomplete(n)
+            },
+        }
+    }
 }
 
 /// Runs the given parser until it fails, discarding matched input.
@@ -225,17 +226,15 @@ pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T,
 /// assert_eq!(skip_many(p, |i| token(i, b'a')).bind(|i, _| token(i, b'b')).unwrap(), b'b');
 /// ```
 #[inline]
-pub fn skip_many<'a, I, T, E, F>(i: Input<'a, I>, mut f: F) -> ParseResult<'a, I, (), E>
+pub fn skip_many<'a, I, T, E, F>(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> {
-    i.parse(|mut i| {
-        loop {
-            match f(Input::new(i)).internal() {
-                State::Data(b, _)    => i = b,
-                State::Error(_, _)   => break,
-                State::Incomplete(n) => return incomplete(n)
-            }
+    loop {
+        match f(i.clone_input()).internal() {
+            State::Data(b, _)    => i = b,
+            State::Error(_, _)   => break,
+            State::Incomplete(n) => return i.incomplete(n),
         }
+    }
 
-        data(i, ())
-    })
+    i.data(())
 }
diff --git a/src/internal.rs b/src/internal.rs
index aaaa610f..da1c4440 100644
--- a/src/internal.rs
+++ b/src/internal.rs
@@ -17,7 +17,7 @@ pub enum State<'a, I: 'a, T, E>
   where I: 'a,
         T: 'a,
         E: 'a {
-    Data(&'a [I], T),
+    Data(Input<'a, I>, T),
     Error(&'a [I], E),
     Incomplete(usize),
 }
@@ -94,6 +94,16 @@ impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
     }
 }
 
+/// Input utilities.
+///
+/// # Internal
+///
+/// Only used by fundamental parsers and combinators.
+pub mod input {
+    pub const DEFAULT: u32      = 0;
+    pub const END_OF_INPUT: u32 = 1;
+}
+
 /// Trait for modifying `Input`.
 ///
 /// # Internal
@@ -102,17 +112,74 @@ impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
 pub trait InputModify<'a> {
     type Type;
 
+    /// Creates a clone of the instance.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(Always)]
+    fn clone_input(&self) -> Self;
+
+    /// Reveals the internal buffer containig the remainder of the input.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn buffer(&self) -> &'a [Self::Type]
+      where <Self as InputModify<'a>>::Type: 'a;
+
     /// Modifies the inner data without leaving the `Input` context.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
     #[inline(always)]
-    fn modify<F>(self, f: F) -> Self
-      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type],
-            <Self as InputModify<'a>>::Type: 'a;
+    fn replace(self, &'a [Self::Type]) -> Self
+      where <Self as InputModify<'a>>::Type: 'a;
+
+    /// Modifies the inner data without leaving the `Input` context.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn modify<F>(self, F) -> Self
+      where F: Fn(&'a [Self::Type]) -> &'a [Self::Type],
+          <Self as InputModify<'a>>::Type: 'a;
+
+    /// Creates a data-carrying value from an input slice and a data value.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn data<T, E>(self, T) -> ParseResult<'a, Self::Type, T, E>;
+
+    /// Creates an error value from an input slice and an error value.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn error<T, E>(self, E) -> ParseResult<'a, Self::Type, T, E>;
+
+    /// Notifies the combinator that a parser has reached the end of the currently supplied slice but
+    /// requires more data.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn incomplete<T, E>(self, usize) -> ParseResult<'a, Self::Type, T, E>;
 
-    /// Applies a parser operating directly on &[Type] to the input.
+    /// Returns true if this is the last available slice of the input.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
     #[inline(always)]
-    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
-      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E>,
-            <Self as InputModify<'a>>::Type: 'a;
+    fn is_last_slice(&self) -> bool;
 }
 
 /// Implementation of internal trait used to build parsers and combinators.
@@ -123,48 +190,68 @@ pub trait InputModify<'a> {
 impl<'a, I> InputModify<'a> for Input<'a, I> {
     type Type = I;
 
+    /// Creates a clone of the instance.
+    #[inline(always)]
+    fn clone_input(&self) -> Self {
+        Input(self.0, self.1)
+    }
+
+    #[inline(always)]
+    fn buffer(&self) -> &'a [Self::Type]
+      where <Self as InputModify<'a>>::Type: 'a {
+        self.1
+    }
+
+    /// Modifies the inner data without leaving the `Input` context.
+    #[inline(always)]
+    fn replace(self, b: &'a [Self::Type]) -> Self
+      where <Self as InputModify<'a>>::Type: 'a {
+        Input(self.0, b)
+    }
+
     /// Modifies the inner data without leaving the `Input` context.
     #[inline(always)]
     fn modify<F>(self, f: F) -> Self
-      where F: FnOnce(&'a [Self::Type]) -> &'a [Self::Type] {
-        Input(f(self.0))
+      where F: Fn(&'a [Self::Type]) -> &'a [Self::Type],
+          <Self as InputModify<'a>>::Type: 'a {
+        Input(self.0, f(self.1))
     }
 
-    /// Applies a parser operating directly on &[Type] to the input.
+    /// Creates a data-carrying value from an input slice and a data value.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
     #[inline(always)]
-    fn parse<F, T, E>(self, f: F) -> ParseResult<'a, Self::Type, T, E>
-      where F: FnOnce(&'a [Self::Type]) -> ParseResult<'a, Self::Type, T, E> {
-        f(self.0)
+    // TODO: Remove; use ret instead
+    fn data<T, E>(self, t: T) -> ParseResult<'a, Self::Type, T, E> {
+        ParseResult(State::Data(self, t))
     }
-}
 
-/// Creates a data-carrying value from an input slice and a data value.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-#[inline(always)]
-pub fn data<'a, I, T, E>(i: &'a [I], t: T) -> ParseResult<'a, I, T, E> {
-    ParseResult(State::Data(i, t))
-}
+    /// Creates an error value from an input slice and an error value.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    // TODO: Remove; use err instead
+    fn error<T, E>(self, e: E) -> ParseResult<'a, Self::Type, T, E> {
+        ParseResult(State::Error(self.1, e))
+    }
 
-/// Creates an error value from an input slice and an error value.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-#[inline(always)]
-pub fn error<'a, I, T, E>(i: &'a [I], e: E) -> ParseResult<'a, I, T, E> {
-    ParseResult(State::Error(i, e))
-}
+    /// Notifies the combinator that a parser has reached the end of the currently supplied slice but
+    /// requires more data.
+    ///
+    /// # Internal
+    ///
+    /// Only used by fundamental parsers and combinators.
+    #[inline(always)]
+    fn incomplete<T, E>(self, n: usize) -> ParseResult<'a, Self::Type, T, E> {
+        ParseResult(State::Incomplete(n))
+    }
 
-/// Notifies the combinator that a parser has reached the end of the currently supplied slice but
-/// requires more data.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-#[inline(always)]
-pub fn incomplete<'a, I, T, E>(n: usize) -> ParseResult<'a, I, T, E> {
-    ParseResult(State::Incomplete(n))
+    #[inline(always)]
+    fn is_last_slice(&self) -> bool {
+        self.0 & input::END_OF_INPUT == input::END_OF_INPUT
+    }
 }
diff --git a/src/iter.rs b/src/iter.rs
index 3a66d6e6..6d9ec511 100644
--- a/src/iter.rs
+++ b/src/iter.rs
@@ -4,7 +4,7 @@ use std::marker::PhantomData;
 
 use {ParseResult, Input};
 use internal::State;
-use internal::{ParseResultModify};
+use internal::{InputModify, ParseResultModify};
 
 pub enum EndState<'a, I, E>
   where I: 'a {
@@ -20,7 +20,7 @@ pub struct Iter<'a, I, T, E, F>
         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> {
     state:  EndState<'a, I, E>,
     parser: F,
-    buf:    &'a [I],
+    buf:    Input<'a, I>,
     _t:     PhantomData<T>,
 }
 
@@ -30,7 +30,7 @@ impl<'a, I, T, E, F> Iter<'a, I, T, E, F>
         E: 'a,
         F: FnMut(Input<'a, I>) -> ParseResult<'a, I, T, E> {
     #[inline]
-    pub fn new(buffer: &'a [I], parser: F) -> Iter<'a, I, T, E, F> {
+    pub fn new(buffer: Input<'a, I>, parser: F) -> Iter<'a, I, T, E, F> {
         Iter{
             state:  EndState::Incomplete(0),
             parser: parser,
@@ -42,7 +42,7 @@ impl<'a, I, T, E, F> Iter<'a, I, T, E, F>
     /// 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]
-    pub fn end_state(self) -> (&'a [I], EndState<'a, I, E>) {
+    pub fn end_state(self) -> (Input<'a, I>, EndState<'a, I, E>) {
         (self.buf, self.state)
     }
 }
@@ -56,7 +56,7 @@ impl<'a, I, T, E, F> Iterator for Iter<'a, I, T, E, F>
 
     #[inline]
     fn next(&mut self) -> Option<Self::Item> {
-        match (self.parser)(Input::new(self.buf)).internal() {
+        match (self.parser)(self.buf.clone_input()).internal() {
             State::Data(b, v) => {
                 self.buf = b;
 
diff --git a/src/lib.rs b/src/lib.rs
index 5c773637..8cdc4df9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -192,6 +192,7 @@ pub use combinators::{
 };
 pub use parsers::{
     any,
+    eof,
     not_token,
     peek,
     satisfy,
@@ -207,29 +208,31 @@ pub use err::Error;
 pub use iter::Iter;
 
 use internal::State;
+use internal::InputModify;
 
 /// Linear type containing the parser state, this type is threaded though `bind`.
 #[must_use]
-#[derive(Debug, Eq, PartialEq)]
-pub struct Input<'a, I: 'a>(&'a [I]);
+#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct Input<'a, I: 'a>(u32, &'a [I]);
 
 impl<'a, I> Input<'a, I> {
-    /// Creates a new input to be passed to parsers and/or combinators.
-    #[inline]
-    pub fn new(i: &'a [I]) -> Self {
-        Input(i)
+    // TODO: Remove, use parse_slice instead
+    pub fn new(b: &'a [I]) -> Self {
+        use internal::input::END_OF_INPUT;
+
+        Input(END_OF_INPUT, b)
     }
 
     /// Returns the value `t` with the input context.
     #[inline]
     pub fn ret<T, E>(self, t: T) -> ParseResult<'a, I, T, E> {
-        internal::data(self.0, t)
+        InputModify::data(self, t)
     }
 
     /// Returns the error value `e` with the input context.
     #[inline]
     pub fn err<T, E>(self, e: E) -> ParseResult<'a, I, T, E> {
-        internal::error(self.0, e)
+        InputModify::error(self, e)
     }
 }
 
@@ -312,7 +315,7 @@ impl<'a, I, T, E> ParseResult<'a, I, T, E> {
       where F: FnOnce(Input<'a, I>, T) -> ParseResult<'a, I, U, V>,
             V: From<E> {
         match self.0 {
-            State::Data(i, t)    => f(Input(i), t).map_err(From::from),
+            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)),
         }
@@ -355,7 +358,7 @@ impl<'a, I, T, E> ParseResult<'a, I, T, E> {
     pub fn map<U, F>(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::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)),
         }
@@ -365,7 +368,7 @@ impl<'a, I, T, E> ParseResult<'a, I, T, E> {
     pub fn map_err<V, F>(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::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)),
         }
@@ -400,9 +403,9 @@ impl<'a, I, T, E: fmt::Debug> ParseResult<'a, I, T, E> {
     /// ```
     ///
     /// ```{.should_panic}
-    /// use chomp::{Input, take_while};
+    /// use chomp::{Input, take};
     ///
-    /// let r = take_while(Input::new(b"a"), |c| c == b'a');
+    /// let r = take(Input::new(b"a"), 2);
     ///
     /// // Panics with "called `ParseResult::unwrap` on an incomplete state (requested 1 tokens)"
     /// assert_eq!(r.unwrap(), b"a");
@@ -500,8 +503,8 @@ mod err {
     use std::error;
     use std::fmt;
 
-    use ParseResult;
-    use internal::error;
+    use {Input, ParseResult};
+    use internal::InputModify;
 
     #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
     pub enum Error<I> {
@@ -544,10 +547,10 @@ mod err {
 
 
     #[inline(always)]
-    pub fn string<'a, 'b, I, T>(buffer: &'a [I], _offset: usize, expected: &'b [I])
+    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, _offset: usize, expected: &'b [I])
         -> ParseResult<'a, I, T, Error<I>>
       where I: Copy {
-        error(buffer, Error::String(expected.to_vec()))
+        i.error(Error::String(expected.to_vec()))
     }
 }
 
@@ -563,8 +566,7 @@ mod err {
 
     use std::marker::PhantomData;
 
-    use ParseResult;
-    use internal::error;
+    use {Input, ParseResult};
 
     #[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
     pub struct Error<I>(PhantomData<I>);
@@ -592,10 +594,13 @@ mod err {
     }
 
     #[inline(always)]
-    pub fn string<'a, 'b, I, T>(buffer: &'a [I], offset: usize, _expected: &'b [I])
+    pub fn string<'a, 'b, I, T>(i: Input<'a, I>, offset: usize, _expected: &'b [I])
         -> ParseResult<'a, I, T, Error<I>>
       where I: Copy {
-        error(&buffer[offset..], Error(PhantomData))
+        use internal::InputModify;
+        let b = i.buffer();
+
+        i.replace(&b[offset..]).error(Error(PhantomData))
     }
 }
 
@@ -603,6 +608,7 @@ mod err {
 mod test {
     use {Input, ParseResult};
     use internal::State;
+    use internal::input::END_OF_INPUT;
 
     #[test]
     fn monad_left_identity() {
@@ -610,8 +616,8 @@ mod test {
             i.ret(n + 1)
         }
 
-        let m1 = Input(b"test");
-        let m2 = Input(b"test");
+        let m1 = Input(END_OF_INPUT, b"test");
+        let m2 = Input(END_OF_INPUT, b"test");
 
         let a = 123;
         // return a >>= f
@@ -619,21 +625,21 @@ mod test {
         // f a
         let rhs = f(m2, a);
 
-        assert_eq!(lhs.0, State::Data(b"test", 124));
-        assert_eq!(rhs.0, State::Data(b"test", 124));
+        assert_eq!(lhs.0, State::Data(Input(END_OF_INPUT, b"test"), 124));
+        assert_eq!(rhs.0, State::Data(Input(END_OF_INPUT, b"test"), 124));
     }
 
     #[test]
     fn monad_right_identity() {
-        let m1 = Input(b"test").ret::<_, ()>(1);
-        let m2 = Input(b"test").ret::<_, ()>(1);
+        let m1 = Input(END_OF_INPUT, b"test").ret::<_, ()>(1);
+        let m2 = Input(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(b"test", 1));
-        assert_eq!(rhs.0, State::Data(b"test", 1));
+        assert_eq!(lhs.0, State::Data(Input(END_OF_INPUT, b"test"), 1));
+        assert_eq!(rhs.0, State::Data(Input(END_OF_INPUT, b"test"), 1));
     }
 
     #[test]
@@ -646,15 +652,15 @@ mod test {
             i.ret(num * 2)
         }
 
-        let lhs_m = Input(b"test").ret::<_, ()>(2);
-        let rhs_m = Input(b"test").ret::<_, ()>(2);
+        let lhs_m = Input(END_OF_INPUT, b"test").ret::<_, ()>(2);
+        let rhs_m = Input(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(b"test", 6));
-        assert_eq!(rhs.0, State::Data(b"test", 6));
+        assert_eq!(lhs.0, State::Data(Input(END_OF_INPUT, b"test"), 6));
+        assert_eq!(rhs.0, State::Data(Input(END_OF_INPUT, b"test"), 6));
     }
 }
diff --git a/src/parsers.rs b/src/parsers.rs
index 83388f7d..d1e0ae01 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -3,7 +3,6 @@
 use {Input, SimpleResult};
 use err;
 use internal::InputModify;
-use internal::{data, error, incomplete};
 
 /// Matches any item, returning it if present.
 ///
@@ -18,10 +17,10 @@ use internal::{data, error, incomplete};
 /// ```
 #[inline]
 pub fn any<'a, I: 'a + Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, I> {
-    i.parse(|b| match b.first() {
-        None     => incomplete(1),
-        Some(&c) => data(&b[1..], c),
-    })
+    match i.buffer().first() {
+        None     => i.incomplete(1),
+        Some(&c) => i.modify(|b| &b[1..]).data(c),
+    }
 }
 
 /// Matches an item using ``f``, the item is returned if ``f`` yields true, otherwise this parser
@@ -39,11 +38,11 @@ pub fn any<'a, I: 'a + Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, I> {
 #[inline]
 pub fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, I>
   where F: FnOnce(I) -> bool {
-    i.parse(|b| match b.first() {
-        None             => incomplete(1),
-        Some(&c) if f(c) => data(&b[1..], c),
-        Some(_)          => error(b, err::unexpected()),
-    })
+    match i.buffer().first() {
+        None             => i.incomplete(1),
+        Some(&c) if f(c) => i.modify(|b| &b[1..]).data(c),
+        Some(_)          => i.error(err::unexpected()),
+    }
 }
 
 /// Matches a single token, returning the match on success.
@@ -59,11 +58,11 @@ pub fn satisfy<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I
 /// ```
 #[inline]
 pub fn token<'a, I: 'a + Copy + PartialEq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {
-    i.parse(|b| match b.first() {
-        None               => incomplete(1),
-        Some(&c) if t == c => data(&b[1..], c),
-        Some(_)            => error(b, err::expected(t)),
-    })
+    match i.buffer().first() {
+        None               => i.incomplete(1),
+        Some(&c) if t == c => i.modify(|b| &b[1..]).data(c),
+        Some(_)            => i.error(err::expected(t)),
+    }
 }
 
 /// Matches a single token as long as it is not equal to `t`, returning the match on success.
@@ -83,11 +82,11 @@ pub fn token<'a, I: 'a + Copy + PartialEq>(i: Input<'a, I>, t: I) -> SimpleResul
 /// ```
 #[inline]
 pub fn not_token<'a, I: 'a + Copy + PartialEq>(i: Input<'a, I>, t: I) -> SimpleResult<'a, I, I> {
-    i.parse(|b| match b.first() {
-        None               => incomplete(1),
-        Some(&c) if t != c => data(&b[1..], c),
-        Some(_)            => error(b, err::unexpected()),
-    })
+    match i.buffer().first() {
+        None               => i.incomplete(1),
+        Some(&c) if t != c => i.modify(|b| &b[1..]).data(c),
+        Some(_)            => i.error(err::unexpected()),
+    }
 }
 
 /// Matches any item but does not consume it, on success it gives ``Some`` but if no input remains
@@ -108,7 +107,9 @@ pub fn not_token<'a, I: 'a + Copy + PartialEq>(i: Input<'a, I>, t: I) -> SimpleR
 /// ```
 #[inline]
 pub fn peek<'a, I: 'a + Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, Option<I>> {
-    i.parse(|b| data(b, b.first().map(|&c| c)))
+    let d = i.buffer().first().map(|&c| c);
+
+    i.data(d)
 }
 
 /// Matches ``num`` items no matter what they are, returning a slice of the matched items.
@@ -124,11 +125,13 @@ pub fn peek<'a, I: 'a + Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, Option<I>>
 /// ```
 #[inline]
 pub fn take<'a, I: 'a + Copy>(i: Input<'a, I>, num: usize) -> SimpleResult<'a, I, &'a [I]> {
-    i.parse(|b| if num <= b.len() {
-        data(&b[num..], &b[..num])
+    let b = i.buffer();
+
+    if num <= b.len() {
+        i.replace(&b[num..]).data(&b[..num])
     } else {
-        incomplete(num)
-    })
+        i.incomplete(num)
+    }
 }
 
 /// Matches all items while ``f`` returns false, returns a slice of all the matched items.
@@ -156,12 +159,21 @@ pub fn take<'a, I: 'a + Copy>(i: Input<'a, I>, num: usize) -> SimpleResult<'a, I
 #[inline]
 pub fn take_while<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, &'a [I]>
   where F: Fn(I) -> bool {
-    i.parse(|b| match b.iter().map(|c| *c).position(|c| f(c) == false) {
-        Some(n) => data(&b[n..], &b[..n]),
+    let b = i.buffer();
+
+    match b.iter().map(|c| *c).position(|c| f(c) == false) {
+        Some(n) => i.replace(&b[n..]).data(&b[..n]),
         // TODO: Should this following 1 be something else, seeing as take_while1 is potentially
         // infinite?
-        None    => incomplete(1),
-    })
+        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]).data(b)
+        } else {
+            i.incomplete(1)
+        },
+    }
 }
 
 /// Matches all items while ``f`` returns true, if at least one item matched this parser succeeds
@@ -180,13 +192,22 @@ pub fn take_while<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a
 #[inline]
 pub fn take_while1<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, &'a [I]>
   where F: Fn(I) -> bool {
-    i.parse(|b| match b.iter().map(|c| *c).position(|c| f(c) == false) {
-        Some(0) => error(b, err::unexpected()),
-        Some(n) => data(&b[n..], &b[..n]),
+    let b = i.buffer();
+
+    match b.iter().map(|c| *c).position(|c| f(c) == false) {
+        Some(0) => i.error(err::unexpected()),
+        Some(n) => i.replace(&b[n..]).data(&b[..n]),
         // TODO: Should this following 1 be something else, seeing as take_while1 is potentially
         // infinite?
-        None    => incomplete(1),
-    })
+        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]).data(b)
+        } else {
+            i.incomplete(1)
+        },
+    }
 }
 
 /// Matches all items until ``f`` returns true, all items to that point will be returned as a slice
@@ -205,12 +226,14 @@ pub fn take_while1<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'
 #[inline]
 pub fn take_till<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a, I, &'a [I]>
   where F: Fn(I) -> bool {
-    i.parse(|b| match b.iter().map(|c| *c).position(f) {
-        Some(n) => data(&b[n..], &b[0..n]),
+    let b = i.buffer();
+
+    match b.iter().map(|c| *c).position(f) {
+        Some(n) => i.replace(&b[n..]).data(&b[0..n]),
         // TODO: Should this following 1 be something else, seeing as take_while1 is potentially
         // infinite?
-        None    => incomplete(1),
-    })
+        None    => i.incomplete(1),
+    }
 }
 
 /// Matches the remainder of the buffer and returns it, always succeeds.
@@ -224,11 +247,12 @@ pub fn take_till<'a, I: 'a + Copy, F>(i: Input<'a, I>, f: F) -> SimpleResult<'a,
 /// ```
 #[inline]
 pub fn take_remainder<'a, I: Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, &'a [I]> {
+    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
-    i.parse(|b| data(&b[..0], b))
+    i.replace(&b[..0]).data(b)
 }
 
 /// Matches the given slice against the parser, returning the matched slice upon success.
@@ -246,21 +270,41 @@ pub fn take_remainder<'a, I: Copy>(i: Input<'a, I>) -> SimpleResult<'a, I, &'a [
 #[inline]
 pub fn string<'a, 'b, I: Copy + PartialEq>(i: Input<'a, I>, s: &'b [I])
     -> SimpleResult<'a, I, &'a [I]> {
-    i.parse(|b| {
-        if s.len() > b.len() {
-            return incomplete(s.len() - b.len());
-        }
+    let b = i.buffer();
 
-        let d = &b[..s.len()];
+    if s.len() > b.len() {
+        return i.incomplete(s.len() - b.len());
+    }
+
+    let d = &b[..s.len()];
 
-        for i in 0..s.len() {
-            if s[i] != d[i] {
-                return err::string(b, i, s);
-            }
+    for j in 0..s.len() {
+        if s[j] != d[j] {
+            return err::string(i, j, s);
         }
+    }
 
-        data(&b[s.len()..], d)
-    })
+    i.replace(&b[s.len()..]).data(d)
+}
+
+/// Matches the end of the input.
+///
+/// ```
+/// use chomp::{Input, token, eof};
+///
+/// let i = Input::new(b"a");
+///
+/// let r = token(i, b'a').bind(|i, _| eof(i));
+///
+/// assert_eq!(r.unwrap(), ());
+/// ```
+#[inline]
+pub fn eof<I>(i: Input<I>) -> SimpleResult<I, ()> {
+    if i.buffer().len() == 0 && i.is_last_slice() {
+        i.ret(())
+    } else {
+        i.err(err::unexpected())
+    }
 }
 
 #[cfg(test)]


Test patch: