Skip to content

Commit

Permalink
issues-1223 Add take_from combinator
Browse files Browse the repository at this point in the history
  • Loading branch information
ikrivosheev committed Jan 26, 2023
1 parent bf8cddb commit b0cf000
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
31 changes: 31 additions & 0 deletions src/bytes/complete.rs
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,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::take_from;
///
/// fn take_from6(s: &str) -> IResult<&str, ()> {
/// take_from(6usize)(s)
/// }
///
/// assert_eq!(take_from6("1234567"), Ok(("7", ())));
/// assert_eq!(take_from6("things"), Ok(("", ())));
/// assert_eq!(take_from6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
/// assert_eq!(take_from6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
/// ```
pub fn take_from<C, I, Error: ParseError<I>>(
count: C,
) -> impl Fn(I) -> IResult<I, (), Error>
where
I: Input,
C: ToUsize,
{
let c = count.to_usize();
move |i: I| match i.slice_index(c) {
Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))),
Ok(index) => Ok((i.take_from(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
37 changes: 37 additions & 0 deletions src/bytes/streaming.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,43 @@ where
}
}

/// Skip a slice of N input elements (Input[N..]).
///
/// # Streaming Specific
/// *Streaming version* if the input has less than N elements, `take_from` will
/// return a `Err::Incomplete(Needed::new(M))` where M is the number of
/// additional bytes the parser would need to succeed.
/// It is well defined for `&[u8]` as the number of elements is the byte size,
/// but for types like `&str`, we cannot know how many bytes correspond for
/// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)`
///
/// # Example
/// ```rust
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::streaming::take_from;
///
/// fn take_from6(s: &str) -> IResult<&str, ()> {
/// take_from(6usize)(s)
/// }
///
/// assert_eq!(take_from6("1234567"), Ok(("7", ())));
/// assert_eq!(take_from6("things"), Ok(("", ())));
/// assert_eq!(take_from6("short"), Err(Err::Incomplete(Needed::Unknown)));
/// ```
pub fn take_from<C, I, Error: ParseError<I>>(
count: C,
) -> impl Fn(I) -> IResult<I, (), Error>
where
I: Input,
C: ToUsize,
{
let c = count.to_usize();
move |i: I| match i.slice_index(c) {
Err(i) => Err(Err::Incomplete(i)),
Ok(index) => Ok((i.take_from(index), ())),
}
}

/// Returns the input slice up to the first occurrence of the pattern.
///
/// It doesn't consume the pattern.
Expand Down

0 comments on commit b0cf000

Please sign in to comment.