Skip to content

Commit

Permalink
issues-1223 Add InputSkip trait
Browse files Browse the repository at this point in the history
  • Loading branch information
ikrivosheev committed Oct 27, 2022
1 parent 3645656 commit 7fb5931
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 9 deletions.
33 changes: 32 additions & 1 deletion src/bytes/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::internal::{Err, IResult, Parser};
use crate::lib::std::ops::RangeFrom;
use crate::lib::std::result::Result::*;
use crate::traits::{
Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake,
Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputSkip, InputTake,
InputTakeAtPosition, Slice, ToUsize,
};

Expand Down Expand Up @@ -414,6 +414,37 @@ where
}
}

/// Skip a slice of N input elements (Input[N..]).
///
/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument.
/// # Example
/// ```rust
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::complete::skip;
///
/// fn skip6(s: &str) -> IResult<&str, ()> {
/// skip(6usize)(s)
/// }
///
/// assert_eq!(skip6("1234567"), Ok(("7", ())));
/// assert_eq!(skip6("things"), Ok(("", ())));
/// assert_eq!(skip6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
/// assert_eq!(skip6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
/// ```
pub fn skip<C, Input, Error: ParseError<Input>>(
count: C,
) -> impl Fn(Input) -> IResult<Input, (), Error>
where
Input: InputIter + InputSkip,
C: ToUsize,
{
let c = count.to_usize();
move |i: Input| match i.slice_index(c) {
Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))),
Ok(index) => Ok((i.skip(index), ())),
}
}

/// Returns the input slice up to the first occurrence of the pattern.
///
/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
Expand Down
8 changes: 4 additions & 4 deletions src/character/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,23 +414,23 @@ where
/// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit))));
/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit))));
/// ```
///
///
/// ## Parsing an integer
/// You can use `digit1` in combination with [`map_res`] to parse an integer:
///
///
/// ```
/// # use nom::{Err, error::{Error, ErrorKind}, IResult, Needed};
/// # use nom::combinator::map_res;
/// # use nom::character::complete::digit1;
/// fn parser(input: &str) -> IResult<&str, u32> {
/// map_res(digit1, str::parse)(input)
/// }
///
///
/// assert_eq!(parser("416"), Ok(("", 416)));
/// assert_eq!(parser("12b"), Ok(("b", 12)));
/// assert!(parser("b").is_err());
/// ```
///
///
/// [`map_res`]: crate::combinator::map_res
pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
where
Expand Down
17 changes: 13 additions & 4 deletions src/sequence/tests.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::*;
use crate::bytes::streaming::{tag, take};
use crate::error::{ErrorKind, Error};
use crate::error::{Error, ErrorKind};
use crate::internal::{Err, IResult, Needed};
use crate::number::streaming::be_u16;

Expand Down Expand Up @@ -275,7 +275,16 @@ fn tuple_test() {

#[test]
fn unit_type() {
assert_eq!(tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"), Ok(("abxsbsh", ())));
assert_eq!(tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"), Ok(("sdfjakdsas", ())));
assert_eq!(tuple::<&'static str, (), Error<&'static str>, ()>(())(""), Ok(("", ())));
assert_eq!(
tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"),
Ok(("abxsbsh", ()))
);
assert_eq!(
tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"),
Ok(("sdfjakdsas", ()))
);
assert_eq!(
tuple::<&'static str, (), Error<&'static str>, ()>(())(""),
Ok(("", ()))
);
}
20 changes: 20 additions & 0 deletions src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,12 @@ pub trait InputTake: Sized {
fn take_split(&self, count: usize) -> (Self, Self);
}

/// Abstracts skipping operation
pub trait InputSkip: Sized {
/// Skip a slice of `count` bytes. panics if count > length
fn skip(&self, count: usize) -> Self;
}

impl<'a> InputIter for &'a [u8] {
type Item = u8;
type Iter = Enumerate<Self::IterElem>;
Expand Down Expand Up @@ -427,6 +433,20 @@ impl<'a> InputTake for &'a str {
}
}

impl<'a> InputSkip for &'a [u8] {
#[inline]
fn skip(&self, count: usize) -> Self {
&self[count..]
}
}

impl<'a> InputSkip for &'a str {
#[inline]
fn skip(&self, count: usize) -> Self {
&self[count..]
}
}

/// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`).
///
/// When implementing a custom input type, it is possible to use directly the
Expand Down

0 comments on commit 7fb5931

Please sign in to comment.