Skip to content

Commit

Permalink
Merge pull request #298 from Marwes/length_prefix
Browse files Browse the repository at this point in the history
feat: Add a length_prefix combinator
  • Loading branch information
Marwes authored Nov 18, 2020
2 parents c8f308f + 996383d commit e47d45b
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 9 deletions.
80 changes: 78 additions & 2 deletions src/parser/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,19 @@ use crate::{
ParseResult::{self, *},
ResultExt, StreamError, Tracked,
},
lib::marker::PhantomData,
lib::{convert::TryFrom, marker::PhantomData},
parser::ParseMode,
};

#[cfg(feature = "std")]
use crate::lib::error::Error as StdError;

#[cfg(not(feature = "std"))]
use crate::lib::fmt;

use crate::stream::{
uncons_range, uncons_while, uncons_while1, wrap_stream_error, Range as StreamRange,
RangeStream, StreamOnce,
RangeStream, StreamErrorFor, StreamOnce,
};

use crate::Parser;
Expand Down Expand Up @@ -626,6 +632,76 @@ where
}
}

#[cfg(feature = "std")]
parser! {
/// Takes a parser which parses a `length` then extracts a range of that length and returns it.
/// Commonly used in binary formats
///
/// ```
/// # use combine::parser::{byte::num::be_u16, range::length_prefix};
/// # use combine::*;
/// # fn main() {
/// let mut input = Vec::new();
/// input.extend_from_slice(&3u16.to_be_bytes());
/// input.extend_from_slice(b"1234");
///
/// let mut parser = length_prefix(be_u16());
/// let result = parser.parse(&input[..]);
/// assert_eq!(result, Ok((&b"123"[..], &b"4"[..])));
/// # }
/// ```
pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
where [
Input: RangeStream,
P: Parser<Input>,
usize: TryFrom<P::Output>,
<usize as TryFrom<P::Output>>::Error: StdError + Send + Sync + 'static,
]
{
len
.and_then(|u| {
usize::try_from(u)
.map_err(StreamErrorFor::<Input>::other)
})
.then_partial(|&mut len| take(len))
}
}

#[cfg(not(feature = "std"))]
parser! {
/// Takes a parser which parses a `length` then extracts a range of that length and returns it.
/// Commonly used in binary formats
///
/// ```
/// # use combine::parser::{byte::num::be_u16, range::length_prefix};
/// # use combine::*;
/// # fn main() {
/// let mut input = Vec::new();
/// input.extend_from_slice(&3u16.to_be_bytes());
/// input.extend_from_slice(b"1234");
///
/// let mut parser = length_prefix(be_u16());
/// let result = parser.parse(&input[..]);
/// assert_eq!(result, Ok((&b"123"[..], &b"4"[..])));
/// # }
/// ```
pub fn length_prefix[Input, P](len: P)(Input) -> Input::Range
where [
Input: RangeStream,
P: Parser<Input>,
usize: TryFrom<P::Output>,
<usize as TryFrom<P::Output>>::Error: fmt::Display + Send + Sync + 'static,
]
{
len
.and_then(|u| {
usize::try_from(u)
.map_err(StreamErrorFor::<Input>::message_format)
})
.then_partial(|&mut len| take(len))
}
}

#[cfg(test)]
mod tests {

Expand Down
14 changes: 7 additions & 7 deletions travis.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
#!/bin/bash -x
set -ex

cargo build
cargo test --all-features
cargo test --all-features --examples
cargo "$@" build
cargo "$@" test --all-features
cargo "$@" test --all-features --examples

cargo test --bench json --bench http -- --test
cargo check --bench mp4 --features mp4
cargo "$@" test --bench json --bench http -- --test
cargo "$@" check --bench mp4 --features mp4

cargo build --no-default-features
cargo test --no-default-features --examples
cargo "$@" build --no-default-features
cargo "$@" test --no-default-features --examples

0 comments on commit e47d45b

Please sign in to comment.