Repository: m4rw3r/chomp (language: rust)

Issue:
Split InputModify and ParseResultModify into more specialized traits
# Problem

`internal::InputModify` and `internal::ParseResultModify` contain too many methods, making it hard to see what a part is actually doing with the `Input` and `ParseResult` types.
# Proposed solution

Remove `ParseResultModify` and `InputModify` and replace with the following traits:

Note: `ParseResultModify::modify` does not need any corresponding trait, it is unused.
- Replace all uses of `InputModify::modify` with `buffer()` + `replace(buffer)`.
## `IntoInner` trait

``` rust
pub trait IntoInner {
    type Inner;

    fn into_inner() -> Self::Inner;
}
```
- `Input -> (InputState, &[I])`
- `ParseResult -> State`
## `ParseResultChain` for `ParseResult`

Is this really useful? It is used in two spots in `combinators.rs`.

``` rust
pub trait ParseResultChain {
    fn chain<F, T, E>(self, F) -> ParseResult<'a, Self::Input, T, E>
      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>)
               ...;
}
```
## `InputClone`

``` rust
pub trait InputClone {
    fn clone_input(&self) -> Self;
}
```
## `InputBuffer`

``` rust
pub trait InputBuffer<'a> {
    fn buffer(&self) -> &'a [Self::Type]
      where <Self as InputModify<'a>>::Type: 'a;
    fn replace(self, &'a [Self::Type]) -> Self
      where <Self as InputModify<'a>>::Type: 'a;
    fn is_last_slice(&self) -> bool;
}
```

`replace` is never used without `buffer` (except for in one case combined with `parse`), and same goes for `is_last_slice`.
## `InputIncomplete`

``` rust
pub trait InputIncomplete {
    fn incomplete<T, E>(self, usize) -> ParseResult<'a, Self::Type, T, E>;
}
```



Discussion / hints:

Fix patch:
diff --git a/src/buffer/slice.rs b/src/buffer/slice.rs
index a56f1e70..43ec6d75 100644
--- a/src/buffer/slice.rs
+++ b/src/buffer/slice.rs
@@ -1,5 +1,5 @@
-use internal::input;
-use internal::{State, InputModify, ParseResultModify};
+use primitives::input;
+use primitives::{State, InputBuffer, IntoInner};
 
 use {Input, ParseResult};
 use buffer::{IntoStream, ParseError, Stream};
@@ -90,7 +90,7 @@ impl<'a, 'i, I: 'i> Stream<'a, 'i> for SliceStream<'i, I> {
             return Err(ParseError::EndOfInput);
         }
 
-        match f(input::new(input::END_OF_INPUT, &self.slice[self.pos..])).internal() {
+        match f(input::new(input::END_OF_INPUT, &self.slice[self.pos..])).into_inner() {
             State::Data(remainder, data) => {
                 // TODO: Do something neater with the remainder
                 self.pos += self.len() - remainder.buffer().len();
diff --git a/src/buffer/stateful.rs b/src/buffer/stateful.rs
index 4b9d5999..ced65e36 100644
--- a/src/buffer/stateful.rs
+++ b/src/buffer/stateful.rs
@@ -2,8 +2,8 @@ use std::io;
 use std::cmp;
 
 use {Input, ParseResult};
-use internal::input;
-use internal::{InputModify, State, ParseResultModify};
+use primitives::input;
+use primitives::{InputBuffer, State, IntoInner};
 
 use buffer::{
     Buffer,
@@ -14,7 +14,6 @@ use buffer::{
 };
 use buffer::data_source::{IteratorDataSource, ReadDataSource};
 
-
 bitflags!{
     flags ParserState: u64 {
         /// The parser which was last run on the buffer did not manage to complete with the data
@@ -208,7 +207,7 @@ impl<'a, S: DataSource, B: Buffer<S::Item>> Stream<'a, 'a> for Source<S, B>
 
         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)).internal() {
+        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());
diff --git a/src/combinators.rs b/src/combinators.rs
index 5532d437..eb4cf1e9 100644
--- a/src/combinators.rs
+++ b/src/combinators.rs
@@ -4,9 +4,9 @@ use std::iter::FromIterator;
 
 use {ParseResult, Input};
 
-use internal::State;
-use internal::{ParseResultModify, InputModify};
-use internal::iter::{EndState, Iter};
+use primitives::State;
+use primitives::{IntoInner, InputBuffer, InputClone};
+use iter::{EndState, Iter};
 
 
 /// Applies the parser ``p`` exactly ``num`` times, propagating any error or incomplete state.
@@ -81,11 +81,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> {
-    f(i.clone_input()).parse(|s| match s {
+    match f(i.clone()).into_inner() {
         State::Data(b, d)    => b.ret(d),
         State::Error(_, _)   => i.ret(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 +110,11 @@ assert_eq!(or(p3, |i| token(i, b'a'), |i| token(i, b'b')).unwrap_err(), Error::E
 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> {
-    f(i.clone_input()).parse(|s| match s {
+    match f(i.clone()).into_inner() {
         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.
@@ -234,7 +234,7 @@ pub fn many1<'a, I, T, E, F, U>(i: Input<'a, I>, f: F) -> ParseResult<'a, I, T,
 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> {
     loop {
-        match f(i.clone_input()).internal() {
+        match f(i.clone()).into_inner() {
             State::Data(b, _)    => i = b,
             State::Error(_, _)   => break,
             State::Incomplete(n) => return i.incomplete(n),
diff --git a/src/input.rs b/src/input.rs
index d45f9d1a..8f784c40 100644
--- a/src/input.rs
+++ b/src/input.rs
@@ -1,6 +1,4 @@
-use ParseResult;
-use internal::State;
-use internal::InputModify;
+use parse_result::{ParseResult, State};
 use parse_result;
 
 bitflags!{
@@ -12,14 +10,64 @@ bitflags!{
     }
 }
 
+/// **Primitive:** Trait limiting the use of `Clone` for `Input`.
+///
+/// # Primitive
+///
+/// Only used by fundamental parsers and combinators.
+///
+pub trait InputClone {
+    /// **Primitive:** 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> {
+    type Item: 'a;
+
+    /// **Primitive:** 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];
+
+    /// **Primitive:** 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;
+
+    /// **Primitive:** 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`.
 #[must_use]
 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
 pub struct Input<'a, I: 'a>(InputMode, &'a [I]);
 
-/// Creates a new input from the given state and buffer.
+/// **Primitive:** Creates a new input from the given state and buffer.
 ///
-/// # Internal
+/// # Primitive
 ///
 /// Only used by fundamental parsers and combinators.
 pub fn new<I>(state: InputMode, buffer: &[I]) -> Input<I> {
@@ -44,6 +92,17 @@ impl<'a, I> Input<'a, I> {
         parse_result::new(State::Error(self.1, e))
     }
 
+    /// **Primitive:** 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<T, E>(self, n: usize) -> ParseResult<'a, I, T, E> {
+        parse_result::new(State::Incomplete(n))
+    }
+
     /// Converts a `Result` into a `ParseResult`.
     ///
     /// # Examples
@@ -72,57 +131,76 @@ impl<'a, I> Input<'a, I> {
     }
 }
 
-/// Implementation of internal trait used to build parsers and combinators.
+/// **Primitive:** Trait limiting the use of `Clone` for `Input`.
 ///
-/// # Internal
+/// # Primitive
 ///
 /// Only used by fundamental parsers and combinators.
-impl<'a, I> InputModify<'a> for Input<'a, I> {
-    type Type = I;
-
-    /// Creates a clone of the instance.
+///
+/// # 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_input(&self) -> Self {
+    fn clone(&self) -> Self {
         Input(self.0, self.1)
     }
+}
+
+/// **Primitive:** 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::{Input, take};
+/// use chomp::primitives::InputBuffer;
+///
+/// let i = Input::new(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.unwrap(), b"Test");
+/// ```
+impl<'a, I: 'a> InputBuffer<'a> for Input<'a, I> {
+    type Item = I;
 
     #[inline(always)]
-    fn buffer(&self) -> &'a [Self::Type]
-      where <Self as InputModify<'a>>::Type: 'a {
+    fn buffer(&self) -> &'a [Self::Item] {
         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 {
+    fn replace(self, b: &'a [Self::Item]) -> Self {
         Input(self.0, b)
     }
 
-    /// Modifies the inner data without leaving the `Input` context.
-    #[inline(always)]
-    fn modify<F>(self, f: F) -> Self
-      where F: Fn(&'a [Self::Type]) -> &'a [Self::Type],
-          <Self as InputModify<'a>>::Type: 'a {
-        Input(self.0, f(self.1))
-    }
-
-    /// 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> {
-        parse_result::new(State::Incomplete(n))
-    }
-
-    /// Returns true if this is the last input slice available.
-    ///
-    /// # Internal
-    ///
-    /// Only used by fundamental parsers and combinators.
     #[inline(always)]
     fn is_last_slice(&self) -> bool {
         self.0.contains(END_OF_INPUT)
diff --git a/src/internal/mod.rs b/src/internal/mod.rs
deleted file mode 100644
index b77b8926..00000000
--- a/src/internal/mod.rs
+++ /dev/null
@@ -1,144 +0,0 @@
-//! Module used to construct fundamental parsers and combinators.
-//!
-//! # Internal
-//!
-//! Only used by fundamental parsers and combinators.
-
-pub mod iter;
-
-use {ParseResult, Input};
-
-/// Internal inner type containing the parse-state.
-///
-/// # Internal
-///
-/// 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 {
-    Data(Input<'a, I>, T),
-    Error(&'a [I], E),
-    /// The number of additional items requested
-    Incomplete(usize),
-}
-
-/// Internal trait for modifying `ParseResult`.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-pub trait ParseResultModify<'a> {
-    type Input;
-    type Data;
-    type Error;
-
-    /// Modifies the content of ParseResult, without changing its type.
-    #[inline(always)]
-    fn modify<F>(self, F) -> Self
-      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>)
-                   -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
-            <Self as ParseResultModify<'a>>::Input: 'a,
-            <Self as ParseResultModify<'a>>::Data:  'a,
-            <Self as ParseResultModify<'a>>::Error: 'a;
-
-    /// Applies the function `f` to the inner `State`, allows modification of data and error types.
-    #[inline(always)]
-    fn parse<F, T, E>(self, F) -> ParseResult<'a, Self::Input, T, E>
-      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>)
-                   -> ParseResult<'a, Self::Input, T, E>,
-            <Self as ParseResultModify<'a>>::Input: 'a,
-            <Self as ParseResultModify<'a>>::Data:  'a,
-            <Self as ParseResultModify<'a>>::Error: 'a;
-
-    /// Consumes the `ParseResult` and reveals the inner state.
-    #[inline(always)]
-    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error>;
-}
-
-/// Input utilities.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-pub mod input {
-    pub use input::{DEFAULT, END_OF_INPUT, new};
-}
-
-/// ParseResult utilities.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-///
-/// # Note
-///
-/// Prefer to use ``Input::ret``, ``Input::err`` or ``InputModify::incomplete`` instead of using
-/// ``parse_result::new``.
-pub mod parse_result {
-    pub use parse_result::new;
-}
-
-/// Trait for modifying `Input`.
-///
-/// # Internal
-///
-/// Only used by fundamental parsers and combinators.
-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 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;
-
-    /// 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>;
-
-    /// Returns true if this is the last available slice of the input.
-    ///
-    /// # Internal
-    ///
-    /// Only used by fundamental parsers and combinators.
-    #[inline(always)]
-    fn is_last_slice(&self) -> bool;
-}
diff --git a/src/internal/iter.rs b/src/iter.rs
similarity index 92%
rename from src/internal/iter.rs
rename to src/iter.rs
index a22d0690..9c717627 100644
--- a/src/internal/iter.rs
+++ b/src/iter.rs
@@ -5,9 +5,8 @@
 
 use std::marker::PhantomData;
 
-use {ParseResult, Input};
-use internal::State;
-use internal::{InputModify, ParseResultModify};
+use {Input, ParseResult};
+use primitives::{InputClone, IntoInner, State};
 
 pub enum EndState<'a, I, E>
   where I: 'a {
@@ -59,7 +58,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)(self.buf.clone_input()).internal() {
+        match (self.parser)(self.buf.clone()).into_inner() {
             State::Data(b, v) => {
                 self.buf = b;
 
diff --git a/src/lib.rs b/src/lib.rs
index 179ce192..92c71760 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -49,7 +49,7 @@
 //!
 //! * `parsers` contains the basic parsers used to parse streams of input.
 //! * `combinators` contains functions which take parsers and return new ones.
-//! * `internal` contains the building blocks used to make new parsers. This is advanced usage and
+//! * `primitives` contains the building blocks used to make new parsers. This is advanced usage and
 //!   is far more involved than using the pre-existing parsers, but is sometimes unavoidable.
 //!
 //! A parser is, at its simplest, a function that takes a slice of input and returns a
@@ -179,11 +179,11 @@ extern crate conv;
 #[macro_use]
 mod macros;
 mod input;
+mod iter;
 mod parse_result;
 
 pub mod ascii;
 pub mod buffer;
-pub mod internal;
 pub mod parsers;
 pub mod combinators;
 
@@ -213,11 +213,50 @@ pub use parsers::{
 pub use err::Error;
 pub use input::Input;
 pub use parse_result::{
-    U8Result,
-    SimpleResult,
     ParseResult,
+    SimpleResult,
+    U8Result,
 };
 
+/// Module used to construct fundamental parsers and combinators.
+///
+/// # Primitive
+///
+/// Only used by fundamental parsers and combinators.
+pub mod primitives {
+    pub use input::{
+        InputBuffer,
+        InputClone,
+    };
+    pub use parse_result::{
+        IntoInner,
+        State,
+    };
+
+    /// 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;
+    }
+}
+
 #[cfg(feature = "verbose_error")]
 mod err {
     //! This is a private module to contain the more verbose error type as well as adapters for
@@ -321,7 +360,8 @@ mod err {
     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 {
-        use internal::InputModify;
+        use primitives::InputBuffer;
+
         let b = i.buffer();
 
         i.replace(&b[offset..]).err(Error(PhantomData))
diff --git a/src/parse_result.rs b/src/parse_result.rs
index 5af6f3b4..f1d92076 100644
--- a/src/parse_result.rs
+++ b/src/parse_result.rs
@@ -2,14 +2,46 @@ use std::fmt;
 
 use err::Error;
 use input::Input;
-use internal::State;
-use internal::ParseResultModify;
 
 /// Result for dealing with the basic parsers when parsing a stream of `u8`.
 pub type U8Result<'a, T>        = ParseResult<'a, u8, T, Error<u8>>;
 /// Result returned from the basic parsers.
 pub type SimpleResult<'a, I, T> = ParseResult<'a, I, T, Error<I>>;
 
+/// **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 {
+    Data(Input<'a, I>, T),
+    Error(&'a [I], E),
+    /// The number of additional items requested
+    Incomplete(usize),
+}
+
+/// **Primitive:** Consumes self and reveals the inner state.
+///
+/// # Primitive
+///
+/// Only used by fundamental parsers and combinators.
+pub trait IntoInner {
+    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
@@ -287,24 +319,24 @@ impl<'a, I, T: fmt::Debug, E> ParseResult<'a, I, T, E> {
     ///
     #[cfg_attr(feature = "verbose_error", doc = "
 
-# Examples
+ # Examples
 
-```
-use chomp::{Error, Input, token};
+ ```
+ use chomp::{Error, Input, token};
 
-let r = token(Input::new(b\"a\"), b'b');
+ let r = token(Input::new(b\"a\"), b'b');
 
-assert_eq!(r.unwrap_err(), Error::Expected(98));
-```
+ assert_eq!(r.unwrap_err(), Error::Expected(98));
+ ```
 
-```{.should_panic}
-use chomp::{Error, Input, token};
+ ```{.should_panic}
+ use chomp::{Error, Input, token};
 
-let r = token(Input::new(b\"a\"), b'a');
+ let r = token(Input::new(b\"a\"), b'a');
 
-// Panics with \"called `ParseResult::unwrap_err` on a success state: 97\"
-assert_eq!(r.unwrap_err(), Error::Expected(98));
-```
+ // Panics with \"called `ParseResult::unwrap_err` on a success state: 97\"
+ assert_eq!(r.unwrap_err(), Error::Expected(98));
+ ```
     ")]
     #[inline]
     pub fn unwrap_err(self) -> E {
@@ -320,41 +352,51 @@ assert_eq!(r.unwrap_err(), Error::Expected(98));
     }
 }
 
-/// Implementation of internal trait used as a building block for combinators.
+/// **Primitive:** Consumes the `ParseResult` and exposes the internal state.
 ///
-/// # Internal
+/// # Primitive
 ///
 /// Only used by fundamental parsers and combinators.
-impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
-    type Input = I;
-    type Data  = T;
-    type Error = E;
-
-    /// Applies the function `f` to the inner `State` while preserving types.
-    #[inline(always)]
-    fn modify<F>(self, f: F) -> Self
-      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>)
-                   -> ParseResult<'a, Self::Input, Self::Data, Self::Error>,
-            <Self as ParseResultModify<'a>>::Input: 'a,
-            <Self as ParseResultModify<'a>>::Data:  'a,
-            <Self as ParseResultModify<'a>>::Error: 'a {
-        f(self.0)
-    }
-
-    /// Applies the function `f` to the inner `State`, allows modification of data and error types.
-    #[inline(always)]
-    fn parse<F, U, V>(self, f: F) -> ParseResult<'a, Self::Input, U, V>
-      where F: FnOnce(State<'a, Self::Input, Self::Data, Self::Error>)
-                   -> ParseResult<'a, Self::Input, U, V>,
-            <Self as ParseResultModify<'a>>::Input: 'a,
-            <Self as ParseResultModify<'a>>::Data:  'a,
-            <Self as ParseResultModify<'a>>::Error: 'a {
-        f(self.0)
-    }
+///
+/// # 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 to make it easier to use the parsers
+/// `unwrap`, `unwrap_err` and `expect` were introduced which breaks the linearity guarantee when
+/// used early.
+///
+/// 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, 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 i = Input::new(b"foo");
+///
+/// let r = my_combinator(i, |i| take(i, 10), &b"test"[..]);
+///
+/// assert_eq!(r.unwrap(), b"test");
+/// ```
+impl<'a, I, T, E> IntoInner for ParseResult<'a, I, T, E> {
+    type Inner = State<'a, I, T, E>;
 
-    /// Consumes the `ParseResult` and reveals the inner state.
     #[inline(always)]
-    fn internal(self) -> State<'a, Self::Input, Self::Data, Self::Error> {
+    fn into_inner(self) -> Self::Inner {
         self.0
     }
 }
@@ -363,7 +405,7 @@ impl<'a, I, T, E> ParseResultModify<'a> for ParseResult<'a, I, T, E> {
 mod test {
     use input;
     use input::{Input, END_OF_INPUT};
-    use internal::State;
+    use primitives::State;
 
     use super::ParseResult;
 
diff --git a/src/parsers.rs b/src/parsers.rs
index cb08cd93..733c4758 100644
--- a/src/parsers.rs
+++ b/src/parsers.rs
@@ -4,7 +4,7 @@ use std::mem;
 
 use {Input, SimpleResult};
 use err;
-use internal::InputModify;
+use primitives::{InputBuffer};
 
 /// Matches any item, returning it if present.
 ///
@@ -19,9 +19,11 @@ use internal::InputModify;
 /// ```
 #[inline]
 pub fn any<I: Copy>(i: Input<I>) -> SimpleResult<I, I> {
-    match i.buffer().first() {
+    let b = i.buffer();
+
+    match b.first() {
         None     => i.incomplete(1),
-        Some(&c) => i.modify(|b| &b[1..]).ret(c),
+        Some(&c) => i.replace(&b[1..]).ret(c),
     }
 }
 
@@ -40,9 +42,11 @@ pub fn any<I: Copy>(i: Input<I>) -> SimpleResult<I, I> {
 #[inline]
 pub fn satisfy<I: Copy, F>(i: Input<I>, f: F) -> SimpleResult<I, I>
   where F: FnOnce(I) -> bool {
-    match i.buffer().first() {
+    let b = i.buffer();
+
+    match b.first() {
         None             => i.incomplete(1),
-        Some(&c) if f(c) => i.modify(|b| &b[1..]).ret(c),
+        Some(&c) if f(c) => i.replace(&b[1..]).ret(c),
         Some(_)          => i.err(err::unexpected()),
     }
 }
@@ -60,9 +64,11 @@ pub fn satisfy<I: Copy, F>(i: Input<I>, f: F) -> SimpleResult<I, I>
 /// ```
 #[inline]
 pub fn token<I: Copy + PartialEq>(i: Input<I>, t: I) -> SimpleResult<I, I> {
-    match i.buffer().first() {
+    let b = i.buffer();
+
+    match b.first() {
         None               => i.incomplete(1),
-        Some(&c) if t == c => i.modify(|b| &b[1..]).ret(c),
+        Some(&c) if t == c => i.replace(&b[1..]).ret(c),
         Some(_)            => i.err(err::expected(t)),
     }
 }
@@ -84,9 +90,11 @@ pub fn token<I: Copy + PartialEq>(i: Input<I>, t: I) -> SimpleResult<I, I> {
 /// ```
 #[inline]
 pub fn not_token<I: Copy + PartialEq>(i: Input<I>, t: I) -> SimpleResult<I, I> {
-    match i.buffer().first() {
+    let b = i.buffer();
+
+    match b.first() {
         None               => i.incomplete(1),
-        Some(&c) if t != c => i.modify(|b| &b[1..]).ret(c),
+        Some(&c) if t != c => i.replace(&b[1..]).ret(c),
         Some(_)            => i.err(err::unexpected()),
     }
 }
@@ -341,9 +349,9 @@ pub fn eof<I>(i: Input<I>) -> SimpleResult<I, ()> {
 
 #[cfg(test)]
 mod test {
-    use internal::input;
-    use internal::ParseResultModify;
-    use internal::State;
+    use primitives::input;
+    use primitives::IntoInner;
+    use primitives::State;
     use super::*;
     use {Input, SimpleResult};
 
@@ -394,9 +402,9 @@ mod test {
 
     #[test]
     fn take_test() {
-        assert_eq!(take(input::new(input::DEFAULT, b"a"), 1).internal(), State::Data(input::new(input::DEFAULT, b""), &b"a"[..]));
-        assert_eq!(take(input::new(input::DEFAULT, b"a"), 2).internal(), State::Incomplete(1));
-        assert_eq!(take(input::new(input::DEFAULT, b"ab"), 1).internal(), State::Data(input::new(input::DEFAULT, b"b"), &b"a"[..]));
-        assert_eq!(take(input::new(input::DEFAULT, b"ab"), 2).internal(), State::Data(input::new(input::DEFAULT, b""), &b"ab"[..]));
+        assert_eq!(take(input::new(input::DEFAULT, b"a"), 1).into_inner(), State::Data(input::new(input::DEFAULT, b""), &b"a"[..]));
+        assert_eq!(take(input::new(input::DEFAULT, b"a"), 2).into_inner(), State::Incomplete(1));
+        assert_eq!(take(input::new(input::DEFAULT, b"ab"), 1).into_inner(), State::Data(input::new(input::DEFAULT, b"b"), &b"a"[..]));
+        assert_eq!(take(input::new(input::DEFAULT, b"ab"), 2).into_inner(), State::Data(input::new(input::DEFAULT, b""), &b"ab"[..]));
     }
 }


Test patch: