Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
197
third-party/vendor/nom/src/bits/complete.rs
vendored
Normal file
197
third-party/vendor/nom/src/bits/complete.rs
vendored
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
//! Bit level parsers
|
||||
//!
|
||||
|
||||
use crate::error::{ErrorKind, ParseError};
|
||||
use crate::internal::{Err, IResult};
|
||||
use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
|
||||
use crate::traits::{InputIter, InputLength, Slice, ToUsize};
|
||||
|
||||
/// Generates a parser taking `count` bits
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::bits::complete::take;
|
||||
/// # use nom::IResult;
|
||||
/// # use nom::error::{Error, ErrorKind};
|
||||
/// // Input is a tuple of (input: I, bit_offset: usize)
|
||||
/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
|
||||
/// take(count)(input)
|
||||
/// }
|
||||
///
|
||||
/// // Consumes 0 bits, returns 0
|
||||
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
|
||||
///
|
||||
/// // Consumes 4 bits, returns their values and increase offset to 4
|
||||
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
|
||||
///
|
||||
/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
|
||||
/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
|
||||
///
|
||||
/// // Tries to consume 12 bits but only 8 are available
|
||||
/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
|
||||
/// ```
|
||||
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
|
||||
count: C,
|
||||
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
|
||||
C: ToUsize,
|
||||
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
|
||||
{
|
||||
let count = count.to_usize();
|
||||
move |(input, bit_offset): (I, usize)| {
|
||||
if count == 0 {
|
||||
Ok(((input, bit_offset), 0u8.into()))
|
||||
} else {
|
||||
let cnt = (count + bit_offset).div(8);
|
||||
if input.input_len() * 8 < count + bit_offset {
|
||||
Err(Err::Error(E::from_error_kind(
|
||||
(input, bit_offset),
|
||||
ErrorKind::Eof,
|
||||
)))
|
||||
} else {
|
||||
let mut acc: O = 0_u8.into();
|
||||
let mut offset: usize = bit_offset;
|
||||
let mut remaining: usize = count;
|
||||
let mut end_offset: usize = 0;
|
||||
|
||||
for byte in input.iter_elements().take(cnt + 1) {
|
||||
if remaining == 0 {
|
||||
break;
|
||||
}
|
||||
let val: O = if offset == 0 {
|
||||
byte.into()
|
||||
} else {
|
||||
((byte << offset) as u8 >> offset).into()
|
||||
};
|
||||
|
||||
if remaining < 8 - offset {
|
||||
acc += val >> (8 - offset - remaining);
|
||||
end_offset = remaining + offset;
|
||||
break;
|
||||
} else {
|
||||
acc += val << (remaining - (8 - offset));
|
||||
remaining -= 8 - offset;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
Ok(((input.slice(cnt..), end_offset), acc))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a parser taking `count` bits and comparing them to `pattern`
|
||||
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
|
||||
pattern: O,
|
||||
count: C,
|
||||
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
|
||||
C: ToUsize,
|
||||
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
|
||||
{
|
||||
let count = count.to_usize();
|
||||
move |input: (I, usize)| {
|
||||
let inp = input.clone();
|
||||
|
||||
take(count)(input).and_then(|(i, o)| {
|
||||
if pattern == o {
|
||||
Ok((i, o))
|
||||
} else {
|
||||
Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses one specific bit as a bool.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::bits::complete::bool;
|
||||
/// # use nom::IResult;
|
||||
/// # use nom::error::{Error, ErrorKind};
|
||||
///
|
||||
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
|
||||
/// bool(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
|
||||
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
|
||||
/// ```
|
||||
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
|
||||
{
|
||||
let (res, bit): (_, u32) = take(1usize)(input)?;
|
||||
Ok((res, bit != 0))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_take_0() {
|
||||
let input = [0b00010010].as_ref();
|
||||
let count = 0usize;
|
||||
assert_eq!(count, 0usize);
|
||||
let offset = 0usize;
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
|
||||
|
||||
assert_eq!(result, Ok(((input, offset), 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_take_eof() {
|
||||
let input = [0b00010010].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(crate::Err::Error(crate::error::Error {
|
||||
input: (input, 8),
|
||||
code: ErrorKind::Eof
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_take_span_over_multiple_bytes() {
|
||||
let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_0() {
|
||||
let input = [0b10000000].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
|
||||
|
||||
assert_eq!(result, Ok(((input, 1), true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_eof() {
|
||||
let input = [0b10000000].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(crate::Err::Error(crate::error::Error {
|
||||
input: (input, 8),
|
||||
code: ErrorKind::Eof
|
||||
}))
|
||||
);
|
||||
}
|
||||
}
|
||||
179
third-party/vendor/nom/src/bits/mod.rs
vendored
Normal file
179
third-party/vendor/nom/src/bits/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,179 @@
|
|||
//! Bit level parsers
|
||||
//!
|
||||
|
||||
pub mod complete;
|
||||
pub mod streaming;
|
||||
|
||||
use crate::error::{ErrorKind, ParseError};
|
||||
use crate::internal::{Err, IResult, Needed, Parser};
|
||||
use crate::lib::std::ops::RangeFrom;
|
||||
use crate::traits::{ErrorConvert, Slice};
|
||||
|
||||
/// Converts a byte-level input to a bit-level input, for consumption by a parser that uses bits.
|
||||
///
|
||||
/// Afterwards, the input is converted back to a byte-level parser, with any remaining bits thrown
|
||||
/// away.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// use nom::bits::{bits, streaming::take};
|
||||
/// use nom::error::Error;
|
||||
/// use nom::sequence::tuple;
|
||||
/// use nom::IResult;
|
||||
///
|
||||
/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
|
||||
/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input)
|
||||
/// }
|
||||
///
|
||||
/// let input = &[0x12, 0x34, 0xff, 0xff];
|
||||
///
|
||||
/// let output = parse(input).expect("We take 1.5 bytes and the input is longer than 2 bytes");
|
||||
///
|
||||
/// // The first byte is consumed, the second byte is partially consumed and dropped.
|
||||
/// let remaining = output.0;
|
||||
/// assert_eq!(remaining, [0xff, 0xff]);
|
||||
///
|
||||
/// let parsed = output.1;
|
||||
/// assert_eq!(parsed.0, 0x01);
|
||||
/// assert_eq!(parsed.1, 0x23);
|
||||
/// ```
|
||||
pub fn bits<I, O, E1, E2, P>(mut parser: P) -> impl FnMut(I) -> IResult<I, O, E2>
|
||||
where
|
||||
E1: ParseError<(I, usize)> + ErrorConvert<E2>,
|
||||
E2: ParseError<I>,
|
||||
I: Slice<RangeFrom<usize>>,
|
||||
P: Parser<(I, usize), O, E1>,
|
||||
{
|
||||
move |input: I| match parser.parse((input, 0)) {
|
||||
Ok(((rest, offset), result)) => {
|
||||
// If the next byte has been partially read, it will be sliced away as well.
|
||||
// The parser functions might already slice away all fully read bytes.
|
||||
// That's why `offset / 8` isn't necessarily needed at all times.
|
||||
let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 };
|
||||
Ok((rest.slice(remaining_bytes_index..), result))
|
||||
}
|
||||
Err(Err::Incomplete(n)) => Err(Err::Incomplete(n.map(|u| u.get() / 8 + 1))),
|
||||
Err(Err::Error(e)) => Err(Err::Error(e.convert())),
|
||||
Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
|
||||
}
|
||||
}
|
||||
|
||||
/// Counterpart to `bits`, `bytes` transforms its bit stream input into a byte slice for the underlying
|
||||
/// parser, allowing byte-slice parsers to work on bit streams.
|
||||
///
|
||||
/// A partial byte remaining in the input will be ignored and the given parser will start parsing
|
||||
/// at the next full byte.
|
||||
///
|
||||
/// ```
|
||||
/// use nom::bits::{bits, bytes, streaming::take};
|
||||
/// use nom::combinator::rest;
|
||||
/// use nom::error::Error;
|
||||
/// use nom::sequence::tuple;
|
||||
/// use nom::IResult;
|
||||
///
|
||||
/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8, &[u8])> {
|
||||
/// bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((
|
||||
/// take(4usize),
|
||||
/// take(8usize),
|
||||
/// bytes::<_, _, Error<&[u8]>, _, _>(rest)
|
||||
/// )))(input)
|
||||
/// }
|
||||
///
|
||||
/// let input = &[0x12, 0x34, 0xff, 0xff];
|
||||
///
|
||||
/// assert_eq!(parse( input ), Ok(( &[][..], (0x01, 0x23, &[0xff, 0xff][..]) )));
|
||||
/// ```
|
||||
pub fn bytes<I, O, E1, E2, P>(mut parser: P) -> impl FnMut((I, usize)) -> IResult<(I, usize), O, E2>
|
||||
where
|
||||
E1: ParseError<I> + ErrorConvert<E2>,
|
||||
E2: ParseError<(I, usize)>,
|
||||
I: Slice<RangeFrom<usize>> + Clone,
|
||||
P: Parser<I, O, E1>,
|
||||
{
|
||||
move |(input, offset): (I, usize)| {
|
||||
let inner = if offset % 8 != 0 {
|
||||
input.slice((1 + offset / 8)..)
|
||||
} else {
|
||||
input.slice((offset / 8)..)
|
||||
};
|
||||
let i = (input, offset);
|
||||
match parser.parse(inner) {
|
||||
Ok((rest, res)) => Ok(((rest, 0), res)),
|
||||
Err(Err::Incomplete(Needed::Unknown)) => Err(Err::Incomplete(Needed::Unknown)),
|
||||
Err(Err::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) {
|
||||
Some(v) => Err::Incomplete(Needed::new(v)),
|
||||
None => Err::Failure(E2::from_error_kind(i, ErrorKind::TooLarge)),
|
||||
}),
|
||||
Err(Err::Error(e)) => Err(Err::Error(e.convert())),
|
||||
Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::bits::streaming::take;
|
||||
use crate::error::Error;
|
||||
use crate::sequence::tuple;
|
||||
|
||||
#[test]
|
||||
/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
|
||||
/// previous bytes are fully consumed
|
||||
fn test_complete_byte_consumption_bits() {
|
||||
let input = &[0x12, 0x34, 0x56, 0x78];
|
||||
|
||||
// Take 3 bit slices with sizes [4, 8, 4].
|
||||
let result: IResult<&[u8], (u8, u8, u8)> =
|
||||
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize), take(4usize))))(
|
||||
input,
|
||||
);
|
||||
|
||||
let output = result.expect("We take 2 bytes and the input is longer than 2 bytes");
|
||||
|
||||
let remaining = output.0;
|
||||
assert_eq!(remaining, [0x56, 0x78]);
|
||||
|
||||
let parsed = output.1;
|
||||
assert_eq!(parsed.0, 0x01);
|
||||
assert_eq!(parsed.1, 0x23);
|
||||
assert_eq!(parsed.2, 0x04);
|
||||
}
|
||||
|
||||
#[test]
|
||||
/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
|
||||
/// previous bytes are NOT fully consumed. Partially consumed bytes are supposed to be dropped.
|
||||
/// I.e. if we consume 1.5 bytes of 4 bytes, 2 bytes will be returned, bits 13-16 will be
|
||||
/// dropped.
|
||||
fn test_partial_byte_consumption_bits() {
|
||||
let input = &[0x12, 0x34, 0x56, 0x78];
|
||||
|
||||
// Take bit slices with sizes [4, 8].
|
||||
let result: IResult<&[u8], (u8, u8)> =
|
||||
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input);
|
||||
|
||||
let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes");
|
||||
|
||||
let remaining = output.0;
|
||||
assert_eq!(remaining, [0x56, 0x78]);
|
||||
|
||||
let parsed = output.1;
|
||||
assert_eq!(parsed.0, 0x01);
|
||||
assert_eq!(parsed.1, 0x23);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
/// Ensure that in Incomplete error is thrown, if too few bytes are passed for a given parser.
|
||||
fn test_incomplete_bits() {
|
||||
let input = &[0x12];
|
||||
|
||||
// Take bit slices with sizes [4, 8].
|
||||
let result: IResult<&[u8], (u8, u8)> =
|
||||
bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple((take(4usize), take(8usize))))(input);
|
||||
|
||||
assert!(result.is_err());
|
||||
let error = result.err().unwrap();
|
||||
assert_eq!("Parsing requires 2 bytes/chars", error.to_string());
|
||||
}
|
||||
}
|
||||
170
third-party/vendor/nom/src/bits/streaming.rs
vendored
Normal file
170
third-party/vendor/nom/src/bits/streaming.rs
vendored
Normal file
|
|
@ -0,0 +1,170 @@
|
|||
//! Bit level parsers
|
||||
//!
|
||||
|
||||
use crate::error::{ErrorKind, ParseError};
|
||||
use crate::internal::{Err, IResult, Needed};
|
||||
use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
|
||||
use crate::traits::{InputIter, InputLength, Slice, ToUsize};
|
||||
|
||||
/// Generates a parser taking `count` bits
|
||||
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
|
||||
count: C,
|
||||
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
|
||||
C: ToUsize,
|
||||
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
|
||||
{
|
||||
let count = count.to_usize();
|
||||
move |(input, bit_offset): (I, usize)| {
|
||||
if count == 0 {
|
||||
Ok(((input, bit_offset), 0u8.into()))
|
||||
} else {
|
||||
let cnt = (count + bit_offset).div(8);
|
||||
if input.input_len() * 8 < count + bit_offset {
|
||||
Err(Err::Incomplete(Needed::new(count as usize)))
|
||||
} else {
|
||||
let mut acc: O = 0_u8.into();
|
||||
let mut offset: usize = bit_offset;
|
||||
let mut remaining: usize = count;
|
||||
let mut end_offset: usize = 0;
|
||||
|
||||
for byte in input.iter_elements().take(cnt + 1) {
|
||||
if remaining == 0 {
|
||||
break;
|
||||
}
|
||||
let val: O = if offset == 0 {
|
||||
byte.into()
|
||||
} else {
|
||||
((byte << offset) as u8 >> offset).into()
|
||||
};
|
||||
|
||||
if remaining < 8 - offset {
|
||||
acc += val >> (8 - offset - remaining);
|
||||
end_offset = remaining + offset;
|
||||
break;
|
||||
} else {
|
||||
acc += val << (remaining - (8 - offset));
|
||||
remaining -= 8 - offset;
|
||||
offset = 0;
|
||||
}
|
||||
}
|
||||
Ok(((input.slice(cnt..), end_offset), acc))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a parser taking `count` bits and comparing them to `pattern`
|
||||
pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
|
||||
pattern: O,
|
||||
count: C,
|
||||
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
|
||||
C: ToUsize,
|
||||
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
|
||||
{
|
||||
let count = count.to_usize();
|
||||
move |input: (I, usize)| {
|
||||
let inp = input.clone();
|
||||
|
||||
take(count)(input).and_then(|(i, o)| {
|
||||
if pattern == o {
|
||||
Ok((i, o))
|
||||
} else {
|
||||
Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses one specific bit as a bool.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::bits::complete::bool;
|
||||
/// # use nom::IResult;
|
||||
/// # use nom::error::{Error, ErrorKind};
|
||||
///
|
||||
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
|
||||
/// bool(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
|
||||
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
|
||||
/// ```
|
||||
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
|
||||
where
|
||||
I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
|
||||
{
|
||||
let (res, bit): (_, u32) = take(1usize)(input)?;
|
||||
Ok((res, bit != 0))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_take_0() {
|
||||
let input = [].as_ref();
|
||||
let count = 0usize;
|
||||
assert_eq!(count, 0usize);
|
||||
let offset = 0usize;
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
|
||||
|
||||
assert_eq!(result, Ok(((input, offset), 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tag_ok() {
|
||||
let input = [0b00011111].as_ref();
|
||||
let offset = 0usize;
|
||||
let bits_to_take = 4usize;
|
||||
let value_to_tag = 0b0001;
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> =
|
||||
tag(value_to_tag, bits_to_take)((input, offset));
|
||||
|
||||
assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tag_err() {
|
||||
let input = [0b00011111].as_ref();
|
||||
let offset = 0usize;
|
||||
let bits_to_take = 4usize;
|
||||
let value_to_tag = 0b1111;
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), usize> =
|
||||
tag(value_to_tag, bits_to_take)((input, offset));
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
Err(crate::Err::Error(crate::error::Error {
|
||||
input: (input, offset),
|
||||
code: ErrorKind::TagBits
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_0() {
|
||||
let input = [0b10000000].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
|
||||
|
||||
assert_eq!(result, Ok(((input, 1), true)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bool_eof() {
|
||||
let input = [0b10000000].as_ref();
|
||||
|
||||
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
|
||||
|
||||
assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
}
|
||||
267
third-party/vendor/nom/src/branch/mod.rs
vendored
Normal file
267
third-party/vendor/nom/src/branch/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
//! Choice combinators
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::error::ErrorKind;
|
||||
use crate::error::ParseError;
|
||||
use crate::internal::{Err, IResult, Parser};
|
||||
|
||||
/// Helper trait for the [alt()] combinator.
|
||||
///
|
||||
/// This trait is implemented for tuples of up to 21 elements
|
||||
pub trait Alt<I, O, E> {
|
||||
/// Tests each parser in the tuple and returns the result of the first one that succeeds
|
||||
fn choice(&mut self, input: I) -> IResult<I, O, E>;
|
||||
}
|
||||
|
||||
/// Tests a list of parsers one by one until one succeeds.
|
||||
///
|
||||
/// It takes as argument a tuple of parsers. There is a maximum of 21
|
||||
/// parsers. If you need more, it is possible to nest them in other `alt` calls,
|
||||
/// like this: `alt(parser_a, alt(parser_b, parser_c))`
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::error_position;
|
||||
/// # use nom::{Err,error::ErrorKind, Needed, IResult};
|
||||
/// use nom::character::complete::{alpha1, digit1};
|
||||
/// use nom::branch::alt;
|
||||
/// # fn main() {
|
||||
/// fn parser(input: &str) -> IResult<&str, &str> {
|
||||
/// alt((alpha1, digit1))(input)
|
||||
/// };
|
||||
///
|
||||
/// // the first parser, alpha1, recognizes the input
|
||||
/// assert_eq!(parser("abc"), Ok(("", "abc")));
|
||||
///
|
||||
/// // the first parser returns an error, so alt tries the second one
|
||||
/// assert_eq!(parser("123456"), Ok(("", "123456")));
|
||||
///
|
||||
/// // both parsers failed, and with the default error type, alt will return the last error
|
||||
/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// With a custom error type, it is possible to have alt return the error of the parser
|
||||
/// that went the farthest in the input data
|
||||
pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
|
||||
mut l: List,
|
||||
) -> impl FnMut(I) -> IResult<I, O, E> {
|
||||
move |i: I| l.choice(i)
|
||||
}
|
||||
|
||||
/// Helper trait for the [permutation()] combinator.
|
||||
///
|
||||
/// This trait is implemented for tuples of up to 21 elements
|
||||
pub trait Permutation<I, O, E> {
|
||||
/// Tries to apply all parsers in the tuple in various orders until all of them succeed
|
||||
fn permutation(&mut self, input: I) -> IResult<I, O, E>;
|
||||
}
|
||||
|
||||
/// Applies a list of parsers in any order.
|
||||
///
|
||||
/// Permutation will succeed if all of the child parsers succeeded.
|
||||
/// It takes as argument a tuple of parsers, and returns a
|
||||
/// tuple of the parser results.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::character::complete::{alpha1, digit1};
|
||||
/// use nom::branch::permutation;
|
||||
/// # fn main() {
|
||||
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
|
||||
/// permutation((alpha1, digit1))(input)
|
||||
/// }
|
||||
///
|
||||
/// // permutation recognizes alphabetic characters then digit
|
||||
/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
|
||||
///
|
||||
/// // but also in inverse order
|
||||
/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
|
||||
///
|
||||
/// // it will fail if one of the parsers failed
|
||||
/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit))));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The parsers are applied greedily: if there are multiple unapplied parsers
|
||||
/// that could parse the next slice of input, the first one is used.
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, IResult};
|
||||
/// use nom::branch::permutation;
|
||||
/// use nom::character::complete::{anychar, char};
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, (char, char)> {
|
||||
/// permutation((anychar, char('a')))(input)
|
||||
/// }
|
||||
///
|
||||
/// // anychar parses 'b', then char('a') parses 'a'
|
||||
/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
|
||||
///
|
||||
/// // anychar parses 'a', then char('a') fails on 'b',
|
||||
/// // even though char('a') followed by anychar would succeed
|
||||
/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char))));
|
||||
/// ```
|
||||
///
|
||||
pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
|
||||
mut l: List,
|
||||
) -> impl FnMut(I) -> IResult<I, O, E> {
|
||||
move |i: I| l.permutation(i)
|
||||
}
|
||||
|
||||
macro_rules! alt_trait(
|
||||
($first:ident $second:ident $($id: ident)+) => (
|
||||
alt_trait!(__impl $first $second; $($id)+);
|
||||
);
|
||||
(__impl $($current:ident)*; $head:ident $($id: ident)+) => (
|
||||
alt_trait_impl!($($current)*);
|
||||
|
||||
alt_trait!(__impl $($current)* $head; $($id)+);
|
||||
);
|
||||
(__impl $($current:ident)*; $head:ident) => (
|
||||
alt_trait_impl!($($current)*);
|
||||
alt_trait_impl!($($current)* $head);
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! alt_trait_impl(
|
||||
($($id:ident)+) => (
|
||||
impl<
|
||||
Input: Clone, Output, Error: ParseError<Input>,
|
||||
$($id: Parser<Input, Output, Error>),+
|
||||
> Alt<Input, Output, Error> for ( $($id),+ ) {
|
||||
|
||||
fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
|
||||
match self.0.parse(input.clone()) {
|
||||
Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! alt_trait_inner(
|
||||
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Err(Err::Error(e)) => {
|
||||
let err = $err.or(e);
|
||||
succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
|
||||
}
|
||||
res => res,
|
||||
}
|
||||
);
|
||||
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
|
||||
Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
|
||||
);
|
||||
);
|
||||
|
||||
alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
|
||||
|
||||
// Manually implement Alt for (A,), the 1-tuple type
|
||||
impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
|
||||
Alt<Input, Output, Error> for (A,)
|
||||
{
|
||||
fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
|
||||
self.0.parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! permutation_trait(
|
||||
(
|
||||
$name1:ident $ty1:ident $item1:ident
|
||||
$name2:ident $ty2:ident $item2:ident
|
||||
$($name3:ident $ty3:ident $item3:ident)*
|
||||
) => (
|
||||
permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
|
||||
);
|
||||
(
|
||||
__impl $($name:ident $ty:ident $item:ident),+;
|
||||
$name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
|
||||
) => (
|
||||
permutation_trait_impl!($($name $ty $item),+);
|
||||
permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
|
||||
);
|
||||
(__impl $($name:ident $ty:ident $item:ident),+;) => (
|
||||
permutation_trait_impl!($($name $ty $item),+);
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! permutation_trait_impl(
|
||||
($($name:ident $ty:ident $item:ident),+) => (
|
||||
impl<
|
||||
Input: Clone, $($ty),+ , Error: ParseError<Input>,
|
||||
$($name: Parser<Input, $ty, Error>),+
|
||||
> Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
|
||||
|
||||
fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
|
||||
let mut res = ($(Option::<$ty>::None),+);
|
||||
|
||||
loop {
|
||||
let mut err: Option<Error> = None;
|
||||
permutation_trait_inner!(0, self, input, res, err, $($name)+);
|
||||
|
||||
// If we reach here, every iterator has either been applied before,
|
||||
// or errored on the remaining input
|
||||
if let Some(err) = err {
|
||||
// There are remaining parsers, and all errored on the remaining input
|
||||
return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
|
||||
}
|
||||
|
||||
// All parsers were applied
|
||||
match res {
|
||||
($(Some($item)),+) => return Ok((input, ($($item),+))),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! permutation_trait_inner(
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
|
||||
if $res.$it.is_none() {
|
||||
match $self.$it.parse($input.clone()) {
|
||||
Ok((i, o)) => {
|
||||
$input = i;
|
||||
$res.$it = Some(o);
|
||||
continue;
|
||||
}
|
||||
Err(Err::Error(e)) => {
|
||||
$err = Some(match $err {
|
||||
Some(err) => err.or(e),
|
||||
None => e,
|
||||
});
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
};
|
||||
}
|
||||
succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
|
||||
);
|
||||
($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
|
||||
);
|
||||
|
||||
permutation_trait!(
|
||||
FnA A a
|
||||
FnB B b
|
||||
FnC C c
|
||||
FnD D d
|
||||
FnE E e
|
||||
FnF F f
|
||||
FnG G g
|
||||
FnH H h
|
||||
FnI I i
|
||||
FnJ J j
|
||||
FnK K k
|
||||
FnL L l
|
||||
FnM M m
|
||||
FnN N n
|
||||
FnO O o
|
||||
FnP P p
|
||||
FnQ Q q
|
||||
FnR R r
|
||||
FnS S s
|
||||
FnT T t
|
||||
FnU U u
|
||||
);
|
||||
142
third-party/vendor/nom/src/branch/tests.rs
vendored
Normal file
142
third-party/vendor/nom/src/branch/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
use crate::branch::{alt, permutation};
|
||||
use crate::bytes::streaming::tag;
|
||||
use crate::error::ErrorKind;
|
||||
use crate::internal::{Err, IResult, Needed};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::{
|
||||
error::ParseError,
|
||||
lib::std::{
|
||||
fmt::Debug,
|
||||
string::{String, ToString},
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct ErrorStr(String);
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl From<u32> for ErrorStr {
|
||||
fn from(i: u32) -> Self {
|
||||
ErrorStr(format!("custom error code: {}", i))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a> From<&'a str> for ErrorStr {
|
||||
fn from(i: &'a str) -> Self {
|
||||
ErrorStr(format!("custom error message: {}", i))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<I: Debug> ParseError<I> for ErrorStr {
|
||||
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
|
||||
ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
|
||||
}
|
||||
|
||||
fn append(input: I, kind: ErrorKind, other: Self) -> Self {
|
||||
ErrorStr(format!(
|
||||
"custom error message: ({:?}, {:?}) - {:?}",
|
||||
input, kind, other
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn alt_test() {
|
||||
fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
Ok((&b""[..], input))
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
Err(Err::Error(ErrorStr("abcd".to_string())))
|
||||
}
|
||||
|
||||
fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
Ok((input, &b""[..]))
|
||||
}
|
||||
|
||||
fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
alt((dont_work, dont_work))(i)
|
||||
}
|
||||
fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
alt((dont_work, work))(i)
|
||||
}
|
||||
fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
|
||||
alt((dont_work, dont_work, work2, dont_work))(i)
|
||||
}
|
||||
//named!(alt1, alt!(dont_work | dont_work));
|
||||
//named!(alt2, alt!(dont_work | work));
|
||||
//named!(alt3, alt!(dont_work | dont_work | work2 | dont_work));
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(
|
||||
alt1(a),
|
||||
Err(Err::Error(error_node_position!(
|
||||
a,
|
||||
ErrorKind::Alt,
|
||||
ErrorStr("abcd".to_string())
|
||||
)))
|
||||
);
|
||||
assert_eq!(alt2(a), Ok((&b""[..], a)));
|
||||
assert_eq!(alt3(a), Ok((a, &b""[..])));
|
||||
|
||||
fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
alt((tag("abcd"), tag("efgh")))(i)
|
||||
}
|
||||
let b = &b"efgh"[..];
|
||||
assert_eq!(alt4(a), Ok((&b""[..], a)));
|
||||
assert_eq!(alt4(b), Ok((&b""[..], b)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn alt_incomplete() {
|
||||
fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
alt((tag("a"), tag("bc"), tag("def")))(i)
|
||||
}
|
||||
|
||||
let a = &b""[..];
|
||||
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
|
||||
let a = &b"b"[..];
|
||||
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
|
||||
let a = &b"bcd"[..];
|
||||
assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..])));
|
||||
let a = &b"cde"[..];
|
||||
assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Tag))));
|
||||
let a = &b"de"[..];
|
||||
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
|
||||
let a = &b"defg"[..];
|
||||
assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn permutation_test() {
|
||||
fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
|
||||
permutation((tag("abcd"), tag("efg"), tag("hi")))(i)
|
||||
}
|
||||
|
||||
let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
|
||||
|
||||
let a = &b"abcdefghijk"[..];
|
||||
assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
|
||||
let b = &b"efgabcdhijk"[..];
|
||||
assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
|
||||
let c = &b"hiefgabcdjk"[..];
|
||||
assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
|
||||
|
||||
let d = &b"efgxyzabcdefghi"[..];
|
||||
assert_eq!(
|
||||
perm(d),
|
||||
Err(Err::Error(error_node_position!(
|
||||
&b"efgxyzabcdefghi"[..],
|
||||
ErrorKind::Permutation,
|
||||
error_position!(&b"xyzabcdefghi"[..], ErrorKind::Tag)
|
||||
)))
|
||||
);
|
||||
|
||||
let e = &b"efgabc"[..];
|
||||
assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
756
third-party/vendor/nom/src/bytes/complete.rs
vendored
Normal file
756
third-party/vendor/nom/src/bytes/complete.rs
vendored
Normal file
|
|
@ -0,0 +1,756 @@
|
|||
//! Parsers recognizing bytes streams, complete input version
|
||||
|
||||
use crate::error::ErrorKind;
|
||||
use crate::error::ParseError;
|
||||
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,
|
||||
InputTakeAtPosition, Slice, ToUsize,
|
||||
};
|
||||
|
||||
/// Recognizes a pattern
|
||||
///
|
||||
/// The input data will be compared to the tag combinator's argument and will return the part of
|
||||
/// the input that matches the argument
|
||||
///
|
||||
/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// fn parser(s: &str) -> IResult<&str, &str> {
|
||||
/// tag("Hello")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
|
||||
/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn tag<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + Compare<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let tag_len = tag.input_len();
|
||||
let t = tag.clone();
|
||||
let res: IResult<_, _, Error> = match i.compare(t) {
|
||||
CompareResult::Ok => Ok(i.take_split(tag_len)),
|
||||
_ => {
|
||||
let e: ErrorKind = ErrorKind::Tag;
|
||||
Err(Err::Error(Error::from_error_kind(i, e)))
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Recognizes a case insensitive pattern.
|
||||
///
|
||||
/// The input data will be compared to the tag combinator's argument and will return the part of
|
||||
/// the input that matches the argument with no regard to case.
|
||||
///
|
||||
/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::tag_no_case;
|
||||
///
|
||||
/// fn parser(s: &str) -> IResult<&str, &str> {
|
||||
/// tag_no_case("hello")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
|
||||
/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
|
||||
/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
|
||||
/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn tag_no_case<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + Compare<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let tag_len = tag.input_len();
|
||||
let t = tag.clone();
|
||||
|
||||
let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
|
||||
CompareResult::Ok => Ok(i.take_split(tag_len)),
|
||||
_ => {
|
||||
let e: ErrorKind = ErrorKind::Tag;
|
||||
Err(Err::Error(Error::from_error_kind(i, e)))
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse till certain characters are met.
|
||||
///
|
||||
/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
|
||||
///
|
||||
/// It doesn't consume the matched character.
|
||||
///
|
||||
/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::is_not;
|
||||
///
|
||||
/// fn not_space(s: &str) -> IResult<&str, &str> {
|
||||
/// is_not(" \t\r\n")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
|
||||
/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
|
||||
/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
|
||||
/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot))));
|
||||
/// ```
|
||||
pub fn is_not<T, Input, Error: ParseError<Input>>(
|
||||
arr: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
T: FindToken<<Input as InputTakeAtPosition>::Item>,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::IsNot;
|
||||
i.split_at_position1_complete(|c| arr.find_token(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest slice of the matches the pattern.
|
||||
///
|
||||
/// The parser will return the longest slice consisting of the characters in provided in the
|
||||
/// combinator's argument.
|
||||
///
|
||||
/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::is_a;
|
||||
///
|
||||
/// fn hex(s: &str) -> IResult<&str, &str> {
|
||||
/// is_a("1234567890ABCDEF")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
|
||||
/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
|
||||
/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
|
||||
/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
|
||||
/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA))));
|
||||
/// ```
|
||||
pub fn is_a<T, Input, Error: ParseError<Input>>(
|
||||
arr: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
T: FindToken<<Input as InputTakeAtPosition>::Item>,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::IsA;
|
||||
i.split_at_position1_complete(|c| !arr.find_token(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest input slice (if any) that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_while;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while(is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
|
||||
/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
|
||||
/// ```
|
||||
pub fn take_while<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| i.split_at_position_complete(|c| !cond(c))
|
||||
}
|
||||
|
||||
/// Returns the longest (at least 1) input slice that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_while1;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while1(is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
|
||||
/// ```
|
||||
pub fn take_while1<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::TakeWhile1;
|
||||
i.split_at_position1_complete(|c| !cond(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest (m <= len <= n) input slice that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out
|
||||
/// of range (m <= len <= n).
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_while_m_n;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while_m_n(3, 6, is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
|
||||
/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
|
||||
/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN))));
|
||||
/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
|
||||
/// ```
|
||||
pub fn take_while_m_n<F, Input, Error: ParseError<Input>>(
|
||||
m: usize,
|
||||
n: usize,
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
|
||||
F: Fn(<Input as InputIter>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let input = i;
|
||||
|
||||
match input.position(|c| !cond(c)) {
|
||||
Some(idx) => {
|
||||
if idx >= m {
|
||||
if idx <= n {
|
||||
let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) {
|
||||
Ok(input.take_split(index))
|
||||
} else {
|
||||
Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
)))
|
||||
};
|
||||
res
|
||||
} else {
|
||||
let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) {
|
||||
Ok(input.take_split(index))
|
||||
} else {
|
||||
Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
)))
|
||||
};
|
||||
res
|
||||
}
|
||||
} else {
|
||||
let e = ErrorKind::TakeWhileMN;
|
||||
Err(Err::Error(Error::from_error_kind(input, e)))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let len = input.input_len();
|
||||
if len >= n {
|
||||
match input.slice_index(n) {
|
||||
Ok(index) => Ok(input.take_split(index)),
|
||||
Err(_needed) => Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
))),
|
||||
}
|
||||
} else if len >= m && len <= n {
|
||||
let res: IResult<_, _, Error> = Ok((input.slice(len..), input));
|
||||
res
|
||||
} else {
|
||||
let e = ErrorKind::TakeWhileMN;
|
||||
Err(Err::Error(Error::from_error_kind(input, e)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest input slice (if any) till a predicate is met.
|
||||
///
|
||||
/// The parser will return the longest slice till the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_till;
|
||||
///
|
||||
/// fn till_colon(s: &str) -> IResult<&str, &str> {
|
||||
/// take_till(|c| c == ':')(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
|
||||
/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
|
||||
/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
|
||||
/// assert_eq!(till_colon(""), Ok(("", "")));
|
||||
/// ```
|
||||
pub fn take_till<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| i.split_at_position_complete(|c| cond(c))
|
||||
}
|
||||
|
||||
/// Returns the longest (at least 1) input slice till a predicate is met.
|
||||
///
|
||||
/// The parser will return the longest slice till the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the
|
||||
/// predicate matches the first input.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_till1;
|
||||
///
|
||||
/// fn till_colon(s: &str) -> IResult<&str, &str> {
|
||||
/// take_till1(|c| c == ':')(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
|
||||
/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
|
||||
/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
|
||||
/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
|
||||
/// ```
|
||||
pub fn take_till1<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::TakeTill1;
|
||||
i.split_at_position1_complete(|c| cond(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an input slice containing the first 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;
|
||||
///
|
||||
/// fn take6(s: &str) -> IResult<&str, &str> {
|
||||
/// take(6usize)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
|
||||
/// assert_eq!(take6("things"), Ok(("", "things")));
|
||||
/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
|
||||
/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
|
||||
/// ```
|
||||
///
|
||||
/// The units that are taken will depend on the input type. For example, for a
|
||||
/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
|
||||
/// take that many `u8`'s:
|
||||
///
|
||||
/// ```rust
|
||||
/// use nom::error::Error;
|
||||
/// use nom::bytes::complete::take;
|
||||
///
|
||||
/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙")));
|
||||
/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
|
||||
/// ```
|
||||
pub fn take<C, Input, Error: ParseError<Input>>(
|
||||
count: C,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputIter + InputTake,
|
||||
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.take_split(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)))`
|
||||
/// if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_until;
|
||||
///
|
||||
/// fn until_eof(s: &str) -> IResult<&str, &str> {
|
||||
/// take_until("eof")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
|
||||
/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
|
||||
/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
|
||||
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
|
||||
/// ```
|
||||
pub fn take_until<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + FindSubstring<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let t = tag.clone();
|
||||
let res: IResult<_, _, Error> = match i.find_substring(t) {
|
||||
None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
|
||||
Some(index) => Ok(i.take_split(index)),
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the non empty input slice up to the first occurrence of the pattern.
|
||||
///
|
||||
/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
|
||||
/// if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::complete::take_until1;
|
||||
///
|
||||
/// fn until_eof(s: &str) -> IResult<&str, &str> {
|
||||
/// take_until1("eof")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
|
||||
/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
|
||||
/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
|
||||
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
|
||||
/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
|
||||
/// ```
|
||||
pub fn take_until1<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + FindSubstring<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let t = tag.clone();
|
||||
let res: IResult<_, _, Error> = match i.find_substring(t) {
|
||||
None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
|
||||
Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
|
||||
Some(index) => Ok(i.take_split(index)),
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a byte string with escaped characters.
|
||||
///
|
||||
/// * The first argument matches the normal characters (it must not accept the control character)
|
||||
/// * The second argument is the control character (like `\` in most languages)
|
||||
/// * The third argument matches the escaped characters
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// # use nom::character::complete::digit1;
|
||||
/// use nom::bytes::complete::escaped;
|
||||
/// use nom::character::complete::one_of;
|
||||
///
|
||||
/// fn esc(s: &str) -> IResult<&str, &str> {
|
||||
/// escaped(digit1, '\\', one_of(r#""n\"#))(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(esc("123;"), Ok((";", "123")));
|
||||
/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#)));
|
||||
/// ```
|
||||
///
|
||||
pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>(
|
||||
mut normal: F,
|
||||
control_char: char,
|
||||
mut escapable: G,
|
||||
) -> impl FnMut(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: Clone
|
||||
+ crate::traits::Offset
|
||||
+ InputLength
|
||||
+ InputTake
|
||||
+ InputTakeAtPosition
|
||||
+ Slice<RangeFrom<usize>>
|
||||
+ InputIter,
|
||||
<Input as InputIter>::Item: crate::traits::AsChar,
|
||||
F: Parser<Input, O1, Error>,
|
||||
G: Parser<Input, O2, Error>,
|
||||
Error: ParseError<Input>,
|
||||
{
|
||||
use crate::traits::AsChar;
|
||||
|
||||
move |input: Input| {
|
||||
let mut i = input.clone();
|
||||
|
||||
while i.input_len() > 0 {
|
||||
let current_len = i.input_len();
|
||||
|
||||
match normal.parse(i.clone()) {
|
||||
Ok((i2, _)) => {
|
||||
// return if we consumed everything or if the normal parser
|
||||
// does not consume anything
|
||||
if i2.input_len() == 0 {
|
||||
return Ok((input.slice(input.input_len()..), input));
|
||||
} else if i2.input_len() == current_len {
|
||||
let index = input.offset(&i2);
|
||||
return Ok(input.take_split(index));
|
||||
} else {
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
Err(Err::Error(_)) => {
|
||||
// unwrap() should be safe here since index < $i.input_len()
|
||||
if i.iter_elements().next().unwrap().as_char() == control_char {
|
||||
let next = control_char.len_utf8();
|
||||
if next >= i.input_len() {
|
||||
return Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::Escaped,
|
||||
)));
|
||||
} else {
|
||||
match escapable.parse(i.slice(next..)) {
|
||||
Ok((i2, _)) => {
|
||||
if i2.input_len() == 0 {
|
||||
return Ok((input.slice(input.input_len()..), input));
|
||||
} else {
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let index = input.offset(&i);
|
||||
if index == 0 {
|
||||
return Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::Escaped,
|
||||
)));
|
||||
}
|
||||
return Ok(input.take_split(index));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok((input.slice(input.input_len()..), input))
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a byte string with escaped characters.
|
||||
///
|
||||
/// * The first argument matches the normal characters (it must not match the control character)
|
||||
/// * The second argument is the control character (like `\` in most languages)
|
||||
/// * The third argument matches the escaped characters and transforms them
|
||||
///
|
||||
/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// # use std::str::from_utf8;
|
||||
/// use nom::bytes::complete::{escaped_transform, tag};
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// use nom::branch::alt;
|
||||
/// use nom::combinator::value;
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, String> {
|
||||
/// escaped_transform(
|
||||
/// alpha1,
|
||||
/// '\\',
|
||||
/// alt((
|
||||
/// value("\\", tag("\\")),
|
||||
/// value("\"", tag("\"")),
|
||||
/// value("\n", tag("n")),
|
||||
/// ))
|
||||
/// )(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd"))));
|
||||
/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd"))));
|
||||
/// ```
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
|
||||
mut normal: F,
|
||||
control_char: char,
|
||||
mut transform: G,
|
||||
) -> impl FnMut(Input) -> IResult<Input, Output, Error>
|
||||
where
|
||||
Input: Clone
|
||||
+ crate::traits::Offset
|
||||
+ InputLength
|
||||
+ InputTake
|
||||
+ InputTakeAtPosition
|
||||
+ Slice<RangeFrom<usize>>
|
||||
+ InputIter,
|
||||
Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
<Input as InputIter>::Item: crate::traits::AsChar,
|
||||
F: Parser<Input, O1, Error>,
|
||||
G: Parser<Input, O2, Error>,
|
||||
Error: ParseError<Input>,
|
||||
{
|
||||
use crate::traits::AsChar;
|
||||
|
||||
move |input: Input| {
|
||||
let mut index = 0;
|
||||
let mut res = input.new_builder();
|
||||
|
||||
let i = input.clone();
|
||||
|
||||
while index < i.input_len() {
|
||||
let current_len = i.input_len();
|
||||
let remainder = i.slice(index..);
|
||||
match normal.parse(remainder.clone()) {
|
||||
Ok((i2, o)) => {
|
||||
o.extend_into(&mut res);
|
||||
if i2.input_len() == 0 {
|
||||
return Ok((i.slice(i.input_len()..), res));
|
||||
} else if i2.input_len() == current_len {
|
||||
return Ok((remainder, res));
|
||||
} else {
|
||||
index = input.offset(&i2);
|
||||
}
|
||||
}
|
||||
Err(Err::Error(_)) => {
|
||||
// unwrap() should be safe here since index < $i.input_len()
|
||||
if remainder.iter_elements().next().unwrap().as_char() == control_char {
|
||||
let next = index + control_char.len_utf8();
|
||||
let input_len = input.input_len();
|
||||
|
||||
if next >= input_len {
|
||||
return Err(Err::Error(Error::from_error_kind(
|
||||
remainder,
|
||||
ErrorKind::EscapedTransform,
|
||||
)));
|
||||
} else {
|
||||
match transform.parse(i.slice(next..)) {
|
||||
Ok((i2, o)) => {
|
||||
o.extend_into(&mut res);
|
||||
if i2.input_len() == 0 {
|
||||
return Ok((i.slice(i.input_len()..), res));
|
||||
} else {
|
||||
index = input.offset(&i2);
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if index == 0 {
|
||||
return Err(Err::Error(Error::from_error_kind(
|
||||
remainder,
|
||||
ErrorKind::EscapedTransform,
|
||||
)));
|
||||
}
|
||||
return Ok((remainder, res));
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Ok((input.slice(index..), res))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn complete_take_while_m_n_utf8_all_matching() {
|
||||
let result: IResult<&str, &str> =
|
||||
super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn");
|
||||
assert_eq!(result, Ok(("", "øn")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn complete_take_while_m_n_utf8_all_matching_substring() {
|
||||
let result: IResult<&str, &str> =
|
||||
super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn");
|
||||
assert_eq!(result, Ok(("n", "ø")));
|
||||
}
|
||||
|
||||
// issue #1336 "escaped hangs if normal parser accepts empty"
|
||||
fn escaped_string(input: &str) -> IResult<&str, &str> {
|
||||
use crate::character::complete::{alpha0, one_of};
|
||||
escaped(alpha0, '\\', one_of("n"))(input)
|
||||
}
|
||||
|
||||
// issue #1336 "escaped hangs if normal parser accepts empty"
|
||||
#[test]
|
||||
fn escaped_hang() {
|
||||
escaped_string("7").unwrap();
|
||||
escaped_string("a7").unwrap();
|
||||
}
|
||||
|
||||
// issue ##1118 escaped does not work with empty string
|
||||
fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> {
|
||||
use crate::bytes::complete::*;
|
||||
use crate::character::complete::*;
|
||||
use crate::combinator::opt;
|
||||
use crate::sequence::delimited;
|
||||
|
||||
delimited(
|
||||
char('"'),
|
||||
escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
|
||||
char('"'),
|
||||
)(input)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn escaped_hang_1118() {
|
||||
assert_eq!(unquote(r#""""#), Ok(("", "")));
|
||||
}
|
||||
}
|
||||
6
third-party/vendor/nom/src/bytes/mod.rs
vendored
Normal file
6
third-party/vendor/nom/src/bytes/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
//! Parsers recognizing bytes streams
|
||||
|
||||
pub mod complete;
|
||||
pub mod streaming;
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
700
third-party/vendor/nom/src/bytes/streaming.rs
vendored
Normal file
700
third-party/vendor/nom/src/bytes/streaming.rs
vendored
Normal file
|
|
@ -0,0 +1,700 @@
|
|||
//! Parsers recognizing bytes streams, streaming version
|
||||
|
||||
use crate::error::ErrorKind;
|
||||
use crate::error::ParseError;
|
||||
use crate::internal::{Err, IResult, Needed, Parser};
|
||||
use crate::lib::std::ops::RangeFrom;
|
||||
use crate::lib::std::result::Result::*;
|
||||
use crate::traits::{
|
||||
Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake,
|
||||
InputTakeAtPosition, Slice, ToUsize,
|
||||
};
|
||||
|
||||
/// Recognizes a pattern.
|
||||
///
|
||||
/// The input data will be compared to the tag combinator's argument and will return the part of
|
||||
/// the input that matches the argument.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::tag;
|
||||
///
|
||||
/// fn parser(s: &str) -> IResult<&str, &str> {
|
||||
/// tag("Hello")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
|
||||
/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4))));
|
||||
/// ```
|
||||
pub fn tag<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputLength + Compare<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let tag_len = tag.input_len();
|
||||
let t = tag.clone();
|
||||
|
||||
let res: IResult<_, _, Error> = match i.compare(t) {
|
||||
CompareResult::Ok => Ok(i.take_split(tag_len)),
|
||||
CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))),
|
||||
CompareResult::Error => {
|
||||
let e: ErrorKind = ErrorKind::Tag;
|
||||
Err(Err::Error(Error::from_error_kind(i, e)))
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Recognizes a case insensitive pattern.
|
||||
///
|
||||
/// The input data will be compared to the tag combinator's argument and will return the part of
|
||||
/// the input that matches the argument with no regard to case.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::tag_no_case;
|
||||
///
|
||||
/// fn parser(s: &str) -> IResult<&str, &str> {
|
||||
/// tag_no_case("hello")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
|
||||
/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
|
||||
/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
|
||||
/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5))));
|
||||
/// ```
|
||||
pub fn tag_no_case<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputLength + Compare<T>,
|
||||
T: InputLength + Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let tag_len = tag.input_len();
|
||||
let t = tag.clone();
|
||||
|
||||
let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
|
||||
CompareResult::Ok => Ok(i.take_split(tag_len)),
|
||||
CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))),
|
||||
CompareResult::Error => {
|
||||
let e: ErrorKind = ErrorKind::Tag;
|
||||
Err(Err::Error(Error::from_error_kind(i, e)))
|
||||
}
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Parse till certain characters are met.
|
||||
///
|
||||
/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
|
||||
///
|
||||
/// It doesn't consume the matched character.
|
||||
///
|
||||
/// It will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::is_not;
|
||||
///
|
||||
/// fn not_space(s: &str) -> IResult<&str, &str> {
|
||||
/// is_not(" \t\r\n")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
|
||||
/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
|
||||
/// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// ```
|
||||
pub fn is_not<T, Input, Error: ParseError<Input>>(
|
||||
arr: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
T: FindToken<<Input as InputTakeAtPosition>::Item>,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::IsNot;
|
||||
i.split_at_position1(|c| arr.find_token(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest slice of the matches the pattern.
|
||||
///
|
||||
/// The parser will return the longest slice consisting of the characters in provided in the
|
||||
/// combinator's argument.
|
||||
///
|
||||
/// # Streaming specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met
|
||||
/// or if the pattern reaches the end of the input.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::is_a;
|
||||
///
|
||||
/// fn hex(s: &str) -> IResult<&str, &str> {
|
||||
/// is_a("1234567890ABCDEF")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
|
||||
/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
|
||||
/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
|
||||
/// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(hex(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// ```
|
||||
pub fn is_a<T, Input, Error: ParseError<Input>>(
|
||||
arr: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
T: FindToken<<Input as InputTakeAtPosition>::Item>,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::IsA;
|
||||
i.split_at_position1(|c| !arr.find_token(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest input slice (if any) that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_while;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while(is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
|
||||
/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// ```
|
||||
pub fn take_while<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| i.split_at_position(|c| !cond(c))
|
||||
}
|
||||
|
||||
/// Returns the longest (at least 1) input slice that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_while1;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while1(is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
|
||||
/// ```
|
||||
pub fn take_while1<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::TakeWhile1;
|
||||
i.split_at_position1(|c| !cond(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest (m <= len <= n) input slice that matches the predicate.
|
||||
///
|
||||
/// The parser will return the longest slice that matches the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met.
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_while_m_n;
|
||||
/// use nom::character::is_alphabetic;
|
||||
///
|
||||
/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// take_while_m_n(3, 6, is_alphabetic)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
|
||||
/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
|
||||
/// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
|
||||
/// ```
|
||||
pub fn take_while_m_n<F, Input, Error: ParseError<Input>>(
|
||||
m: usize,
|
||||
n: usize,
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputIter + InputLength,
|
||||
F: Fn(<Input as InputIter>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let input = i;
|
||||
|
||||
match input.position(|c| !cond(c)) {
|
||||
Some(idx) => {
|
||||
if idx >= m {
|
||||
if idx <= n {
|
||||
let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) {
|
||||
Ok(input.take_split(index))
|
||||
} else {
|
||||
Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
)))
|
||||
};
|
||||
res
|
||||
} else {
|
||||
let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) {
|
||||
Ok(input.take_split(index))
|
||||
} else {
|
||||
Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
)))
|
||||
};
|
||||
res
|
||||
}
|
||||
} else {
|
||||
let e = ErrorKind::TakeWhileMN;
|
||||
Err(Err::Error(Error::from_error_kind(input, e)))
|
||||
}
|
||||
}
|
||||
None => {
|
||||
let len = input.input_len();
|
||||
if len >= n {
|
||||
match input.slice_index(n) {
|
||||
Ok(index) => Ok(input.take_split(index)),
|
||||
Err(_needed) => Err(Err::Error(Error::from_error_kind(
|
||||
input,
|
||||
ErrorKind::TakeWhileMN,
|
||||
))),
|
||||
}
|
||||
} else {
|
||||
let needed = if m > len { m - len } else { 1 };
|
||||
Err(Err::Incomplete(Needed::new(needed)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the longest input slice (if any) till a predicate is met.
|
||||
///
|
||||
/// The parser will return the longest slice till the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
|
||||
/// end of input or if there was not match.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_till;
|
||||
///
|
||||
/// fn till_colon(s: &str) -> IResult<&str, &str> {
|
||||
/// take_till(|c| c == ':')(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
|
||||
/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
|
||||
/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// ```
|
||||
pub fn take_till<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| i.split_at_position(|c| cond(c))
|
||||
}
|
||||
|
||||
/// Returns the longest (at least 1) input slice till a predicate is met.
|
||||
///
|
||||
/// The parser will return the longest slice till the given predicate *(a function that
|
||||
/// takes the input and returns a bool)*.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
|
||||
/// end of input or if there was not match.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_till1;
|
||||
///
|
||||
/// fn till_colon(s: &str) -> IResult<&str, &str> {
|
||||
/// take_till1(|c| c == ':')(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
|
||||
/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
|
||||
/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
/// ```
|
||||
pub fn take_till1<F, Input, Error: ParseError<Input>>(
|
||||
cond: F,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTakeAtPosition,
|
||||
F: Fn(<Input as InputTakeAtPosition>::Item) -> bool,
|
||||
{
|
||||
move |i: Input| {
|
||||
let e: ErrorKind = ErrorKind::TakeTill1;
|
||||
i.split_at_position1(|c| cond(c), e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an input slice containing the first N input elements (Input[..N]).
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* if the input has less than N elements, `take` 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::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take;
|
||||
///
|
||||
/// fn take6(s: &str) -> IResult<&str, &str> {
|
||||
/// take(6usize)(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
|
||||
/// assert_eq!(take6("things"), Ok(("", "things")));
|
||||
/// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
/// ```
|
||||
pub fn take<C, Input, Error: ParseError<Input>>(
|
||||
count: C,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputIter + InputTake + InputLength,
|
||||
C: ToUsize,
|
||||
{
|
||||
let c = count.to_usize();
|
||||
move |i: Input| match i.slice_index(c) {
|
||||
Err(i) => Err(Err::Incomplete(i)),
|
||||
Ok(index) => Ok(i.take_split(index)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the input slice up to the first occurrence of the pattern.
|
||||
///
|
||||
/// It doesn't consume the pattern.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
|
||||
/// contain the pattern or if the input is smaller than the pattern.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_until;
|
||||
///
|
||||
/// fn until_eof(s: &str) -> IResult<&str, &str> {
|
||||
/// take_until("eof")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
|
||||
/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
|
||||
/// ```
|
||||
pub fn take_until<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputLength + FindSubstring<T>,
|
||||
T: Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let t = tag.clone();
|
||||
|
||||
let res: IResult<_, _, Error> = match i.find_substring(t) {
|
||||
None => Err(Err::Incomplete(Needed::Unknown)),
|
||||
Some(index) => Ok(i.take_split(index)),
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the non empty input slice up to the first occurrence of the pattern.
|
||||
///
|
||||
/// It doesn't consume the pattern.
|
||||
///
|
||||
/// # Streaming Specific
|
||||
/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
|
||||
/// contain the pattern or if the input is smaller than the pattern.
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
|
||||
/// use nom::bytes::streaming::take_until1;
|
||||
///
|
||||
/// fn until_eof(s: &str) -> IResult<&str, &str> {
|
||||
/// take_until1("eof")(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
|
||||
/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
|
||||
/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
|
||||
/// ```
|
||||
pub fn take_until1<T, Input, Error: ParseError<Input>>(
|
||||
tag: T,
|
||||
) -> impl Fn(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: InputTake + InputLength + FindSubstring<T>,
|
||||
T: Clone,
|
||||
{
|
||||
move |i: Input| {
|
||||
let t = tag.clone();
|
||||
|
||||
let res: IResult<_, _, Error> = match i.find_substring(t) {
|
||||
None => Err(Err::Incomplete(Needed::Unknown)),
|
||||
Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
|
||||
Some(index) => Ok(i.take_split(index)),
|
||||
};
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a byte string with escaped characters.
|
||||
///
|
||||
/// * The first argument matches the normal characters (it must not accept the control character)
|
||||
/// * The second argument is the control character (like `\` in most languages)
|
||||
/// * The third argument matches the escaped characters
|
||||
/// # Example
|
||||
/// ```
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// # use nom::character::complete::digit1;
|
||||
/// use nom::bytes::streaming::escaped;
|
||||
/// use nom::character::streaming::one_of;
|
||||
///
|
||||
/// fn esc(s: &str) -> IResult<&str, &str> {
|
||||
/// escaped(digit1, '\\', one_of("\"n\\"))(s)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(esc("123;"), Ok((";", "123")));
|
||||
/// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34")));
|
||||
/// ```
|
||||
///
|
||||
pub fn escaped<Input, Error, F, G, O1, O2>(
|
||||
mut normal: F,
|
||||
control_char: char,
|
||||
mut escapable: G,
|
||||
) -> impl FnMut(Input) -> IResult<Input, Input, Error>
|
||||
where
|
||||
Input: Clone
|
||||
+ crate::traits::Offset
|
||||
+ InputLength
|
||||
+ InputTake
|
||||
+ InputTakeAtPosition
|
||||
+ Slice<RangeFrom<usize>>
|
||||
+ InputIter,
|
||||
<Input as InputIter>::Item: crate::traits::AsChar,
|
||||
F: Parser<Input, O1, Error>,
|
||||
G: Parser<Input, O2, Error>,
|
||||
Error: ParseError<Input>,
|
||||
{
|
||||
use crate::traits::AsChar;
|
||||
|
||||
move |input: Input| {
|
||||
let mut i = input.clone();
|
||||
|
||||
while i.input_len() > 0 {
|
||||
let current_len = i.input_len();
|
||||
|
||||
match normal.parse(i.clone()) {
|
||||
Ok((i2, _)) => {
|
||||
if i2.input_len() == 0 {
|
||||
return Err(Err::Incomplete(Needed::Unknown));
|
||||
} else if i2.input_len() == current_len {
|
||||
let index = input.offset(&i2);
|
||||
return Ok(input.take_split(index));
|
||||
} else {
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
Err(Err::Error(_)) => {
|
||||
// unwrap() should be safe here since index < $i.input_len()
|
||||
if i.iter_elements().next().unwrap().as_char() == control_char {
|
||||
let next = control_char.len_utf8();
|
||||
if next >= i.input_len() {
|
||||
return Err(Err::Incomplete(Needed::new(1)));
|
||||
} else {
|
||||
match escapable.parse(i.slice(next..)) {
|
||||
Ok((i2, _)) => {
|
||||
if i2.input_len() == 0 {
|
||||
return Err(Err::Incomplete(Needed::Unknown));
|
||||
} else {
|
||||
i = i2;
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let index = input.offset(&i);
|
||||
return Ok(input.take_split(index));
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(Err::Incomplete(Needed::Unknown))
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a byte string with escaped characters.
|
||||
///
|
||||
/// * The first argument matches the normal characters (it must not match the control character)
|
||||
/// * The second argument is the control character (like `\` in most languages)
|
||||
/// * The third argument matches the escaped characters and transforms them
|
||||
///
|
||||
/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::{Err, error::ErrorKind, Needed, IResult};
|
||||
/// # use std::str::from_utf8;
|
||||
/// use nom::bytes::streaming::{escaped_transform, tag};
|
||||
/// use nom::character::streaming::alpha1;
|
||||
/// use nom::branch::alt;
|
||||
/// use nom::combinator::value;
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, String> {
|
||||
/// escaped_transform(
|
||||
/// alpha1,
|
||||
/// '\\',
|
||||
/// alt((
|
||||
/// value("\\", tag("\\")),
|
||||
/// value("\"", tag("\"")),
|
||||
/// value("\n", tag("n")),
|
||||
/// ))
|
||||
/// )(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd"))));
|
||||
/// ```
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
|
||||
mut normal: F,
|
||||
control_char: char,
|
||||
mut transform: G,
|
||||
) -> impl FnMut(Input) -> IResult<Input, Output, Error>
|
||||
where
|
||||
Input: Clone
|
||||
+ crate::traits::Offset
|
||||
+ InputLength
|
||||
+ InputTake
|
||||
+ InputTakeAtPosition
|
||||
+ Slice<RangeFrom<usize>>
|
||||
+ InputIter,
|
||||
Input: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
|
||||
<Input as InputIter>::Item: crate::traits::AsChar,
|
||||
F: Parser<Input, O1, Error>,
|
||||
G: Parser<Input, O2, Error>,
|
||||
Error: ParseError<Input>,
|
||||
{
|
||||
use crate::traits::AsChar;
|
||||
|
||||
move |input: Input| {
|
||||
let mut index = 0;
|
||||
let mut res = input.new_builder();
|
||||
|
||||
let i = input.clone();
|
||||
|
||||
while index < i.input_len() {
|
||||
let current_len = i.input_len();
|
||||
let remainder = i.slice(index..);
|
||||
match normal.parse(remainder.clone()) {
|
||||
Ok((i2, o)) => {
|
||||
o.extend_into(&mut res);
|
||||
if i2.input_len() == 0 {
|
||||
return Err(Err::Incomplete(Needed::Unknown));
|
||||
} else if i2.input_len() == current_len {
|
||||
return Ok((remainder, res));
|
||||
} else {
|
||||
index = input.offset(&i2);
|
||||
}
|
||||
}
|
||||
Err(Err::Error(_)) => {
|
||||
// unwrap() should be safe here since index < $i.input_len()
|
||||
if remainder.iter_elements().next().unwrap().as_char() == control_char {
|
||||
let next = index + control_char.len_utf8();
|
||||
let input_len = input.input_len();
|
||||
|
||||
if next >= input_len {
|
||||
return Err(Err::Incomplete(Needed::Unknown));
|
||||
} else {
|
||||
match transform.parse(i.slice(next..)) {
|
||||
Ok((i2, o)) => {
|
||||
o.extend_into(&mut res);
|
||||
if i2.input_len() == 0 {
|
||||
return Err(Err::Incomplete(Needed::Unknown));
|
||||
} else {
|
||||
index = input.offset(&i2);
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return Ok((remainder, res));
|
||||
}
|
||||
}
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
Err(Err::Incomplete(Needed::Unknown))
|
||||
}
|
||||
}
|
||||
636
third-party/vendor/nom/src/bytes/tests.rs
vendored
Normal file
636
third-party/vendor/nom/src/bytes/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,636 @@
|
|||
use crate::character::is_alphabetic;
|
||||
use crate::character::streaming::{
|
||||
alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
|
||||
multispace1 as multispace, oct_digit1 as oct_digit, space1 as space,
|
||||
};
|
||||
use crate::error::ErrorKind;
|
||||
use crate::internal::{Err, IResult, Needed};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::{
|
||||
branch::alt,
|
||||
bytes::complete::{escaped, escaped_transform, tag},
|
||||
combinator::{map, value},
|
||||
lib::std::string::String,
|
||||
lib::std::vec::Vec,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn is_a() {
|
||||
use crate::bytes::streaming::is_a;
|
||||
|
||||
fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
is_a("ab")(i)
|
||||
}
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..])));
|
||||
|
||||
let b = &b"bcde"[..];
|
||||
assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..])));
|
||||
|
||||
let c = &b"cdef"[..];
|
||||
assert_eq!(
|
||||
a_or_b(c),
|
||||
Err(Err::Error(error_position!(c, ErrorKind::IsA)))
|
||||
);
|
||||
|
||||
let d = &b"bacdef"[..];
|
||||
assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_not() {
|
||||
use crate::bytes::streaming::is_not;
|
||||
|
||||
fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
is_not("ab")(i)
|
||||
}
|
||||
|
||||
let a = &b"cdab"[..];
|
||||
assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..])));
|
||||
|
||||
let b = &b"cbde"[..];
|
||||
assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..])));
|
||||
|
||||
let c = &b"abab"[..];
|
||||
assert_eq!(
|
||||
a_or_b(c),
|
||||
Err(Err::Error(error_position!(c, ErrorKind::IsNot)))
|
||||
);
|
||||
|
||||
let d = &b"cdefba"[..];
|
||||
assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..])));
|
||||
|
||||
let e = &b"e"[..];
|
||||
assert_eq!(a_or_b(e), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[allow(unused_variables)]
|
||||
#[test]
|
||||
fn escaping() {
|
||||
use crate::character::streaming::one_of;
|
||||
|
||||
fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
escaped(alpha, '\\', one_of("\"n\\"))(i)
|
||||
}
|
||||
assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
|
||||
assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
|
||||
assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
|
||||
assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
|
||||
assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
|
||||
assert_eq!(
|
||||
esc(&b"AB\\"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"AB\\"[..],
|
||||
ErrorKind::Escaped
|
||||
)))
|
||||
);
|
||||
assert_eq!(
|
||||
esc(&b"AB\\A"[..]),
|
||||
Err(Err::Error(error_node_position!(
|
||||
&b"AB\\A"[..],
|
||||
ErrorKind::Escaped,
|
||||
error_position!(&b"A"[..], ErrorKind::OneOf)
|
||||
)))
|
||||
);
|
||||
|
||||
fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
escaped(digit, '\\', one_of("\"n\\"))(i)
|
||||
}
|
||||
assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn escaping_str() {
|
||||
use crate::character::streaming::one_of;
|
||||
|
||||
fn esc(i: &str) -> IResult<&str, &str> {
|
||||
escaped(alpha, '\\', one_of("\"n\\"))(i)
|
||||
}
|
||||
assert_eq!(esc("abcd;"), Ok((";", "abcd")));
|
||||
assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
|
||||
assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
|
||||
assert_eq!(esc("\\n;"), Ok((";", "\\n")));
|
||||
assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
|
||||
assert_eq!(
|
||||
esc("AB\\"),
|
||||
Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped)))
|
||||
);
|
||||
assert_eq!(
|
||||
esc("AB\\A"),
|
||||
Err(Err::Error(error_node_position!(
|
||||
"AB\\A",
|
||||
ErrorKind::Escaped,
|
||||
error_position!("A", ErrorKind::OneOf)
|
||||
)))
|
||||
);
|
||||
|
||||
fn esc2(i: &str) -> IResult<&str, &str> {
|
||||
escaped(digit, '\\', one_of("\"n\\"))(i)
|
||||
}
|
||||
assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));
|
||||
|
||||
fn esc3(i: &str) -> IResult<&str, &str> {
|
||||
escaped(alpha, '\u{241b}', one_of("\"n"))(i)
|
||||
}
|
||||
assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
fn to_s(i: Vec<u8>) -> String {
|
||||
String::from_utf8_lossy(&i).into_owned()
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn escape_transform() {
|
||||
fn esc(i: &[u8]) -> IResult<&[u8], String> {
|
||||
map(
|
||||
escaped_transform(
|
||||
alpha,
|
||||
'\\',
|
||||
alt((
|
||||
value(&b"\\"[..], tag("\\")),
|
||||
value(&b"\""[..], tag("\"")),
|
||||
value(&b"\n"[..], tag("n")),
|
||||
)),
|
||||
),
|
||||
to_s,
|
||||
)(i)
|
||||
}
|
||||
|
||||
assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
|
||||
assert_eq!(
|
||||
esc(&b"ab\\\"cd;"[..]),
|
||||
Ok((&b";"[..], String::from("ab\"cd")))
|
||||
);
|
||||
assert_eq!(
|
||||
esc(&b"\\\"abcd;"[..]),
|
||||
Ok((&b";"[..], String::from("\"abcd")))
|
||||
);
|
||||
assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
|
||||
assert_eq!(
|
||||
esc(&b"ab\\\"12"[..]),
|
||||
Ok((&b"12"[..], String::from("ab\"")))
|
||||
);
|
||||
assert_eq!(
|
||||
esc(&b"AB\\"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"\\"[..],
|
||||
ErrorKind::EscapedTransform
|
||||
)))
|
||||
);
|
||||
assert_eq!(
|
||||
esc(&b"AB\\A"[..]),
|
||||
Err(Err::Error(error_node_position!(
|
||||
&b"AB\\A"[..],
|
||||
ErrorKind::EscapedTransform,
|
||||
error_position!(&b"A"[..], ErrorKind::Tag)
|
||||
)))
|
||||
);
|
||||
|
||||
fn esc2(i: &[u8]) -> IResult<&[u8], String> {
|
||||
map(
|
||||
escaped_transform(
|
||||
alpha,
|
||||
'&',
|
||||
alt((
|
||||
value("è".as_bytes(), tag("egrave;")),
|
||||
value("à".as_bytes(), tag("agrave;")),
|
||||
)),
|
||||
),
|
||||
to_s,
|
||||
)(i)
|
||||
}
|
||||
assert_eq!(
|
||||
esc2(&b"abèDEF;"[..]),
|
||||
Ok((&b";"[..], String::from("abèDEF")))
|
||||
);
|
||||
assert_eq!(
|
||||
esc2(&b"abèDàEF;"[..]),
|
||||
Ok((&b";"[..], String::from("abèDàEF")))
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn escape_transform_str() {
|
||||
fn esc(i: &str) -> IResult<&str, String> {
|
||||
escaped_transform(
|
||||
alpha,
|
||||
'\\',
|
||||
alt((
|
||||
value("\\", tag("\\")),
|
||||
value("\"", tag("\"")),
|
||||
value("\n", tag("n")),
|
||||
)),
|
||||
)(i)
|
||||
}
|
||||
|
||||
assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
|
||||
assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
|
||||
assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
|
||||
assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
|
||||
assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
|
||||
assert_eq!(
|
||||
esc("AB\\"),
|
||||
Err(Err::Error(error_position!(
|
||||
"\\",
|
||||
ErrorKind::EscapedTransform
|
||||
)))
|
||||
);
|
||||
assert_eq!(
|
||||
esc("AB\\A"),
|
||||
Err(Err::Error(error_node_position!(
|
||||
"AB\\A",
|
||||
ErrorKind::EscapedTransform,
|
||||
error_position!("A", ErrorKind::Tag)
|
||||
)))
|
||||
);
|
||||
|
||||
fn esc2(i: &str) -> IResult<&str, String> {
|
||||
escaped_transform(
|
||||
alpha,
|
||||
'&',
|
||||
alt((value("è", tag("egrave;")), value("à", tag("agrave;")))),
|
||||
)(i)
|
||||
}
|
||||
assert_eq!(esc2("abèDEF;"), Ok((";", String::from("abèDEF"))));
|
||||
assert_eq!(
|
||||
esc2("abèDàEF;"),
|
||||
Ok((";", String::from("abèDàEF")))
|
||||
);
|
||||
|
||||
fn esc3(i: &str) -> IResult<&str, String> {
|
||||
escaped_transform(
|
||||
alpha,
|
||||
'␛',
|
||||
alt((value("\0", tag("0")), value("\n", tag("n")))),
|
||||
)(i)
|
||||
}
|
||||
assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_until_incomplete() {
|
||||
use crate::bytes::streaming::take_until;
|
||||
fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_until("end")(i)
|
||||
}
|
||||
assert_eq!(y(&b"nd"[..]), Err(Err::Incomplete(Needed::Unknown)));
|
||||
assert_eq!(y(&b"123"[..]), Err(Err::Incomplete(Needed::Unknown)));
|
||||
assert_eq!(y(&b"123en"[..]), Err(Err::Incomplete(Needed::Unknown)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_until_incomplete_s() {
|
||||
use crate::bytes::streaming::take_until;
|
||||
fn ys(i: &str) -> IResult<&str, &str> {
|
||||
take_until("end")(i)
|
||||
}
|
||||
assert_eq!(ys("123en"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn recognize() {
|
||||
use crate::bytes::streaming::{tag, take};
|
||||
use crate::combinator::recognize;
|
||||
use crate::sequence::delimited;
|
||||
|
||||
fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(delimited(tag("<!--"), take(5_usize), tag("-->")))(i)
|
||||
}
|
||||
let r = x(&b"<!-- abc --> aaa"[..]);
|
||||
assert_eq!(r, Ok((&b" aaa"[..], &b"<!-- abc -->"[..])));
|
||||
|
||||
let semicolon = &b";"[..];
|
||||
|
||||
fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(alpha)(i)
|
||||
}
|
||||
let ra = ya(&b"abc;"[..]);
|
||||
assert_eq!(ra, Ok((semicolon, &b"abc"[..])));
|
||||
|
||||
fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(digit)(i)
|
||||
}
|
||||
let rd = yd(&b"123;"[..]);
|
||||
assert_eq!(rd, Ok((semicolon, &b"123"[..])));
|
||||
|
||||
fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(hex_digit)(i)
|
||||
}
|
||||
let rhd = yhd(&b"123abcDEF;"[..]);
|
||||
assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..])));
|
||||
|
||||
fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(oct_digit)(i)
|
||||
}
|
||||
let rod = yod(&b"1234567;"[..]);
|
||||
assert_eq!(rod, Ok((semicolon, &b"1234567"[..])));
|
||||
|
||||
fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(alphanumeric)(i)
|
||||
}
|
||||
let ran = yan(&b"123abc;"[..]);
|
||||
assert_eq!(ran, Ok((semicolon, &b"123abc"[..])));
|
||||
|
||||
fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(space)(i)
|
||||
}
|
||||
let rs = ys(&b" \t;"[..]);
|
||||
assert_eq!(rs, Ok((semicolon, &b" \t"[..])));
|
||||
|
||||
fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(multispace)(i)
|
||||
}
|
||||
let rms = yms(&b" \t\r\n;"[..]);
|
||||
assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while() {
|
||||
use crate::bytes::streaming::take_while;
|
||||
|
||||
fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_while(is_alphabetic)(i)
|
||||
}
|
||||
let a = b"";
|
||||
let b = b"abcd";
|
||||
let c = b"abcd123";
|
||||
let d = b"123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&c[..]), Ok((&d[..], &b[..])));
|
||||
assert_eq!(f(&d[..]), Ok((&d[..], &a[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while1() {
|
||||
use crate::bytes::streaming::take_while1;
|
||||
|
||||
fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_while1(is_alphabetic)(i)
|
||||
}
|
||||
let a = b"";
|
||||
let b = b"abcd";
|
||||
let c = b"abcd123";
|
||||
let d = b"123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..])));
|
||||
assert_eq!(
|
||||
f(&d[..]),
|
||||
Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_m_n() {
|
||||
use crate::bytes::streaming::take_while_m_n;
|
||||
|
||||
fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_while_m_n(2, 4, is_alphabetic)(i)
|
||||
}
|
||||
let a = b"";
|
||||
let b = b"a";
|
||||
let c = b"abc";
|
||||
let d = b"abc123";
|
||||
let e = b"abcde";
|
||||
let f = b"123";
|
||||
|
||||
assert_eq!(x(&a[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(x(&b[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(x(&c[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..])));
|
||||
assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..])));
|
||||
assert_eq!(
|
||||
x(&f[..]),
|
||||
Err(Err::Error(error_position!(&f[..], ErrorKind::TakeWhileMN)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_till() {
|
||||
use crate::bytes::streaming::take_till;
|
||||
|
||||
fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_till(is_alphabetic)(i)
|
||||
}
|
||||
let a = b"";
|
||||
let b = b"abcd";
|
||||
let c = b"123abcd";
|
||||
let d = b"123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..])));
|
||||
assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
|
||||
assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_till1() {
|
||||
use crate::bytes::streaming::take_till1;
|
||||
|
||||
fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_till1(is_alphabetic)(i)
|
||||
}
|
||||
let a = b"";
|
||||
let b = b"abcd";
|
||||
let c = b"123abcd";
|
||||
let d = b"123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(
|
||||
f(&b[..]),
|
||||
Err(Err::Error(error_position!(&b[..], ErrorKind::TakeTill1)))
|
||||
);
|
||||
assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
|
||||
assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_utf8() {
|
||||
use crate::bytes::streaming::take_while;
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
take_while(|c| c != '點')(i)
|
||||
}
|
||||
|
||||
assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f("abcd點"), Ok(("點", "abcd")));
|
||||
assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));
|
||||
|
||||
fn g(i: &str) -> IResult<&str, &str> {
|
||||
take_while(|c| c == '點')(i)
|
||||
}
|
||||
|
||||
assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(g("點abcd"), Ok(("abcd", "點")));
|
||||
assert_eq!(g("點點點a"), Ok(("a", "點點點")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_till_utf8() {
|
||||
use crate::bytes::streaming::take_till;
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
take_till(|c| c == '點')(i)
|
||||
}
|
||||
|
||||
assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f("abcd點"), Ok(("點", "abcd")));
|
||||
assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));
|
||||
|
||||
fn g(i: &str) -> IResult<&str, &str> {
|
||||
take_till(|c| c != '點')(i)
|
||||
}
|
||||
|
||||
assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(g("點abcd"), Ok(("abcd", "點")));
|
||||
assert_eq!(g("點點點a"), Ok(("a", "點點點")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_utf8() {
|
||||
use crate::bytes::streaming::{take, take_while};
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
take(3_usize)(i)
|
||||
}
|
||||
|
||||
assert_eq!(f(""), Err(Err::Incomplete(Needed::Unknown)));
|
||||
assert_eq!(f("ab"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
assert_eq!(f("點"), Err(Err::Incomplete(Needed::Unknown)));
|
||||
assert_eq!(f("ab點cd"), Ok(("cd", "ab點")));
|
||||
assert_eq!(f("a點bcd"), Ok(("cd", "a點b")));
|
||||
assert_eq!(f("a點b"), Ok(("", "a點b")));
|
||||
|
||||
fn g(i: &str) -> IResult<&str, &str> {
|
||||
take_while(|c| c == '點')(i)
|
||||
}
|
||||
|
||||
assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(g("點abcd"), Ok(("abcd", "點")));
|
||||
assert_eq!(g("點點點a"), Ok(("a", "點點點")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_m_n_utf8() {
|
||||
use crate::bytes::streaming::take_while_m_n;
|
||||
|
||||
fn parser(i: &str) -> IResult<&str, &str> {
|
||||
take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i)
|
||||
}
|
||||
assert_eq!(parser("A!"), Ok(("!", "A")));
|
||||
assert_eq!(parser("😃!"), Ok(("!", "😃")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_m_n_utf8_full_match() {
|
||||
use crate::bytes::streaming::take_while_m_n;
|
||||
|
||||
fn parser(i: &str) -> IResult<&str, &str> {
|
||||
take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i)
|
||||
}
|
||||
assert_eq!(parser("øn"), Ok(("n", "ø")));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn recognize_take_while() {
|
||||
use crate::bytes::streaming::take_while;
|
||||
use crate::character::is_alphanumeric;
|
||||
use crate::combinator::recognize;
|
||||
|
||||
fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
take_while(is_alphanumeric)(i)
|
||||
}
|
||||
fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
recognize(x)(i)
|
||||
}
|
||||
assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
|
||||
println!("X: {:?}", x(&b"ab"[..]));
|
||||
assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn length_bytes() {
|
||||
use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8};
|
||||
|
||||
fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
length_data(le_u8)(i)
|
||||
}
|
||||
assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..])));
|
||||
assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..])));
|
||||
assert_eq!(x(b"\x02."), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(x(b"\x02"), Err(Err::Incomplete(Needed::new(2))));
|
||||
|
||||
fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
let (i, _) = tag("magic")(i)?;
|
||||
length_data(le_u8)(i)
|
||||
}
|
||||
assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..])));
|
||||
assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..])));
|
||||
assert_eq!(y(b"magic\x02."), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(y(b"magic\x02"), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn case_insensitive() {
|
||||
use crate::bytes::streaming::tag_no_case;
|
||||
|
||||
fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
tag_no_case("ABcd")(i)
|
||||
}
|
||||
assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..])));
|
||||
assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..])));
|
||||
assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..])));
|
||||
assert_eq!(test(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(
|
||||
test(&b"Hello"[..]),
|
||||
Err(Err::Error(error_position!(&b"Hello"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
test(&b"Hel"[..]),
|
||||
Err(Err::Error(error_position!(&b"Hel"[..], ErrorKind::Tag)))
|
||||
);
|
||||
|
||||
fn test2(i: &str) -> IResult<&str, &str> {
|
||||
tag_no_case("ABcd")(i)
|
||||
}
|
||||
assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd")));
|
||||
assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd")));
|
||||
assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD")));
|
||||
assert_eq!(test2("ab"), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(
|
||||
test2("Hello"),
|
||||
Err(Err::Error(error_position!(&"Hello"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
test2("Hel"),
|
||||
Err(Err::Error(error_position!(&"Hel"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tag_fixed_size_array() {
|
||||
use crate::bytes::streaming::tag;
|
||||
|
||||
fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
tag([0x42])(i)
|
||||
}
|
||||
fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
tag(&[0x42])(i)
|
||||
}
|
||||
let input = [0x42, 0x00];
|
||||
assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
|
||||
assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
|
||||
}
|
||||
1227
third-party/vendor/nom/src/character/complete.rs
vendored
Normal file
1227
third-party/vendor/nom/src/character/complete.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
116
third-party/vendor/nom/src/character/mod.rs
vendored
Normal file
116
third-party/vendor/nom/src/character/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
//! Character specific parsers and combinators
|
||||
//!
|
||||
//! Functions recognizing specific characters
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
pub mod complete;
|
||||
pub mod streaming;
|
||||
|
||||
/// Tests if byte is ASCII alphabetic: A-Z, a-z
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_alphabetic;
|
||||
/// assert_eq!(is_alphabetic(b'9'), false);
|
||||
/// assert_eq!(is_alphabetic(b'a'), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_alphabetic(chr: u8) -> bool {
|
||||
(chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A)
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII digit: 0-9
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_digit;
|
||||
/// assert_eq!(is_digit(b'a'), false);
|
||||
/// assert_eq!(is_digit(b'9'), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_digit(chr: u8) -> bool {
|
||||
chr >= 0x30 && chr <= 0x39
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII hex digit: 0-9, A-F, a-f
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_hex_digit;
|
||||
/// assert_eq!(is_hex_digit(b'a'), true);
|
||||
/// assert_eq!(is_hex_digit(b'9'), true);
|
||||
/// assert_eq!(is_hex_digit(b'A'), true);
|
||||
/// assert_eq!(is_hex_digit(b'x'), false);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_hex_digit(chr: u8) -> bool {
|
||||
(chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66)
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII octal digit: 0-7
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_oct_digit;
|
||||
/// assert_eq!(is_oct_digit(b'a'), false);
|
||||
/// assert_eq!(is_oct_digit(b'9'), false);
|
||||
/// assert_eq!(is_oct_digit(b'6'), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_oct_digit(chr: u8) -> bool {
|
||||
chr >= 0x30 && chr <= 0x37
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII alphanumeric: A-Z, a-z, 0-9
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_alphanumeric;
|
||||
/// assert_eq!(is_alphanumeric(b'-'), false);
|
||||
/// assert_eq!(is_alphanumeric(b'a'), true);
|
||||
/// assert_eq!(is_alphanumeric(b'9'), true);
|
||||
/// assert_eq!(is_alphanumeric(b'A'), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_alphanumeric(chr: u8) -> bool {
|
||||
is_alphabetic(chr) || is_digit(chr)
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII space or tab
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_space;
|
||||
/// assert_eq!(is_space(b'\n'), false);
|
||||
/// assert_eq!(is_space(b'\r'), false);
|
||||
/// assert_eq!(is_space(b' '), true);
|
||||
/// assert_eq!(is_space(b'\t'), true);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_space(chr: u8) -> bool {
|
||||
chr == b' ' || chr == b'\t'
|
||||
}
|
||||
|
||||
/// Tests if byte is ASCII newline: \n
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use nom::character::is_newline;
|
||||
/// assert_eq!(is_newline(b'\n'), true);
|
||||
/// assert_eq!(is_newline(b'\r'), false);
|
||||
/// assert_eq!(is_newline(b' '), false);
|
||||
/// assert_eq!(is_newline(b'\t'), false);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn is_newline(chr: u8) -> bool {
|
||||
chr == b'\n'
|
||||
}
|
||||
1182
third-party/vendor/nom/src/character/streaming.rs
vendored
Normal file
1182
third-party/vendor/nom/src/character/streaming.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
62
third-party/vendor/nom/src/character/tests.rs
vendored
Normal file
62
third-party/vendor/nom/src/character/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
use super::streaming::*;
|
||||
use crate::error::ErrorKind;
|
||||
use crate::internal::{Err, IResult};
|
||||
|
||||
#[test]
|
||||
fn one_of_test() {
|
||||
fn f(i: &[u8]) -> IResult<&[u8], char> {
|
||||
one_of("ab")(i)
|
||||
}
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));
|
||||
|
||||
fn utf8(i: &str) -> IResult<&str, char> {
|
||||
one_of("+\u{FF0B}")(i)
|
||||
}
|
||||
|
||||
assert!(utf8("+").is_ok());
|
||||
assert!(utf8("\u{FF0B}").is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn none_of_test() {
|
||||
fn f(i: &[u8]) -> IResult<&[u8], char> {
|
||||
none_of("ab")(i)
|
||||
}
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Ok((&b"de"[..], 'c')));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_byteslice() {
|
||||
fn f(i: &[u8]) -> IResult<&[u8], char> {
|
||||
char('c')(i)
|
||||
}
|
||||
|
||||
let a = &b"abcd"[..];
|
||||
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
|
||||
|
||||
let b = &b"cde"[..];
|
||||
assert_eq!(f(b), Ok((&b"de"[..], 'c')));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn char_str() {
|
||||
fn f(i: &str) -> IResult<&str, char> {
|
||||
char('c')(i)
|
||||
}
|
||||
|
||||
let a = &"abcd"[..];
|
||||
assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
|
||||
|
||||
let b = &"cde"[..];
|
||||
assert_eq!(f(b), Ok((&"de"[..], 'c')));
|
||||
}
|
||||
809
third-party/vendor/nom/src/combinator/mod.rs
vendored
Normal file
809
third-party/vendor/nom/src/combinator/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,809 @@
|
|||
//! General purpose combinators
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::lib::std::boxed::Box;
|
||||
|
||||
use crate::error::{ErrorKind, FromExternalError, ParseError};
|
||||
use crate::internal::*;
|
||||
use crate::lib::std::borrow::Borrow;
|
||||
use crate::lib::std::convert::Into;
|
||||
#[cfg(feature = "std")]
|
||||
use crate::lib::std::fmt::Debug;
|
||||
use crate::lib::std::mem::transmute;
|
||||
use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
|
||||
use crate::traits::{AsChar, InputIter, InputLength, InputTakeAtPosition, ParseTo};
|
||||
use crate::traits::{Compare, CompareResult, Offset, Slice};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Return the remaining input.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::error::ErrorKind;
|
||||
/// use nom::combinator::rest;
|
||||
/// assert_eq!(rest::<_,(_, ErrorKind)>("abc"), Ok(("", "abc")));
|
||||
/// assert_eq!(rest::<_,(_, ErrorKind)>(""), Ok(("", "")));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, T, E>
|
||||
where
|
||||
T: Slice<RangeFrom<usize>>,
|
||||
T: InputLength,
|
||||
{
|
||||
Ok((input.slice(input.input_len()..), input))
|
||||
}
|
||||
|
||||
/// Return the length of the remaining input.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::error::ErrorKind;
|
||||
/// use nom::combinator::rest_len;
|
||||
/// assert_eq!(rest_len::<_,(_, ErrorKind)>("abc"), Ok(("abc", 3)));
|
||||
/// assert_eq!(rest_len::<_,(_, ErrorKind)>(""), Ok(("", 0)));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
|
||||
where
|
||||
T: InputLength,
|
||||
{
|
||||
let len = input.input_len();
|
||||
Ok((input, len))
|
||||
}
|
||||
|
||||
/// Maps a function on the result of a parser.
|
||||
///
|
||||
/// ```rust
|
||||
/// use nom::{Err,error::ErrorKind, IResult,Parser};
|
||||
/// use nom::character::complete::digit1;
|
||||
/// use nom::combinator::map;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = map(digit1, |s: &str| s.len());
|
||||
///
|
||||
/// // the parser will count how many characters were returned by digit1
|
||||
/// assert_eq!(parser.parse("123456"), Ok(("", 6)));
|
||||
///
|
||||
/// // this will fail if digit1 fails
|
||||
/// assert_eq!(parser.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn map<I, O1, O2, E, F, G>(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: FnMut(O1) -> O2,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = parser.parse(input)?;
|
||||
Ok((input, f(o1)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a function returning a `Result` over the result of a parser.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::character::complete::digit1;
|
||||
/// use nom::combinator::map_res;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parse = map_res(digit1, |s: &str| s.parse::<u8>());
|
||||
///
|
||||
/// // the parser will convert the result of digit1 to a number
|
||||
/// assert_eq!(parse("123"), Ok(("", 123)));
|
||||
///
|
||||
/// // this will fail if digit1 fails
|
||||
/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
|
||||
///
|
||||
/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
|
||||
/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn map_res<I: Clone, O1, O2, E: FromExternalError<I, E2>, E2, F, G>(
|
||||
mut parser: F,
|
||||
mut f: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: FnMut(O1) -> Result<O2, E2>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
let (input, o1) = parser.parse(input)?;
|
||||
match f(o1) {
|
||||
Ok(o2) => Ok((input, o2)),
|
||||
Err(e) => Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, e))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a function returning an `Option` over the result of a parser.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::character::complete::digit1;
|
||||
/// use nom::combinator::map_opt;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parse = map_opt(digit1, |s: &str| s.parse::<u8>().ok());
|
||||
///
|
||||
/// // the parser will convert the result of digit1 to a number
|
||||
/// assert_eq!(parse("123"), Ok(("", 123)));
|
||||
///
|
||||
/// // this will fail if digit1 fails
|
||||
/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
|
||||
///
|
||||
/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
|
||||
/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn map_opt<I: Clone, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut parser: F,
|
||||
mut f: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: FnMut(O1) -> Option<O2>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
let (input, o1) = parser.parse(input)?;
|
||||
match f(o1) {
|
||||
Some(o2) => Ok((input, o2)),
|
||||
None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a parser over the result of another one.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::character::complete::digit1;
|
||||
/// use nom::bytes::complete::take;
|
||||
/// use nom::combinator::map_parser;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parse = map_parser(take(5u8), digit1);
|
||||
///
|
||||
/// assert_eq!(parse("12345"), Ok(("", "12345")));
|
||||
/// assert_eq!(parse("123ab"), Ok(("", "123")));
|
||||
/// assert_eq!(parse("123"), Err(Err::Error(("123", ErrorKind::Eof))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn map_parser<I, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut parser: F,
|
||||
mut applied_parser: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<O1, O2, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = parser.parse(input)?;
|
||||
let (_, o2) = applied_parser.parse(o1)?;
|
||||
Ok((input, o2))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::bytes::complete::take;
|
||||
/// use nom::number::complete::u8;
|
||||
/// use nom::combinator::flat_map;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parse = flat_map(u8, take);
|
||||
///
|
||||
/// assert_eq!(parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
|
||||
/// assert_eq!(parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(
|
||||
mut parser: F,
|
||||
mut applied_parser: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: FnMut(O1) -> H,
|
||||
H: Parser<I, O2, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = parser.parse(input)?;
|
||||
applied_parser(o1).parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
/// Optional parser, will return `None` on [`Err::Error`].
|
||||
///
|
||||
/// To chain an error up, see [`cut`].
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::opt;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// fn parser(i: &str) -> IResult<&str, Option<&str>> {
|
||||
/// opt(alpha1)(i)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("abcd;"), Ok((";", Some("abcd"))));
|
||||
/// assert_eq!(parser("123;"), Ok(("123;", None)));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn opt<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, Option<O>, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match f.parse(input) {
|
||||
Ok((i, o)) => Ok((i, Some(o))),
|
||||
Err(Err::Error(_)) => Ok((i, None)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls the parser if the condition is met.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::{Error, ErrorKind}, IResult};
|
||||
/// use nom::combinator::cond;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> {
|
||||
/// cond(b, alpha1)(i)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser(true, "abcd;"), Ok((";", Some("abcd"))));
|
||||
/// assert_eq!(parser(false, "abcd;"), Ok(("abcd;", None)));
|
||||
/// assert_eq!(parser(true, "123;"), Err(Err::Error(Error::new("123;", ErrorKind::Alpha))));
|
||||
/// assert_eq!(parser(false, "123;"), Ok(("123;", None)));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn cond<I, O, E: ParseError<I>, F>(
|
||||
b: bool,
|
||||
mut f: F,
|
||||
) -> impl FnMut(I) -> IResult<I, Option<O>, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
if b {
|
||||
match f.parse(input) {
|
||||
Ok((i, o)) => Ok((i, Some(o))),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
} else {
|
||||
Ok((input, None))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Tries to apply its parser without consuming the input.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::peek;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = peek(alpha1);
|
||||
///
|
||||
/// assert_eq!(parser("abcd;"), Ok(("abcd;", "abcd")));
|
||||
/// assert_eq!(parser("123;"), Err(Err::Error(("123;", ErrorKind::Alpha))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn peek<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match f.parse(input) {
|
||||
Ok((_, o)) => Ok((i, o)),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// returns its input if it is at the end of input data
|
||||
///
|
||||
/// When we're at the end of the data, this combinator
|
||||
/// will succeed
|
||||
///
|
||||
/// ```
|
||||
/// # use std::str;
|
||||
/// # use nom::{Err, error::ErrorKind, IResult};
|
||||
/// # use nom::combinator::eof;
|
||||
///
|
||||
/// # fn main() {
|
||||
/// let parser = eof;
|
||||
/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Eof))));
|
||||
/// assert_eq!(parser(""), Ok(("", "")));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn eof<I: InputLength + Clone, E: ParseError<I>>(input: I) -> IResult<I, I, E> {
|
||||
if input.input_len() == 0 {
|
||||
let clone = input.clone();
|
||||
Ok((input, clone))
|
||||
} else {
|
||||
Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms Incomplete into `Error`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::bytes::streaming::take;
|
||||
/// use nom::combinator::complete;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = complete(take(5u8));
|
||||
///
|
||||
/// assert_eq!(parser("abcdefg"), Ok(("fg", "abcde")));
|
||||
/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Complete))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn complete<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match f.parse(input) {
|
||||
Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))),
|
||||
rest => rest,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Succeeds if all the input has been consumed by its child parser.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::all_consuming;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = all_consuming(alpha1);
|
||||
///
|
||||
/// assert_eq!(parser("abcd"), Ok(("", "abcd")));
|
||||
/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Eof))));
|
||||
/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn all_consuming<I, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
|
||||
where
|
||||
I: InputLength,
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, res) = f.parse(input)?;
|
||||
if input.input_len() == 0 {
|
||||
Ok((input, res))
|
||||
} else {
|
||||
Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the result of the child parser if it satisfies a verification function.
|
||||
///
|
||||
/// The verification function takes as argument a reference to the output of the
|
||||
/// parser.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::verify;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = verify(alpha1, |s: &str| s.len() == 4);
|
||||
///
|
||||
/// assert_eq!(parser("abcd"), Ok(("", "abcd")));
|
||||
/// assert_eq!(parser("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify))));
|
||||
/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn verify<I: Clone, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut first: F,
|
||||
second: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O1, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Fn(&O2) -> bool,
|
||||
O1: Borrow<O2>,
|
||||
O2: ?Sized,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
let (input, o) = first.parse(input)?;
|
||||
|
||||
if second(o.borrow()) {
|
||||
Ok((input, o))
|
||||
} else {
|
||||
Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the provided value if the child parser succeeds.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::value;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = value(1234, alpha1);
|
||||
///
|
||||
/// assert_eq!(parser("abcd"), Ok(("", 1234)));
|
||||
/// assert_eq!(parser("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn value<I, O1: Clone, O2, E: ParseError<I>, F>(
|
||||
val: O1,
|
||||
mut parser: F,
|
||||
) -> impl FnMut(I) -> IResult<I, O1, E>
|
||||
where
|
||||
F: Parser<I, O2, E>,
|
||||
{
|
||||
move |input: I| parser.parse(input).map(|(i, _)| (i, val.clone()))
|
||||
}
|
||||
|
||||
/// Succeeds if the child parser returns an error.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::not;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = not(alpha1);
|
||||
///
|
||||
/// assert_eq!(parser("123"), Ok(("123", ())));
|
||||
/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Not))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn not<I: Clone, O, E: ParseError<I>, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, (), E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match parser.parse(input) {
|
||||
Ok(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Not))),
|
||||
Err(Err::Error(_)) => Ok((i, ())),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// If the child parser was successful, return the consumed input as produced value.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::recognize;
|
||||
/// use nom::character::complete::{char, alpha1};
|
||||
/// use nom::sequence::separated_pair;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = recognize(separated_pair(alpha1, char(','), alpha1));
|
||||
///
|
||||
/// assert_eq!(parser("abcd,efgh"), Ok(("", "abcd,efgh")));
|
||||
/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Char))));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn recognize<I: Clone + Offset + Slice<RangeTo<usize>>, O, E: ParseError<I>, F>(
|
||||
mut parser: F,
|
||||
) -> impl FnMut(I) -> IResult<I, I, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match parser.parse(i) {
|
||||
Ok((i, _)) => {
|
||||
let index = input.offset(&i);
|
||||
Ok((i, input.slice(..index)))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// if the child parser was successful, return the consumed input with the output
|
||||
/// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it
|
||||
/// returns the parser output as well.
|
||||
///
|
||||
/// This can be useful especially in cases where the output is not the same type
|
||||
/// as the input, or the input is a user defined type.
|
||||
///
|
||||
/// Returned tuple is of the format `(consumed input, produced output)`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::combinator::{consumed, value, recognize, map};
|
||||
/// use nom::character::complete::{char, alpha1};
|
||||
/// use nom::bytes::complete::tag;
|
||||
/// use nom::sequence::separated_pair;
|
||||
///
|
||||
/// fn inner_parser(input: &str) -> IResult<&str, bool> {
|
||||
/// value(true, tag("1234"))(input)
|
||||
/// }
|
||||
///
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut consumed_parser = consumed(value(true, separated_pair(alpha1, char(','), alpha1)));
|
||||
///
|
||||
/// assert_eq!(consumed_parser("abcd,efgh1"), Ok(("1", ("abcd,efgh", true))));
|
||||
/// assert_eq!(consumed_parser("abcd;"),Err(Err::Error((";", ErrorKind::Char))));
|
||||
///
|
||||
///
|
||||
/// // the first output (representing the consumed input)
|
||||
/// // should be the same as that of the `recognize` parser.
|
||||
/// let mut recognize_parser = recognize(inner_parser);
|
||||
/// let mut consumed_parser = map(consumed(inner_parser), |(consumed, output)| consumed);
|
||||
///
|
||||
/// assert_eq!(recognize_parser("1234"), consumed_parser("1234"));
|
||||
/// assert_eq!(recognize_parser("abcd"), consumed_parser("abcd"));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn consumed<I, O, F, E>(mut parser: F) -> impl FnMut(I) -> IResult<I, (I, O), E>
|
||||
where
|
||||
I: Clone + Offset + Slice<RangeTo<usize>>,
|
||||
E: ParseError<I>,
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let i = input.clone();
|
||||
match parser.parse(i) {
|
||||
Ok((remaining, result)) => {
|
||||
let index = input.offset(&remaining);
|
||||
let consumed = input.slice(..index);
|
||||
Ok((remaining, (consumed, result)))
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms an [`Err::Error`] (recoverable) to [`Err::Failure`] (unrecoverable)
|
||||
///
|
||||
/// This commits the parse result, preventing alternative branch paths like with
|
||||
/// [`nom::branch::alt`][crate::branch::alt].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Without `cut`:
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// # use nom::character::complete::{one_of, digit1};
|
||||
/// # use nom::combinator::rest;
|
||||
/// # use nom::branch::alt;
|
||||
/// # use nom::sequence::preceded;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, &str> {
|
||||
/// alt((
|
||||
/// preceded(one_of("+-"), digit1),
|
||||
/// rest
|
||||
/// ))(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
|
||||
/// assert_eq!(parser("ab"), Ok(("", "ab")));
|
||||
/// assert_eq!(parser("+"), Ok(("", "+")));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// With `cut`:
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult, error::Error};
|
||||
/// # use nom::character::complete::{one_of, digit1};
|
||||
/// # use nom::combinator::rest;
|
||||
/// # use nom::branch::alt;
|
||||
/// # use nom::sequence::preceded;
|
||||
/// use nom::combinator::cut;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// fn parser(input: &str) -> IResult<&str, &str> {
|
||||
/// alt((
|
||||
/// preceded(one_of("+-"), cut(digit1)),
|
||||
/// rest
|
||||
/// ))(input)
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
|
||||
/// assert_eq!(parser("ab"), Ok(("", "ab")));
|
||||
/// assert_eq!(parser("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit })));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn cut<I, O, E: ParseError<I>, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, O, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |input: I| match parser.parse(input) {
|
||||
Err(Err::Error(e)) => Err(Err::Failure(e)),
|
||||
rest => rest,
|
||||
}
|
||||
}
|
||||
|
||||
/// automatically converts the child parser's result to another type
|
||||
///
|
||||
/// it will be able to convert the output value and the error value
|
||||
/// as long as the `Into` implementations are available
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::IResult;
|
||||
/// use nom::combinator::into;
|
||||
/// use nom::character::complete::alpha1;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// fn parser1(i: &str) -> IResult<&str, &str> {
|
||||
/// alpha1(i)
|
||||
/// }
|
||||
///
|
||||
/// let mut parser2 = into(parser1);
|
||||
///
|
||||
/// // the parser converts the &str output of the child parser into a Vec<u8>
|
||||
/// let bytes: IResult<&str, Vec<u8>> = parser2("abcd");
|
||||
/// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn into<I, O1, O2, E1, E2, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, O2, E2>
|
||||
where
|
||||
O1: Into<O2>,
|
||||
E1: Into<E2>,
|
||||
E1: ParseError<I>,
|
||||
E2: ParseError<I>,
|
||||
F: Parser<I, O1, E1>,
|
||||
{
|
||||
//map(parser, Into::into)
|
||||
move |input: I| match parser.parse(input) {
|
||||
Ok((i, o)) => Ok((i, o.into())),
|
||||
Err(Err::Error(e)) => Err(Err::Error(e.into())),
|
||||
Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
|
||||
Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an iterator from input data and a parser.
|
||||
///
|
||||
/// Call the iterator's [ParserIterator::finish] method to get the remaining input if successful,
|
||||
/// or the error value if we encountered an error.
|
||||
///
|
||||
/// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`].
|
||||
///
|
||||
/// ```rust
|
||||
/// use nom::{combinator::iterator, IResult, bytes::complete::tag, character::complete::alpha1, sequence::terminated};
|
||||
/// use std::collections::HashMap;
|
||||
///
|
||||
/// let data = "abc|defg|hijkl|mnopqr|123";
|
||||
/// let mut it = iterator(data, terminated(alpha1, tag("|")));
|
||||
///
|
||||
/// let parsed = it.map(|v| (v, v.len())).collect::<HashMap<_,_>>();
|
||||
/// let res: IResult<_,_> = it.finish();
|
||||
///
|
||||
/// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect());
|
||||
/// assert_eq!(res, Ok(("123", ())));
|
||||
/// ```
|
||||
pub fn iterator<Input, Output, Error, F>(input: Input, f: F) -> ParserIterator<Input, Error, F>
|
||||
where
|
||||
F: Parser<Input, Output, Error>,
|
||||
Error: ParseError<Input>,
|
||||
{
|
||||
ParserIterator {
|
||||
iterator: f,
|
||||
input,
|
||||
state: Some(State::Running),
|
||||
}
|
||||
}
|
||||
|
||||
/// Main structure associated to the [iterator] function.
|
||||
pub struct ParserIterator<I, E, F> {
|
||||
iterator: F,
|
||||
input: I,
|
||||
state: Option<State<E>>,
|
||||
}
|
||||
|
||||
impl<I: Clone, E, F> ParserIterator<I, E, F> {
|
||||
/// Returns the remaining input if parsing was successful, or the error if we encountered an error.
|
||||
pub fn finish(mut self) -> IResult<I, (), E> {
|
||||
match self.state.take().unwrap() {
|
||||
State::Running | State::Done => Ok((self.input, ())),
|
||||
State::Failure(e) => Err(Err::Failure(e)),
|
||||
State::Incomplete(i) => Err(Err::Incomplete(i)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, Input, Output, Error, F> core::iter::Iterator for &'a mut ParserIterator<Input, Error, F>
|
||||
where
|
||||
F: FnMut(Input) -> IResult<Input, Output, Error>,
|
||||
Input: Clone,
|
||||
{
|
||||
type Item = Output;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let State::Running = self.state.take().unwrap() {
|
||||
let input = self.input.clone();
|
||||
|
||||
match (self.iterator)(input) {
|
||||
Ok((i, o)) => {
|
||||
self.input = i;
|
||||
self.state = Some(State::Running);
|
||||
Some(o)
|
||||
}
|
||||
Err(Err::Error(_)) => {
|
||||
self.state = Some(State::Done);
|
||||
None
|
||||
}
|
||||
Err(Err::Failure(e)) => {
|
||||
self.state = Some(State::Failure(e));
|
||||
None
|
||||
}
|
||||
Err(Err::Incomplete(i)) => {
|
||||
self.state = Some(State::Incomplete(i));
|
||||
None
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum State<E> {
|
||||
Running,
|
||||
Done,
|
||||
Failure(E),
|
||||
Incomplete(Needed),
|
||||
}
|
||||
|
||||
/// a parser which always succeeds with given value without consuming any input.
|
||||
///
|
||||
/// It can be used for example as the last alternative in `alt` to
|
||||
/// specify the default case.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err,error::ErrorKind, IResult};
|
||||
/// use nom::branch::alt;
|
||||
/// use nom::combinator::{success, value};
|
||||
/// use nom::character::complete::char;
|
||||
/// # fn main() {
|
||||
///
|
||||
/// let mut parser = success::<_,_,(_,ErrorKind)>(10);
|
||||
/// assert_eq!(parser("xyz"), Ok(("xyz", 10)));
|
||||
///
|
||||
/// let mut sign = alt((value(-1, char('-')), value(1, char('+')), success::<_,_,(_,ErrorKind)>(1)));
|
||||
/// assert_eq!(sign("+10"), Ok(("10", 1)));
|
||||
/// assert_eq!(sign("-10"), Ok(("10", -1)));
|
||||
/// assert_eq!(sign("10"), Ok(("10", 1)));
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn success<I, O: Clone, E: ParseError<I>>(val: O) -> impl Fn(I) -> IResult<I, O, E> {
|
||||
move |input: I| Ok((input, val.clone()))
|
||||
}
|
||||
|
||||
/// A parser which always fails.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, IResult};
|
||||
/// use nom::combinator::fail;
|
||||
///
|
||||
/// let s = "string";
|
||||
/// assert_eq!(fail::<_, &str, _>(s), Err(Err::Error((s, ErrorKind::Fail))));
|
||||
/// ```
|
||||
pub fn fail<I, O, E: ParseError<I>>(i: I) -> IResult<I, O, E> {
|
||||
Err(Err::Error(E::from_error_kind(i, ErrorKind::Fail)))
|
||||
}
|
||||
275
third-party/vendor/nom/src/combinator/tests.rs
vendored
Normal file
275
third-party/vendor/nom/src/combinator/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,275 @@
|
|||
use super::*;
|
||||
use crate::bytes::complete::take;
|
||||
use crate::bytes::streaming::tag;
|
||||
use crate::error::ErrorKind;
|
||||
use crate::error::ParseError;
|
||||
use crate::internal::{Err, IResult, Needed};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::lib::std::boxed::Box;
|
||||
use crate::number::complete::u8;
|
||||
|
||||
macro_rules! assert_parse(
|
||||
($left: expr, $right: expr) => {
|
||||
let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
|
||||
assert_eq!(res, $right);
|
||||
};
|
||||
);
|
||||
|
||||
/*#[test]
|
||||
fn t1() {
|
||||
let v1:Vec<u8> = vec![1,2,3];
|
||||
let v2:Vec<u8> = vec![4,5,6];
|
||||
let d = Ok((&v1[..], &v2[..]));
|
||||
let res = d.flat_map(print);
|
||||
assert_eq!(res, Ok((&v2[..], ())));
|
||||
}*/
|
||||
|
||||
#[test]
|
||||
fn eof_on_slices() {
|
||||
let not_over: &[u8] = &b"Hello, world!"[..];
|
||||
let is_over: &[u8] = &b""[..];
|
||||
|
||||
let res_not_over = eof(not_over);
|
||||
assert_parse!(
|
||||
res_not_over,
|
||||
Err(Err::Error(error_position!(not_over, ErrorKind::Eof)))
|
||||
);
|
||||
|
||||
let res_over = eof(is_over);
|
||||
assert_parse!(res_over, Ok((is_over, is_over)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eof_on_strs() {
|
||||
let not_over: &str = "Hello, world!";
|
||||
let is_over: &str = "";
|
||||
|
||||
let res_not_over = eof(not_over);
|
||||
assert_parse!(
|
||||
res_not_over,
|
||||
Err(Err::Error(error_position!(not_over, ErrorKind::Eof)))
|
||||
);
|
||||
|
||||
let res_over = eof(is_over);
|
||||
assert_parse!(res_over, Ok((is_over, is_over)));
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn end_of_input() {
|
||||
let not_over = &b"Hello, world!"[..];
|
||||
let is_over = &b""[..];
|
||||
named!(eof_test, eof!());
|
||||
|
||||
let res_not_over = eof_test(not_over);
|
||||
assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));
|
||||
|
||||
let res_over = eof_test(is_over);
|
||||
assert_eq!(res_over, Ok((is_over, is_over)));
|
||||
}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn rest_on_slices() {
|
||||
let input: &[u8] = &b"Hello, world!"[..];
|
||||
let empty: &[u8] = &b""[..];
|
||||
assert_parse!(rest(input), Ok((empty, input)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rest_on_strs() {
|
||||
let input: &str = "Hello, world!";
|
||||
let empty: &str = "";
|
||||
assert_parse!(rest(input), Ok((empty, input)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rest_len_on_slices() {
|
||||
let input: &[u8] = &b"Hello, world!"[..];
|
||||
assert_parse!(rest_len(input), Ok((input, input.len())));
|
||||
}
|
||||
|
||||
use crate::lib::std::convert::From;
|
||||
impl From<u32> for CustomError {
|
||||
fn from(_: u32) -> Self {
|
||||
CustomError
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ParseError<I> for CustomError {
|
||||
fn from_error_kind(_: I, _: ErrorKind) -> Self {
|
||||
CustomError
|
||||
}
|
||||
|
||||
fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
|
||||
CustomError
|
||||
}
|
||||
}
|
||||
|
||||
struct CustomError;
|
||||
#[allow(dead_code)]
|
||||
fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
|
||||
//fix_error!(input, CustomError, alphanumeric)
|
||||
crate::character::streaming::alphanumeric1(input)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_flat_map() {
|
||||
let input: &[u8] = &[3, 100, 101, 102, 103, 104][..];
|
||||
assert_parse!(
|
||||
flat_map(u8, take)(input),
|
||||
Ok((&[103, 104][..], &[100, 101, 102][..]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_opt() {
|
||||
let input: &[u8] = &[50][..];
|
||||
assert_parse!(
|
||||
map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input),
|
||||
Err(Err::Error((&[50][..], ErrorKind::MapOpt)))
|
||||
);
|
||||
assert_parse!(
|
||||
map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input),
|
||||
Ok((&[][..], 50))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_map_parser() {
|
||||
let input: &[u8] = &[100, 101, 102, 103, 104][..];
|
||||
assert_parse!(
|
||||
map_parser(take(4usize), take(2usize))(input),
|
||||
Ok((&[104][..], &[100, 101][..]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_all_consuming() {
|
||||
let input: &[u8] = &[100, 101, 102][..];
|
||||
assert_parse!(
|
||||
all_consuming(take(2usize))(input),
|
||||
Err(Err::Error((&[102][..], ErrorKind::Eof)))
|
||||
);
|
||||
assert_parse!(
|
||||
all_consuming(take(3usize))(input),
|
||||
Ok((&[][..], &[100, 101, 102][..]))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(unused)]
|
||||
fn test_verify_ref() {
|
||||
use crate::bytes::complete::take;
|
||||
|
||||
let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]);
|
||||
|
||||
assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..])));
|
||||
assert_eq!(
|
||||
parser1(&b"defg"[..]),
|
||||
Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
|
||||
);
|
||||
|
||||
fn parser2(i: &[u8]) -> IResult<&[u8], u32> {
|
||||
verify(crate::number::streaming::be_u32, |val: &u32| *val < 3)(i)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn test_verify_alloc() {
|
||||
use crate::bytes::complete::take;
|
||||
let mut parser1 = verify(map(take(3u8), |s: &[u8]| s.to_vec()), |s: &[u8]| {
|
||||
s == &b"abc"[..]
|
||||
});
|
||||
|
||||
assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], (&b"abc").to_vec())));
|
||||
assert_eq!(
|
||||
parser1(&b"defg"[..]),
|
||||
Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn test_into() {
|
||||
use crate::bytes::complete::take;
|
||||
use crate::{
|
||||
error::{Error, ParseError},
|
||||
Err,
|
||||
};
|
||||
|
||||
let mut parser = into(take::<_, _, Error<_>>(3u8));
|
||||
let result: IResult<&[u8], Vec<u8>> = parser(&b"abcdefg"[..]);
|
||||
|
||||
assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn opt_test() {
|
||||
fn opt_abcd(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> {
|
||||
opt(tag("abcd"))(i)
|
||||
}
|
||||
|
||||
let a = &b"abcdef"[..];
|
||||
let b = &b"bcdefg"[..];
|
||||
let c = &b"ab"[..];
|
||||
assert_eq!(opt_abcd(a), Ok((&b"ef"[..], Some(&b"abcd"[..]))));
|
||||
assert_eq!(opt_abcd(b), Ok((&b"bcdefg"[..], None)));
|
||||
assert_eq!(opt_abcd(c), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn peek_test() {
|
||||
fn peek_tag(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
peek(tag("abcd"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(peek_tag(&b"abcdef"[..]), Ok((&b"abcdef"[..], &b"abcd"[..])));
|
||||
assert_eq!(peek_tag(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(
|
||||
peek_tag(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_test() {
|
||||
fn not_aaa(i: &[u8]) -> IResult<&[u8], ()> {
|
||||
not(tag("aaa"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
not_aaa(&b"aaa"[..]),
|
||||
Err(Err::Error(error_position!(&b"aaa"[..], ErrorKind::Not)))
|
||||
);
|
||||
assert_eq!(not_aaa(&b"aa"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(not_aaa(&b"abcd"[..]), Ok((&b"abcd"[..], ())));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn verify_test() {
|
||||
use crate::bytes::streaming::take;
|
||||
|
||||
fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i)
|
||||
}
|
||||
assert_eq!(test(&b"bcd"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(
|
||||
test(&b"bcdefg"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"bcdefg"[..],
|
||||
ErrorKind::Verify
|
||||
)))
|
||||
);
|
||||
assert_eq!(test(&b"abcdefg"[..]), Ok((&b"fg"[..], &b"abcde"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn fail_test() {
|
||||
let a = "string";
|
||||
let b = "another string";
|
||||
|
||||
assert_eq!(fail::<_, &str, _>(a), Err(Err::Error((a, ErrorKind::Fail))));
|
||||
assert_eq!(fail::<_, &str, _>(b), Err(Err::Error((b, ErrorKind::Fail))));
|
||||
}
|
||||
831
third-party/vendor/nom/src/error.rs
vendored
Normal file
831
third-party/vendor/nom/src/error.rs
vendored
Normal file
|
|
@ -0,0 +1,831 @@
|
|||
//! Error management
|
||||
//!
|
||||
//! Parsers are generic over their error type, requiring that it implements
|
||||
//! the `error::ParseError<Input>` trait.
|
||||
|
||||
use crate::internal::Parser;
|
||||
use crate::lib::std::fmt;
|
||||
|
||||
/// This trait must be implemented by the error type of a nom parser.
|
||||
///
|
||||
/// There are already implementations of it for `(Input, ErrorKind)`
|
||||
/// and `VerboseError<Input>`.
|
||||
///
|
||||
/// It provides methods to create an error from some combinators,
|
||||
/// and combine existing errors in combinators like `alt`.
|
||||
pub trait ParseError<I>: Sized {
|
||||
/// Creates an error from the input position and an [ErrorKind]
|
||||
fn from_error_kind(input: I, kind: ErrorKind) -> Self;
|
||||
|
||||
/// Combines an existing error with a new one created from the input
|
||||
/// position and an [ErrorKind]. This is useful when backtracking
|
||||
/// through a parse tree, accumulating error context on the way
|
||||
fn append(input: I, kind: ErrorKind, other: Self) -> Self;
|
||||
|
||||
/// Creates an error from an input position and an expected character
|
||||
fn from_char(input: I, _: char) -> Self {
|
||||
Self::from_error_kind(input, ErrorKind::Char)
|
||||
}
|
||||
|
||||
/// Combines two existing errors. This function is used to compare errors
|
||||
/// generated in various branches of `alt`.
|
||||
fn or(self, other: Self) -> Self {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is required by the `context` combinator to add a static string
|
||||
/// to an existing error
|
||||
pub trait ContextError<I>: Sized {
|
||||
/// Creates a new error from an input position, a static string and an existing error.
|
||||
/// This is used mainly in the [context] combinator, to add user friendly information
|
||||
/// to errors when backtracking through a parse tree
|
||||
fn add_context(_input: I, _ctx: &'static str, other: Self) -> Self {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
/// This trait is required by the `map_res` combinator to integrate
|
||||
/// error types from external functions, like [std::str::FromStr]
|
||||
pub trait FromExternalError<I, E> {
|
||||
/// Creates a new error from an input position, an [ErrorKind] indicating the
|
||||
/// wrapping parser, and an external error
|
||||
fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self;
|
||||
}
|
||||
|
||||
/// default error type, only contains the error' location and code
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Error<I> {
|
||||
/// position of the error in the input data
|
||||
pub input: I,
|
||||
/// nom error code
|
||||
pub code: ErrorKind,
|
||||
}
|
||||
|
||||
impl<I> Error<I> {
|
||||
/// creates a new basic error
|
||||
pub fn new(input: I, code: ErrorKind) -> Error<I> {
|
||||
Error { input, code }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ParseError<I> for Error<I> {
|
||||
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
|
||||
Error { input, code: kind }
|
||||
}
|
||||
|
||||
fn append(_: I, _: ErrorKind, other: Self) -> Self {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ContextError<I> for Error<I> {}
|
||||
|
||||
impl<I, E> FromExternalError<I, E> for Error<I> {
|
||||
/// Create a new error from an input position and an external error
|
||||
fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
|
||||
Error { input, code: kind }
|
||||
}
|
||||
}
|
||||
|
||||
/// The Display implementation allows the std::error::Error implementation
|
||||
impl<I: fmt::Display> fmt::Display for Error<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "error {:?} at: {}", self.code, self.input)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I: fmt::Debug + fmt::Display> std::error::Error for Error<I> {}
|
||||
|
||||
// for backward compatibility, keep those trait implementations
|
||||
// for the previously used error type
|
||||
impl<I> ParseError<I> for (I, ErrorKind) {
|
||||
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
|
||||
(input, kind)
|
||||
}
|
||||
|
||||
fn append(_: I, _: ErrorKind, other: Self) -> Self {
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ContextError<I> for (I, ErrorKind) {}
|
||||
|
||||
impl<I, E> FromExternalError<I, E> for (I, ErrorKind) {
|
||||
fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
|
||||
(input, kind)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ParseError<I> for () {
|
||||
fn from_error_kind(_: I, _: ErrorKind) -> Self {}
|
||||
|
||||
fn append(_: I, _: ErrorKind, _: Self) -> Self {}
|
||||
}
|
||||
|
||||
impl<I> ContextError<I> for () {}
|
||||
|
||||
impl<I, E> FromExternalError<I, E> for () {
|
||||
fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {}
|
||||
}
|
||||
|
||||
/// Creates an error from the input position and an [ErrorKind]
|
||||
pub fn make_error<I, E: ParseError<I>>(input: I, kind: ErrorKind) -> E {
|
||||
E::from_error_kind(input, kind)
|
||||
}
|
||||
|
||||
/// Combines an existing error with a new one created from the input
|
||||
/// position and an [ErrorKind]. This is useful when backtracking
|
||||
/// through a parse tree, accumulating error context on the way
|
||||
pub fn append_error<I, E: ParseError<I>>(input: I, kind: ErrorKind, other: E) -> E {
|
||||
E::append(input, kind, other)
|
||||
}
|
||||
|
||||
/// This error type accumulates errors and their position when backtracking
|
||||
/// through a parse tree. With some post processing (cf `examples/json.rs`),
|
||||
/// it can be used to display user friendly error messages
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct VerboseError<I> {
|
||||
/// List of errors accumulated by `VerboseError`, containing the affected
|
||||
/// part of input data, and some context
|
||||
pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
/// Error context for `VerboseError`
|
||||
pub enum VerboseErrorKind {
|
||||
/// Static string added by the `context` function
|
||||
Context(&'static str),
|
||||
/// Indicates which character was expected by the `char` function
|
||||
Char(char),
|
||||
/// Error kind given by various nom parsers
|
||||
Nom(ErrorKind),
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
impl<I> ParseError<I> for VerboseError<I> {
|
||||
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
|
||||
VerboseError {
|
||||
errors: vec![(input, VerboseErrorKind::Nom(kind))],
|
||||
}
|
||||
}
|
||||
|
||||
fn append(input: I, kind: ErrorKind, mut other: Self) -> Self {
|
||||
other.errors.push((input, VerboseErrorKind::Nom(kind)));
|
||||
other
|
||||
}
|
||||
|
||||
fn from_char(input: I, c: char) -> Self {
|
||||
VerboseError {
|
||||
errors: vec![(input, VerboseErrorKind::Char(c))],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
impl<I> ContextError<I> for VerboseError<I> {
|
||||
fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self {
|
||||
other.errors.push((input, VerboseErrorKind::Context(ctx)));
|
||||
other
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
impl<I, E> FromExternalError<I, E> for VerboseError<I> {
|
||||
/// Create a new error from an input position and an external error
|
||||
fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
|
||||
Self::from_error_kind(input, kind)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<I: fmt::Display> fmt::Display for VerboseError<I> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
writeln!(f, "Parse error:")?;
|
||||
for (input, error) in &self.errors {
|
||||
match error {
|
||||
VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?,
|
||||
VerboseErrorKind::Char(c) => writeln!(f, "expected '{}' at: {}", c, input)?,
|
||||
VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<I: fmt::Debug + fmt::Display> std::error::Error for VerboseError<I> {}
|
||||
|
||||
use crate::internal::{Err, IResult};
|
||||
|
||||
/// Create a new error from an input position, a static string and an existing error.
|
||||
/// This is used mainly in the [context] combinator, to add user friendly information
|
||||
/// to errors when backtracking through a parse tree
|
||||
pub fn context<I: Clone, E: ContextError<I>, F, O>(
|
||||
context: &'static str,
|
||||
mut f: F,
|
||||
) -> impl FnMut(I) -> IResult<I, O, E>
|
||||
where
|
||||
F: Parser<I, O, E>,
|
||||
{
|
||||
move |i: I| match f.parse(i.clone()) {
|
||||
Ok(o) => Ok(o),
|
||||
Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
|
||||
Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))),
|
||||
Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))),
|
||||
}
|
||||
}
|
||||
|
||||
/// Transforms a `VerboseError` into a trace with input position information
|
||||
#[cfg(feature = "alloc")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn convert_error<I: core::ops::Deref<Target = str>>(
|
||||
input: I,
|
||||
e: VerboseError<I>,
|
||||
) -> crate::lib::std::string::String {
|
||||
use crate::lib::std::fmt::Write;
|
||||
use crate::traits::Offset;
|
||||
|
||||
let mut result = crate::lib::std::string::String::new();
|
||||
|
||||
for (i, (substring, kind)) in e.errors.iter().enumerate() {
|
||||
let offset = input.offset(substring);
|
||||
|
||||
if input.is_empty() {
|
||||
match kind {
|
||||
VerboseErrorKind::Char(c) => {
|
||||
write!(&mut result, "{}: expected '{}', got empty input\n\n", i, c)
|
||||
}
|
||||
VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s),
|
||||
VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e),
|
||||
}
|
||||
} else {
|
||||
let prefix = &input.as_bytes()[..offset];
|
||||
|
||||
// Count the number of newlines in the first `offset` bytes of input
|
||||
let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1;
|
||||
|
||||
// Find the line that includes the subslice:
|
||||
// Find the *last* newline before the substring starts
|
||||
let line_begin = prefix
|
||||
.iter()
|
||||
.rev()
|
||||
.position(|&b| b == b'\n')
|
||||
.map(|pos| offset - pos)
|
||||
.unwrap_or(0);
|
||||
|
||||
// Find the full line after that newline
|
||||
let line = input[line_begin..]
|
||||
.lines()
|
||||
.next()
|
||||
.unwrap_or(&input[line_begin..])
|
||||
.trim_end();
|
||||
|
||||
// The (1-indexed) column number is the offset of our substring into that line
|
||||
let column_number = line.offset(substring) + 1;
|
||||
|
||||
match kind {
|
||||
VerboseErrorKind::Char(c) => {
|
||||
if let Some(actual) = substring.chars().next() {
|
||||
write!(
|
||||
&mut result,
|
||||
"{i}: at line {line_number}:\n\
|
||||
{line}\n\
|
||||
{caret:>column$}\n\
|
||||
expected '{expected}', found {actual}\n\n",
|
||||
i = i,
|
||||
line_number = line_number,
|
||||
line = line,
|
||||
caret = '^',
|
||||
column = column_number,
|
||||
expected = c,
|
||||
actual = actual,
|
||||
)
|
||||
} else {
|
||||
write!(
|
||||
&mut result,
|
||||
"{i}: at line {line_number}:\n\
|
||||
{line}\n\
|
||||
{caret:>column$}\n\
|
||||
expected '{expected}', got end of input\n\n",
|
||||
i = i,
|
||||
line_number = line_number,
|
||||
line = line,
|
||||
caret = '^',
|
||||
column = column_number,
|
||||
expected = c,
|
||||
)
|
||||
}
|
||||
}
|
||||
VerboseErrorKind::Context(s) => write!(
|
||||
&mut result,
|
||||
"{i}: at line {line_number}, in {context}:\n\
|
||||
{line}\n\
|
||||
{caret:>column$}\n\n",
|
||||
i = i,
|
||||
line_number = line_number,
|
||||
context = s,
|
||||
line = line,
|
||||
caret = '^',
|
||||
column = column_number,
|
||||
),
|
||||
VerboseErrorKind::Nom(e) => write!(
|
||||
&mut result,
|
||||
"{i}: at line {line_number}, in {nom_err:?}:\n\
|
||||
{line}\n\
|
||||
{caret:>column$}\n\n",
|
||||
i = i,
|
||||
line_number = line_number,
|
||||
nom_err = e,
|
||||
line = line,
|
||||
caret = '^',
|
||||
column = column_number,
|
||||
),
|
||||
}
|
||||
}
|
||||
// Because `write!` to a `String` is infallible, this `unwrap` is fine.
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
/// Indicates which parser returned an error
|
||||
#[rustfmt::skip]
|
||||
#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
|
||||
#[allow(deprecated,missing_docs)]
|
||||
pub enum ErrorKind {
|
||||
Tag,
|
||||
MapRes,
|
||||
MapOpt,
|
||||
Alt,
|
||||
IsNot,
|
||||
IsA,
|
||||
SeparatedList,
|
||||
SeparatedNonEmptyList,
|
||||
Many0,
|
||||
Many1,
|
||||
ManyTill,
|
||||
Count,
|
||||
TakeUntil,
|
||||
LengthValue,
|
||||
TagClosure,
|
||||
Alpha,
|
||||
Digit,
|
||||
HexDigit,
|
||||
OctDigit,
|
||||
AlphaNumeric,
|
||||
Space,
|
||||
MultiSpace,
|
||||
LengthValueFn,
|
||||
Eof,
|
||||
Switch,
|
||||
TagBits,
|
||||
OneOf,
|
||||
NoneOf,
|
||||
Char,
|
||||
CrLf,
|
||||
RegexpMatch,
|
||||
RegexpMatches,
|
||||
RegexpFind,
|
||||
RegexpCapture,
|
||||
RegexpCaptures,
|
||||
TakeWhile1,
|
||||
Complete,
|
||||
Fix,
|
||||
Escaped,
|
||||
EscapedTransform,
|
||||
NonEmpty,
|
||||
ManyMN,
|
||||
Not,
|
||||
Permutation,
|
||||
Verify,
|
||||
TakeTill1,
|
||||
TakeWhileMN,
|
||||
TooLarge,
|
||||
Many0Count,
|
||||
Many1Count,
|
||||
Float,
|
||||
Satisfy,
|
||||
Fail,
|
||||
}
|
||||
|
||||
#[rustfmt::skip]
|
||||
#[allow(deprecated)]
|
||||
/// Converts an ErrorKind to a number
|
||||
pub fn error_to_u32(e: &ErrorKind) -> u32 {
|
||||
match *e {
|
||||
ErrorKind::Tag => 1,
|
||||
ErrorKind::MapRes => 2,
|
||||
ErrorKind::MapOpt => 3,
|
||||
ErrorKind::Alt => 4,
|
||||
ErrorKind::IsNot => 5,
|
||||
ErrorKind::IsA => 6,
|
||||
ErrorKind::SeparatedList => 7,
|
||||
ErrorKind::SeparatedNonEmptyList => 8,
|
||||
ErrorKind::Many1 => 9,
|
||||
ErrorKind::Count => 10,
|
||||
ErrorKind::TakeUntil => 12,
|
||||
ErrorKind::LengthValue => 15,
|
||||
ErrorKind::TagClosure => 16,
|
||||
ErrorKind::Alpha => 17,
|
||||
ErrorKind::Digit => 18,
|
||||
ErrorKind::AlphaNumeric => 19,
|
||||
ErrorKind::Space => 20,
|
||||
ErrorKind::MultiSpace => 21,
|
||||
ErrorKind::LengthValueFn => 22,
|
||||
ErrorKind::Eof => 23,
|
||||
ErrorKind::Switch => 27,
|
||||
ErrorKind::TagBits => 28,
|
||||
ErrorKind::OneOf => 29,
|
||||
ErrorKind::NoneOf => 30,
|
||||
ErrorKind::Char => 40,
|
||||
ErrorKind::CrLf => 41,
|
||||
ErrorKind::RegexpMatch => 42,
|
||||
ErrorKind::RegexpMatches => 43,
|
||||
ErrorKind::RegexpFind => 44,
|
||||
ErrorKind::RegexpCapture => 45,
|
||||
ErrorKind::RegexpCaptures => 46,
|
||||
ErrorKind::TakeWhile1 => 47,
|
||||
ErrorKind::Complete => 48,
|
||||
ErrorKind::Fix => 49,
|
||||
ErrorKind::Escaped => 50,
|
||||
ErrorKind::EscapedTransform => 51,
|
||||
ErrorKind::NonEmpty => 56,
|
||||
ErrorKind::ManyMN => 57,
|
||||
ErrorKind::HexDigit => 59,
|
||||
ErrorKind::OctDigit => 61,
|
||||
ErrorKind::Many0 => 62,
|
||||
ErrorKind::Not => 63,
|
||||
ErrorKind::Permutation => 64,
|
||||
ErrorKind::ManyTill => 65,
|
||||
ErrorKind::Verify => 66,
|
||||
ErrorKind::TakeTill1 => 67,
|
||||
ErrorKind::TakeWhileMN => 69,
|
||||
ErrorKind::TooLarge => 70,
|
||||
ErrorKind::Many0Count => 71,
|
||||
ErrorKind::Many1Count => 72,
|
||||
ErrorKind::Float => 73,
|
||||
ErrorKind::Satisfy => 74,
|
||||
ErrorKind::Fail => 75,
|
||||
}
|
||||
}
|
||||
|
||||
impl ErrorKind {
|
||||
#[rustfmt::skip]
|
||||
#[allow(deprecated)]
|
||||
/// Converts an ErrorKind to a text description
|
||||
pub fn description(&self) -> &str {
|
||||
match *self {
|
||||
ErrorKind::Tag => "Tag",
|
||||
ErrorKind::MapRes => "Map on Result",
|
||||
ErrorKind::MapOpt => "Map on Option",
|
||||
ErrorKind::Alt => "Alternative",
|
||||
ErrorKind::IsNot => "IsNot",
|
||||
ErrorKind::IsA => "IsA",
|
||||
ErrorKind::SeparatedList => "Separated list",
|
||||
ErrorKind::SeparatedNonEmptyList => "Separated non empty list",
|
||||
ErrorKind::Many0 => "Many0",
|
||||
ErrorKind::Many1 => "Many1",
|
||||
ErrorKind::Count => "Count",
|
||||
ErrorKind::TakeUntil => "Take until",
|
||||
ErrorKind::LengthValue => "Length followed by value",
|
||||
ErrorKind::TagClosure => "Tag closure",
|
||||
ErrorKind::Alpha => "Alphabetic",
|
||||
ErrorKind::Digit => "Digit",
|
||||
ErrorKind::AlphaNumeric => "AlphaNumeric",
|
||||
ErrorKind::Space => "Space",
|
||||
ErrorKind::MultiSpace => "Multiple spaces",
|
||||
ErrorKind::LengthValueFn => "LengthValueFn",
|
||||
ErrorKind::Eof => "End of file",
|
||||
ErrorKind::Switch => "Switch",
|
||||
ErrorKind::TagBits => "Tag on bitstream",
|
||||
ErrorKind::OneOf => "OneOf",
|
||||
ErrorKind::NoneOf => "NoneOf",
|
||||
ErrorKind::Char => "Char",
|
||||
ErrorKind::CrLf => "CrLf",
|
||||
ErrorKind::RegexpMatch => "RegexpMatch",
|
||||
ErrorKind::RegexpMatches => "RegexpMatches",
|
||||
ErrorKind::RegexpFind => "RegexpFind",
|
||||
ErrorKind::RegexpCapture => "RegexpCapture",
|
||||
ErrorKind::RegexpCaptures => "RegexpCaptures",
|
||||
ErrorKind::TakeWhile1 => "TakeWhile1",
|
||||
ErrorKind::Complete => "Complete",
|
||||
ErrorKind::Fix => "Fix",
|
||||
ErrorKind::Escaped => "Escaped",
|
||||
ErrorKind::EscapedTransform => "EscapedTransform",
|
||||
ErrorKind::NonEmpty => "NonEmpty",
|
||||
ErrorKind::ManyMN => "Many(m, n)",
|
||||
ErrorKind::HexDigit => "Hexadecimal Digit",
|
||||
ErrorKind::OctDigit => "Octal digit",
|
||||
ErrorKind::Not => "Negation",
|
||||
ErrorKind::Permutation => "Permutation",
|
||||
ErrorKind::ManyTill => "ManyTill",
|
||||
ErrorKind::Verify => "predicate verification",
|
||||
ErrorKind::TakeTill1 => "TakeTill1",
|
||||
ErrorKind::TakeWhileMN => "TakeWhileMN",
|
||||
ErrorKind::TooLarge => "Needed data size is too large",
|
||||
ErrorKind::Many0Count => "Count occurrence of >=0 patterns",
|
||||
ErrorKind::Many1Count => "Count occurrence of >=1 patterns",
|
||||
ErrorKind::Float => "Float",
|
||||
ErrorKind::Satisfy => "Satisfy",
|
||||
ErrorKind::Fail => "Fail",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a parse error from a `nom::ErrorKind`
|
||||
/// and the position in the input
|
||||
#[allow(unused_variables)]
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! error_position(
|
||||
($input:expr, $code:expr) => ({
|
||||
$crate::error::make_error($input, $code)
|
||||
});
|
||||
);
|
||||
|
||||
/// Creates a parse error from a `nom::ErrorKind`,
|
||||
/// the position in the input and the next error in
|
||||
/// the parsing tree
|
||||
#[allow(unused_variables)]
|
||||
#[macro_export(local_inner_macros)]
|
||||
macro_rules! error_node_position(
|
||||
($input:expr, $code:expr, $next:expr) => ({
|
||||
$crate::error::append_error($input, $code, $next)
|
||||
});
|
||||
);
|
||||
|
||||
/// Prints a message and the input if the parser fails.
|
||||
///
|
||||
/// The message prints the `Error` or `Incomplete`
|
||||
/// and the parser's calling code.
|
||||
///
|
||||
/// It also displays the input in hexdump format
|
||||
///
|
||||
/// ```rust
|
||||
/// use nom::{IResult, error::dbg_dmp, bytes::complete::tag};
|
||||
///
|
||||
/// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
/// dbg_dmp(tag("abcd"), "tag")(i)
|
||||
/// }
|
||||
///
|
||||
/// let a = &b"efghijkl"[..];
|
||||
///
|
||||
/// // Will print the following message:
|
||||
/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
|
||||
/// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
|
||||
/// f(a);
|
||||
/// ```
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "std")))]
|
||||
pub fn dbg_dmp<'a, F, O, E: std::fmt::Debug>(
|
||||
f: F,
|
||||
context: &'static str,
|
||||
) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E>
|
||||
where
|
||||
F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>,
|
||||
{
|
||||
use crate::HexDisplay;
|
||||
move |i: &'a [u8]| match f(i) {
|
||||
Err(e) => {
|
||||
println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
|
||||
Err(e)
|
||||
}
|
||||
a => a,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[cfg(feature = "alloc")]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::character::complete::char;
|
||||
|
||||
#[test]
|
||||
fn convert_error_panic() {
|
||||
let input = "";
|
||||
|
||||
let _result: IResult<_, _, VerboseError<&str>> = char('x')(input);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[cfg(feature = "alloc")]
|
||||
use lib::std::{vec::Vec, collections::HashMap};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use lib::std::hash::Hash;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn add_error_pattern<'a, I: Clone + Hash + Eq, O, E: Clone + Hash + Eq>(
|
||||
h: &mut HashMap<VerboseError<I>, &'a str>,
|
||||
e: VerboseError<I>,
|
||||
message: &'a str,
|
||||
) -> bool {
|
||||
h.insert(e, message);
|
||||
true
|
||||
}
|
||||
|
||||
pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) {
|
||||
let start = input.as_ptr();
|
||||
let off1 = s.as_ptr() as usize - start as usize;
|
||||
let off2 = off1 + s.len();
|
||||
(off1, off2)
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn prepare_errors<O, E: Clone>(input: &[u8], e: VerboseError<&[u8]>) -> Option<Vec<(ErrorKind, usize, usize)>> {
|
||||
let mut v: Vec<(ErrorKind, usize, usize)> = Vec::new();
|
||||
|
||||
for (p, kind) in e.errors.drain(..) {
|
||||
let (o1, o2) = slice_to_offsets(input, p);
|
||||
v.push((kind, o1, o2));
|
||||
}
|
||||
|
||||
v.reverse();
|
||||
Some(v)
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn print_error<O, E: Clone>(input: &[u8], res: VerboseError<&[u8]>) {
|
||||
if let Some(v) = prepare_errors(input, res) {
|
||||
let colors = generate_colors(&v);
|
||||
println!("parser codes: {}", print_codes(&colors, &HashMap::new()));
|
||||
println!("{}", print_offsets(input, 0, &v));
|
||||
} else {
|
||||
println!("not an error");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn generate_colors<E>(v: &[(ErrorKind, usize, usize)]) -> HashMap<u32, u8> {
|
||||
let mut h: HashMap<u32, u8> = HashMap::new();
|
||||
let mut color = 0;
|
||||
|
||||
for &(ref c, _, _) in v.iter() {
|
||||
h.insert(error_to_u32(c), color + 31);
|
||||
color = color + 1 % 7;
|
||||
}
|
||||
|
||||
h
|
||||
}
|
||||
|
||||
pub fn code_from_offset(v: &[(ErrorKind, usize, usize)], offset: usize) -> Option<u32> {
|
||||
let mut acc: Option<(u32, usize, usize)> = None;
|
||||
for &(ref ek, s, e) in v.iter() {
|
||||
let c = error_to_u32(ek);
|
||||
if s <= offset && offset <= e {
|
||||
if let Some((_, start, end)) = acc {
|
||||
if start <= s && e <= end {
|
||||
acc = Some((c, s, e));
|
||||
}
|
||||
} else {
|
||||
acc = Some((c, s, e));
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some((code, _, _)) = acc {
|
||||
return Some(code);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn reset_color(v: &mut Vec<u8>) {
|
||||
v.push(0x1B);
|
||||
v.push(b'[');
|
||||
v.push(0);
|
||||
v.push(b'm');
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
pub fn write_color(v: &mut Vec<u8>, color: u8) {
|
||||
v.push(0x1B);
|
||||
v.push(b'[');
|
||||
v.push(1);
|
||||
v.push(b';');
|
||||
let s = color.to_string();
|
||||
let bytes = s.as_bytes();
|
||||
v.extend(bytes.iter().cloned());
|
||||
v.push(b'm');
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))]
|
||||
pub fn print_codes(colors: &HashMap<u32, u8>, names: &HashMap<u32, &str>) -> String {
|
||||
let mut v = Vec::new();
|
||||
for (code, &color) in colors {
|
||||
if let Some(&s) = names.get(code) {
|
||||
let bytes = s.as_bytes();
|
||||
write_color(&mut v, color);
|
||||
v.extend(bytes.iter().cloned());
|
||||
} else {
|
||||
let s = code.to_string();
|
||||
let bytes = s.as_bytes();
|
||||
write_color(&mut v, color);
|
||||
v.extend(bytes.iter().cloned());
|
||||
}
|
||||
reset_color(&mut v);
|
||||
v.push(b' ');
|
||||
}
|
||||
reset_color(&mut v);
|
||||
|
||||
String::from_utf8_lossy(&v[..]).into_owned()
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub fn print_offsets(input: &[u8], from: usize, offsets: &[(ErrorKind, usize, usize)]) -> String {
|
||||
let mut v = Vec::with_capacity(input.len() * 3);
|
||||
let mut i = from;
|
||||
let chunk_size = 8;
|
||||
let mut current_code: Option<u32> = None;
|
||||
let mut current_code2: Option<u32> = None;
|
||||
|
||||
let colors = generate_colors(&offsets);
|
||||
|
||||
for chunk in input.chunks(chunk_size) {
|
||||
let s = format!("{:08x}", i);
|
||||
for &ch in s.as_bytes().iter() {
|
||||
v.push(ch);
|
||||
}
|
||||
v.push(b'\t');
|
||||
|
||||
let mut k = i;
|
||||
let mut l = i;
|
||||
for &byte in chunk {
|
||||
if let Some(code) = code_from_offset(&offsets, k) {
|
||||
if let Some(current) = current_code {
|
||||
if current != code {
|
||||
reset_color(&mut v);
|
||||
current_code = Some(code);
|
||||
if let Some(&color) = colors.get(&code) {
|
||||
write_color(&mut v, color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current_code = Some(code);
|
||||
if let Some(&color) = colors.get(&code) {
|
||||
write_color(&mut v, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
v.push(CHARS[(byte >> 4) as usize]);
|
||||
v.push(CHARS[(byte & 0xf) as usize]);
|
||||
v.push(b' ');
|
||||
k = k + 1;
|
||||
}
|
||||
|
||||
reset_color(&mut v);
|
||||
|
||||
if chunk_size > chunk.len() {
|
||||
for _ in 0..(chunk_size - chunk.len()) {
|
||||
v.push(b' ');
|
||||
v.push(b' ');
|
||||
v.push(b' ');
|
||||
}
|
||||
}
|
||||
v.push(b'\t');
|
||||
|
||||
for &byte in chunk {
|
||||
if let Some(code) = code_from_offset(&offsets, l) {
|
||||
if let Some(current) = current_code2 {
|
||||
if current != code {
|
||||
reset_color(&mut v);
|
||||
current_code2 = Some(code);
|
||||
if let Some(&color) = colors.get(&code) {
|
||||
write_color(&mut v, color);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
current_code2 = Some(code);
|
||||
if let Some(&color) = colors.get(&code) {
|
||||
write_color(&mut v, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (byte >= 32 && byte <= 126) || byte >= 128 {
|
||||
v.push(byte);
|
||||
} else {
|
||||
v.push(b'.');
|
||||
}
|
||||
l = l + 1;
|
||||
}
|
||||
reset_color(&mut v);
|
||||
|
||||
v.push(b'\n');
|
||||
i = i + chunk_size;
|
||||
}
|
||||
|
||||
String::from_utf8_lossy(&v[..]).into_owned()
|
||||
}
|
||||
*/
|
||||
489
third-party/vendor/nom/src/internal.rs
vendored
Normal file
489
third-party/vendor/nom/src/internal.rs
vendored
Normal file
|
|
@ -0,0 +1,489 @@
|
|||
//! Basic types to build the parsers
|
||||
|
||||
use self::Needed::*;
|
||||
use crate::error::{self, ErrorKind};
|
||||
use crate::lib::std::fmt;
|
||||
use core::num::NonZeroUsize;
|
||||
|
||||
/// Holds the result of parsing functions
|
||||
///
|
||||
/// It depends on the input type `I`, the output type `O`, and the error type `E`
|
||||
/// (by default `(I, nom::ErrorKind)`)
|
||||
///
|
||||
/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
|
||||
/// was not parsed) and the produced value. The `Err` side contains an instance of `nom::Err`.
|
||||
///
|
||||
/// Outside of the parsing code, you can use the [Finish::finish] method to convert
|
||||
/// it to a more common result type
|
||||
pub type IResult<I, O, E = error::Error<I>> = Result<(I, O), Err<E>>;
|
||||
|
||||
/// Helper trait to convert a parser's result to a more manageable type
|
||||
pub trait Finish<I, O, E> {
|
||||
/// converts the parser's result to a type that is more consumable by error
|
||||
/// management libraries. It keeps the same `Ok` branch, and merges `Err::Error`
|
||||
/// and `Err::Failure` into the `Err` side.
|
||||
///
|
||||
/// *warning*: if the result is `Err(Err::Incomplete(_))`, this method will panic.
|
||||
/// - "complete" parsers: It will not be an issue, `Incomplete` is never used
|
||||
/// - "streaming" parsers: `Incomplete` will be returned if there's not enough data
|
||||
/// for the parser to decide, and you should gather more data before parsing again.
|
||||
/// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`,
|
||||
/// you can get out of the parsing loop and call `finish()` on the parser's result
|
||||
fn finish(self) -> Result<(I, O), E>;
|
||||
}
|
||||
|
||||
impl<I, O, E> Finish<I, O, E> for IResult<I, O, E> {
|
||||
fn finish(self) -> Result<(I, O), E> {
|
||||
match self {
|
||||
Ok(res) => Ok(res),
|
||||
Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
|
||||
Err(Err::Incomplete(_)) => {
|
||||
panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Contains information on needed data if a parser returned `Incomplete`
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub enum Needed {
|
||||
/// Needs more data, but we do not know how much
|
||||
Unknown,
|
||||
/// Contains the required data size in bytes
|
||||
Size(NonZeroUsize),
|
||||
}
|
||||
|
||||
impl Needed {
|
||||
/// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
|
||||
pub fn new(s: usize) -> Self {
|
||||
match NonZeroUsize::new(s) {
|
||||
Some(sz) => Needed::Size(sz),
|
||||
None => Needed::Unknown,
|
||||
}
|
||||
}
|
||||
|
||||
/// Indicates if we know how many bytes we need
|
||||
pub fn is_known(&self) -> bool {
|
||||
*self != Unknown
|
||||
}
|
||||
|
||||
/// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
|
||||
#[inline]
|
||||
pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
|
||||
match self {
|
||||
Unknown => Unknown,
|
||||
Size(n) => Needed::new(f(n)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The `Err` enum indicates the parser was not successful
|
||||
///
|
||||
/// It has three cases:
|
||||
///
|
||||
/// * `Incomplete` indicates that more data is needed to decide. The `Needed` enum
|
||||
/// can contain how many additional bytes are necessary. If you are sure your parser
|
||||
/// is working on full data, you can wrap your parser with the `complete` combinator
|
||||
/// to transform that case in `Error`
|
||||
/// * `Error` means some parser did not succeed, but another one might (as an example,
|
||||
/// when testing different branches of an `alt` combinator)
|
||||
/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
|
||||
/// to decide on the next parser to apply, and that parser fails, you know there's no need
|
||||
/// to try other parsers, you were already in the right branch, so the data is invalid
|
||||
///
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub enum Err<E> {
|
||||
/// There was not enough data
|
||||
Incomplete(Needed),
|
||||
/// The parser had an error (recoverable)
|
||||
Error(E),
|
||||
/// The parser had an unrecoverable error: we got to the right
|
||||
/// branch and we know other branches won't work, so backtrack
|
||||
/// as fast as possible
|
||||
Failure(E),
|
||||
}
|
||||
|
||||
impl<E> Err<E> {
|
||||
/// Tests if the result is Incomplete
|
||||
pub fn is_incomplete(&self) -> bool {
|
||||
if let Err::Incomplete(_) = self {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies the given function to the inner error
|
||||
pub fn map<E2, F>(self, f: F) -> Err<E2>
|
||||
where
|
||||
F: FnOnce(E) -> E2,
|
||||
{
|
||||
match self {
|
||||
Err::Incomplete(n) => Err::Incomplete(n),
|
||||
Err::Failure(t) => Err::Failure(f(t)),
|
||||
Err::Error(t) => Err::Error(f(t)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Automatically converts between errors if the underlying type supports it
|
||||
pub fn convert<F>(e: Err<F>) -> Self
|
||||
where
|
||||
E: From<F>,
|
||||
{
|
||||
e.map(crate::lib::std::convert::Into::into)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Err<(T, ErrorKind)> {
|
||||
/// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
|
||||
pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Err::Incomplete(n) => Err::Incomplete(n),
|
||||
Err::Failure((input, k)) => Err::Failure((f(input), k)),
|
||||
Err::Error((input, k)) => Err::Error((f(input), k)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Err<error::Error<T>> {
|
||||
/// Maps `Err<error::Error<T>>` to `Err<error::Error<U>>` with the given `F: T -> U`
|
||||
pub fn map_input<U, F>(self, f: F) -> Err<error::Error<U>>
|
||||
where
|
||||
F: FnOnce(T) -> U,
|
||||
{
|
||||
match self {
|
||||
Err::Incomplete(n) => Err::Incomplete(n),
|
||||
Err::Failure(error::Error { input, code }) => Err::Failure(error::Error {
|
||||
input: f(input),
|
||||
code,
|
||||
}),
|
||||
Err::Error(error::Error { input, code }) => Err::Error(error::Error {
|
||||
input: f(input),
|
||||
code,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec};
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Err<(&[u8], ErrorKind)> {
|
||||
/// Obtaining ownership
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
|
||||
self.map_input(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Err<(&str, ErrorKind)> {
|
||||
/// Obtaining ownership
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn to_owned(self) -> Err<(String, ErrorKind)> {
|
||||
self.map_input(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Err<error::Error<&[u8]>> {
|
||||
/// Obtaining ownership
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn to_owned(self) -> Err<error::Error<Vec<u8>>> {
|
||||
self.map_input(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl Err<error::Error<&str>> {
|
||||
/// Obtaining ownership
|
||||
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
|
||||
pub fn to_owned(self) -> Err<error::Error<String>> {
|
||||
self.map_input(ToOwned::to_owned)
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: Eq> Eq for Err<E> {}
|
||||
|
||||
impl<E> fmt::Display for Err<E>
|
||||
where
|
||||
E: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
|
||||
Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
|
||||
Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
|
||||
Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<E> Error for Err<E>
|
||||
where
|
||||
E: fmt::Debug,
|
||||
{
|
||||
fn source(&self) -> Option<&(dyn Error + 'static)> {
|
||||
None // no underlying error
|
||||
}
|
||||
}
|
||||
|
||||
/// All nom parsers implement this trait
|
||||
pub trait Parser<I, O, E> {
|
||||
/// A parser takes in input type, and returns a `Result` containing
|
||||
/// either the remaining input and the output value, or an error
|
||||
fn parse(&mut self, input: I) -> IResult<I, O, E>;
|
||||
|
||||
/// Maps a function over the result of a parser
|
||||
fn map<G, O2>(self, g: G) -> Map<Self, G, O>
|
||||
where
|
||||
G: Fn(O) -> O2,
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
Map {
|
||||
f: self,
|
||||
g,
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a second parser from the output of the first one, then apply over the rest of the input
|
||||
fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
|
||||
where
|
||||
G: FnMut(O) -> H,
|
||||
H: Parser<I, O2, E>,
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
FlatMap {
|
||||
f: self,
|
||||
g,
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a second parser over the output of the first one
|
||||
fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
|
||||
where
|
||||
G: Parser<O, O2, E>,
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
AndThen {
|
||||
f: self,
|
||||
g,
|
||||
phantom: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
/// Applies a second parser after the first one, return their results as a tuple
|
||||
fn and<G, O2>(self, g: G) -> And<Self, G>
|
||||
where
|
||||
G: Parser<I, O2, E>,
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
And { f: self, g }
|
||||
}
|
||||
|
||||
/// Applies a second parser over the input if the first one failed
|
||||
fn or<G>(self, g: G) -> Or<Self, G>
|
||||
where
|
||||
G: Parser<I, O, E>,
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
Or { f: self, g }
|
||||
}
|
||||
|
||||
/// automatically converts the parser's output and error values to another type, as long as they
|
||||
/// implement the `From` trait
|
||||
fn into<O2: From<O>, E2: From<E>>(self) -> Into<Self, O, O2, E, E2>
|
||||
where
|
||||
Self: core::marker::Sized,
|
||||
{
|
||||
Into {
|
||||
f: self,
|
||||
phantom_out1: core::marker::PhantomData,
|
||||
phantom_err1: core::marker::PhantomData,
|
||||
phantom_out2: core::marker::PhantomData,
|
||||
phantom_err2: core::marker::PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, I, O, E, F> Parser<I, O, E> for F
|
||||
where
|
||||
F: FnMut(I) -> IResult<I, O, E> + 'a,
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, O, E> {
|
||||
self(i)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
use alloc::boxed::Box;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
impl<'a, I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + 'a> {
|
||||
fn parse(&mut self, input: I) -> IResult<I, O, E> {
|
||||
(**self).parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::map`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct Map<F, G, O1> {
|
||||
f: F,
|
||||
g: G,
|
||||
phantom: core::marker::PhantomData<O1>,
|
||||
}
|
||||
|
||||
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
|
||||
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
|
||||
match self.f.parse(i) {
|
||||
Err(e) => Err(e),
|
||||
Ok((i, o)) => Ok((i, (self.g)(o))),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::flat_map`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct FlatMap<F, G, O1> {
|
||||
f: F,
|
||||
g: G,
|
||||
phantom: core::marker::PhantomData<O1>,
|
||||
}
|
||||
|
||||
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
|
||||
for FlatMap<F, G, O1>
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
|
||||
let (i, o1) = self.f.parse(i)?;
|
||||
(self.g)(o1).parse(i)
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::and_then`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct AndThen<F, G, O1> {
|
||||
f: F,
|
||||
g: G,
|
||||
phantom: core::marker::PhantomData<O1>,
|
||||
}
|
||||
|
||||
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
|
||||
for AndThen<F, G, O1>
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, O2, E> {
|
||||
let (i, o1) = self.f.parse(i)?;
|
||||
let (_, o2) = self.g.parse(o1)?;
|
||||
Ok((i, o2))
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::and`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct And<F, G> {
|
||||
f: F,
|
||||
g: G,
|
||||
}
|
||||
|
||||
impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
|
||||
for And<F, G>
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
|
||||
let (i, o1) = self.f.parse(i)?;
|
||||
let (i, o2) = self.g.parse(i)?;
|
||||
Ok((i, (o1, o2)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::or`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct Or<F, G> {
|
||||
f: F,
|
||||
g: G,
|
||||
}
|
||||
|
||||
impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
|
||||
Parser<I, O, E> for Or<F, G>
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, O, E> {
|
||||
match self.f.parse(i.clone()) {
|
||||
Err(Err::Error(e1)) => match self.g.parse(i) {
|
||||
Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
|
||||
res => res,
|
||||
},
|
||||
res => res,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of `Parser::into`
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
pub struct Into<F, O1, O2: From<O1>, E1, E2: From<E1>> {
|
||||
f: F,
|
||||
phantom_out1: core::marker::PhantomData<O1>,
|
||||
phantom_err1: core::marker::PhantomData<E1>,
|
||||
phantom_out2: core::marker::PhantomData<O2>,
|
||||
phantom_err2: core::marker::PhantomData<E2>,
|
||||
}
|
||||
|
||||
impl<
|
||||
'a,
|
||||
I: Clone,
|
||||
O1,
|
||||
O2: From<O1>,
|
||||
E1,
|
||||
E2: crate::error::ParseError<I> + From<E1>,
|
||||
F: Parser<I, O1, E1>,
|
||||
> Parser<I, O2, E2> for Into<F, O1, O2, E1, E2>
|
||||
{
|
||||
fn parse(&mut self, i: I) -> IResult<I, O2, E2> {
|
||||
match self.f.parse(i) {
|
||||
Ok((i, o)) => Ok((i, o.into())),
|
||||
Err(Err::Error(e)) => Err(Err::Error(e.into())),
|
||||
Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
|
||||
Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::error::ErrorKind;
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
macro_rules! assert_size (
|
||||
($t:ty, $sz:expr) => (
|
||||
assert_eq!(crate::lib::std::mem::size_of::<$t>(), $sz);
|
||||
);
|
||||
);
|
||||
|
||||
#[test]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
fn size_test() {
|
||||
assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
|
||||
//FIXME: since rust 1.65, this is now 32 bytes, likely thanks to https://github.com/rust-lang/rust/pull/94075
|
||||
// deactivating that test for now because it'll have different values depending on the rust version
|
||||
// assert_size!(IResult<&str, &str, u32>, 40);
|
||||
assert_size!(Needed, 8);
|
||||
assert_size!(Err<u32>, 16);
|
||||
assert_size!(ErrorKind, 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn err_map_test() {
|
||||
let e = Err::Error(1);
|
||||
assert_eq!(e.map(|v| v + 1), Err::Error(2));
|
||||
}
|
||||
}
|
||||
464
third-party/vendor/nom/src/lib.rs
vendored
Normal file
464
third-party/vendor/nom/src/lib.rs
vendored
Normal file
|
|
@ -0,0 +1,464 @@
|
|||
//! # nom, eating data byte by byte
|
||||
//!
|
||||
//! nom is a parser combinator library with a focus on safe parsing,
|
||||
//! streaming patterns, and as much as possible zero copy.
|
||||
//!
|
||||
//! ## Example
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{
|
||||
//! IResult,
|
||||
//! bytes::complete::{tag, take_while_m_n},
|
||||
//! combinator::map_res,
|
||||
//! sequence::tuple};
|
||||
//!
|
||||
//! #[derive(Debug,PartialEq)]
|
||||
//! pub struct Color {
|
||||
//! pub red: u8,
|
||||
//! pub green: u8,
|
||||
//! pub blue: u8,
|
||||
//! }
|
||||
//!
|
||||
//! fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
|
||||
//! u8::from_str_radix(input, 16)
|
||||
//! }
|
||||
//!
|
||||
//! fn is_hex_digit(c: char) -> bool {
|
||||
//! c.is_digit(16)
|
||||
//! }
|
||||
//!
|
||||
//! fn hex_primary(input: &str) -> IResult<&str, u8> {
|
||||
//! map_res(
|
||||
//! take_while_m_n(2, 2, is_hex_digit),
|
||||
//! from_hex
|
||||
//! )(input)
|
||||
//! }
|
||||
//!
|
||||
//! fn hex_color(input: &str) -> IResult<&str, Color> {
|
||||
//! let (input, _) = tag("#")(input)?;
|
||||
//! let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?;
|
||||
//!
|
||||
//! Ok((input, Color { red, green, blue }))
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! assert_eq!(hex_color("#2F14DF"), Ok(("", Color {
|
||||
//! red: 47,
|
||||
//! green: 20,
|
||||
//! blue: 223,
|
||||
//! })));
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! The code is available on [Github](https://github.com/Geal/nom)
|
||||
//!
|
||||
//! There are a few [guides](https://github.com/Geal/nom/tree/main/doc) with more details
|
||||
//! about [how to write parsers](https://github.com/Geal/nom/blob/main/doc/making_a_new_parser_from_scratch.md),
|
||||
//! or the [error management system](https://github.com/Geal/nom/blob/main/doc/error_management.md).
|
||||
//! You can also check out the [recipes] module that contains examples of common patterns.
|
||||
//!
|
||||
//! **Looking for a specific combinator? Read the
|
||||
//! ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md)**
|
||||
//!
|
||||
//! If you are upgrading to nom 5.0, please read the
|
||||
//! [migration document](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_5.md).
|
||||
//!
|
||||
//! ## Parser combinators
|
||||
//!
|
||||
//! Parser combinators are an approach to parsers that is very different from
|
||||
//! software like [lex](https://en.wikipedia.org/wiki/Lex_(software)) and
|
||||
//! [yacc](https://en.wikipedia.org/wiki/Yacc). Instead of writing the grammar
|
||||
//! in a separate syntax and generating the corresponding code, you use very small
|
||||
//! functions with very specific purposes, like "take 5 bytes", or "recognize the
|
||||
//! word 'HTTP'", and assemble them in meaningful patterns like "recognize
|
||||
//! 'HTTP', then a space, then a version".
|
||||
//! The resulting code is small, and looks like the grammar you would have
|
||||
//! written with other parser approaches.
|
||||
//!
|
||||
//! This gives us a few advantages:
|
||||
//!
|
||||
//! - The parsers are small and easy to write
|
||||
//! - The parsers components are easy to reuse (if they're general enough, please add them to nom!)
|
||||
//! - The parsers components are easy to test separately (unit tests and property-based tests)
|
||||
//! - The parser combination code looks close to the grammar you would have written
|
||||
//! - You can build partial parsers, specific to the data you need at the moment, and ignore the rest
|
||||
//!
|
||||
//! Here is an example of one such parser, to recognize text between parentheses:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{
|
||||
//! IResult,
|
||||
//! sequence::delimited,
|
||||
//! // see the "streaming/complete" paragraph lower for an explanation of these submodules
|
||||
//! character::complete::char,
|
||||
//! bytes::complete::is_not
|
||||
//! };
|
||||
//!
|
||||
//! fn parens(input: &str) -> IResult<&str, &str> {
|
||||
//! delimited(char('('), is_not(")"), char(')'))(input)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! It defines a function named `parens` which will recognize a sequence of the
|
||||
//! character `(`, the longest byte array not containing `)`, then the character
|
||||
//! `)`, and will return the byte array in the middle.
|
||||
//!
|
||||
//! Here is another parser, written without using nom's combinators this time:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{IResult, Err, Needed};
|
||||
//!
|
||||
//! # fn main() {
|
||||
//! fn take4(i: &[u8]) -> IResult<&[u8], &[u8]>{
|
||||
//! if i.len() < 4 {
|
||||
//! Err(Err::Incomplete(Needed::new(4)))
|
||||
//! } else {
|
||||
//! Ok((&i[4..], &i[0..4]))
|
||||
//! }
|
||||
//! }
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! This function takes a byte array as input, and tries to consume 4 bytes.
|
||||
//! Writing all the parsers manually, like this, is dangerous, despite Rust's
|
||||
//! safety features. There are still a lot of mistakes one can make. That's why
|
||||
//! nom provides a list of functions to help in developing parsers.
|
||||
//!
|
||||
//! With functions, you would write it like this:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{IResult, bytes::streaming::take};
|
||||
//! fn take4(input: &str) -> IResult<&str, &str> {
|
||||
//! take(4u8)(input)
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! A parser in nom is a function which, for an input type `I`, an output type `O`
|
||||
//! and an optional error type `E`, will have the following signature:
|
||||
//!
|
||||
//! ```rust,compile_fail
|
||||
//! fn parser(input: I) -> IResult<I, O, E>;
|
||||
//! ```
|
||||
//!
|
||||
//! Or like this, if you don't want to specify a custom error type (it will be `(I, ErrorKind)` by default):
|
||||
//!
|
||||
//! ```rust,compile_fail
|
||||
//! fn parser(input: I) -> IResult<I, O>;
|
||||
//! ```
|
||||
//!
|
||||
//! `IResult` is an alias for the `Result` type:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{Needed, error::Error};
|
||||
//!
|
||||
//! type IResult<I, O, E = Error<I>> = Result<(I, O), Err<E>>;
|
||||
//!
|
||||
//! enum Err<E> {
|
||||
//! Incomplete(Needed),
|
||||
//! Error(E),
|
||||
//! Failure(E),
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! It can have the following values:
|
||||
//!
|
||||
//! - A correct result `Ok((I,O))` with the first element being the remaining of the input (not parsed yet), and the second the output value;
|
||||
//! - An error `Err(Err::Error(c))` with `c` an error that can be built from the input position and a parser specific error
|
||||
//! - An error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed
|
||||
//! - An error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: We cannot backtrack and test another parser
|
||||
//!
|
||||
//! Please refer to the ["choose a combinator" guide](https://github.com/Geal/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers.
|
||||
//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/main/doc).
|
||||
//!
|
||||
//! ## Making new parsers with function combinators
|
||||
//!
|
||||
//! nom is based on functions that generate parsers, with a signature like
|
||||
//! this: `(arguments) -> impl Fn(Input) -> IResult<Input, Output, Error>`.
|
||||
//! The arguments of a combinator can be direct values (like `take` which uses
|
||||
//! a number of bytes or character as argument) or even other parsers (like
|
||||
//! `delimited` which takes as argument 3 parsers, and returns the result of
|
||||
//! the second one if all are successful).
|
||||
//!
|
||||
//! Here are some examples:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::IResult;
|
||||
//! use nom::bytes::complete::{tag, take};
|
||||
//! fn abcd_parser(i: &str) -> IResult<&str, &str> {
|
||||
//! tag("abcd")(i) // will consume bytes if the input begins with "abcd"
|
||||
//! }
|
||||
//!
|
||||
//! fn take_10(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
//! take(10u8)(i) // will consume and return 10 bytes of input
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Combining parsers
|
||||
//!
|
||||
//! There are higher level patterns, like the **`alt`** combinator, which
|
||||
//! provides a choice between multiple parsers. If one branch fails, it tries
|
||||
//! the next, and returns the result of the first parser that succeeds:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::IResult;
|
||||
//! use nom::branch::alt;
|
||||
//! use nom::bytes::complete::tag;
|
||||
//!
|
||||
//! let mut alt_tags = alt((tag("abcd"), tag("efgh")));
|
||||
//!
|
||||
//! assert_eq!(alt_tags(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..])));
|
||||
//! assert_eq!(alt_tags(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..])));
|
||||
//! assert_eq!(alt_tags(&b"ijklxxx"[..]), Err(nom::Err::Error((&b"ijklxxx"[..], nom::error::ErrorKind::Tag))));
|
||||
//! ```
|
||||
//!
|
||||
//! The **`opt`** combinator makes a parser optional. If the child parser returns
|
||||
//! an error, **`opt`** will still succeed and return None:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{IResult, combinator::opt, bytes::complete::tag};
|
||||
//! fn abcd_opt(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> {
|
||||
//! opt(tag("abcd"))(i)
|
||||
//! }
|
||||
//!
|
||||
//! assert_eq!(abcd_opt(&b"abcdxxx"[..]), Ok((&b"xxx"[..], Some(&b"abcd"[..]))));
|
||||
//! assert_eq!(abcd_opt(&b"efghxxx"[..]), Ok((&b"efghxxx"[..], None)));
|
||||
//! ```
|
||||
//!
|
||||
//! **`many0`** applies a parser 0 or more times, and returns a vector of the aggregated results:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # #[cfg(feature = "alloc")]
|
||||
//! # fn main() {
|
||||
//! use nom::{IResult, multi::many0, bytes::complete::tag};
|
||||
//! use std::str;
|
||||
//!
|
||||
//! fn multi(i: &str) -> IResult<&str, Vec<&str>> {
|
||||
//! many0(tag("abcd"))(i)
|
||||
//! }
|
||||
//!
|
||||
//! let a = "abcdef";
|
||||
//! let b = "abcdabcdef";
|
||||
//! let c = "azerty";
|
||||
//! assert_eq!(multi(a), Ok(("ef", vec!["abcd"])));
|
||||
//! assert_eq!(multi(b), Ok(("ef", vec!["abcd", "abcd"])));
|
||||
//! assert_eq!(multi(c), Ok(("azerty", Vec::new())));
|
||||
//! # }
|
||||
//! # #[cfg(not(feature = "alloc"))]
|
||||
//! # fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! Here are some basic combinators available:
|
||||
//!
|
||||
//! - **`opt`**: Will make the parser optional (if it returns the `O` type, the new parser returns `Option<O>`)
|
||||
//! - **`many0`**: Will apply the parser 0 or more times (if it returns the `O` type, the new parser returns `Vec<O>`)
|
||||
//! - **`many1`**: Will apply the parser 1 or more times
|
||||
//!
|
||||
//! There are more complex (and more useful) parsers like `tuple`, which is
|
||||
//! used to apply a series of parsers then assemble their results.
|
||||
//!
|
||||
//! Example with `tuple`:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! use nom::{error::ErrorKind, Needed,
|
||||
//! number::streaming::be_u16,
|
||||
//! bytes::streaming::{tag, take},
|
||||
//! sequence::tuple};
|
||||
//!
|
||||
//! let mut tpl = tuple((be_u16, take(3u8), tag("fg")));
|
||||
//!
|
||||
//! assert_eq!(
|
||||
//! tpl(&b"abcdefgh"[..]),
|
||||
//! Ok((
|
||||
//! &b"h"[..],
|
||||
//! (0x6162u16, &b"cde"[..], &b"fg"[..])
|
||||
//! ))
|
||||
//! );
|
||||
//! assert_eq!(tpl(&b"abcde"[..]), Err(nom::Err::Incomplete(Needed::new(2))));
|
||||
//! let input = &b"abcdejk"[..];
|
||||
//! assert_eq!(tpl(input), Err(nom::Err::Error((&input[5..], ErrorKind::Tag))));
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! But you can also use a sequence of combinators written in imperative style,
|
||||
//! thanks to the `?` operator:
|
||||
//!
|
||||
//! ```rust
|
||||
//! # fn main() {
|
||||
//! use nom::{IResult, bytes::complete::tag};
|
||||
//!
|
||||
//! #[derive(Debug, PartialEq)]
|
||||
//! struct A {
|
||||
//! a: u8,
|
||||
//! b: u8
|
||||
//! }
|
||||
//!
|
||||
//! fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,1)) }
|
||||
//! fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,2)) }
|
||||
//!
|
||||
//! fn f(i: &[u8]) -> IResult<&[u8], A> {
|
||||
//! // if successful, the parser returns `Ok((remaining_input, output_value))` that we can destructure
|
||||
//! let (i, _) = tag("abcd")(i)?;
|
||||
//! let (i, a) = ret_int1(i)?;
|
||||
//! let (i, _) = tag("efgh")(i)?;
|
||||
//! let (i, b) = ret_int2(i)?;
|
||||
//!
|
||||
//! Ok((i, A { a, b }))
|
||||
//! }
|
||||
//!
|
||||
//! let r = f(b"abcdefghX");
|
||||
//! assert_eq!(r, Ok((&b"X"[..], A{a: 1, b: 2})));
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Streaming / Complete
|
||||
//!
|
||||
//! Some of nom's modules have `streaming` or `complete` submodules. They hold
|
||||
//! different variants of the same combinators.
|
||||
//!
|
||||
//! A streaming parser assumes that we might not have all of the input data.
|
||||
//! This can happen with some network protocol or large file parsers, where the
|
||||
//! input buffer can be full and need to be resized or refilled.
|
||||
//!
|
||||
//! A complete parser assumes that we already have all of the input data.
|
||||
//! This will be the common case with small files that can be read entirely to
|
||||
//! memory.
|
||||
//!
|
||||
//! Here is how it works in practice:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use nom::{IResult, Err, Needed, error::{Error, ErrorKind}, bytes, character};
|
||||
//!
|
||||
//! fn take_streaming(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
//! bytes::streaming::take(4u8)(i)
|
||||
//! }
|
||||
//!
|
||||
//! fn take_complete(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
//! bytes::complete::take(4u8)(i)
|
||||
//! }
|
||||
//!
|
||||
//! // both parsers will take 4 bytes as expected
|
||||
//! assert_eq!(take_streaming(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..])));
|
||||
//! assert_eq!(take_complete(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..])));
|
||||
//!
|
||||
//! // if the input is smaller than 4 bytes, the streaming parser
|
||||
//! // will return `Incomplete` to indicate that we need more data
|
||||
//! assert_eq!(take_streaming(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
//!
|
||||
//! // but the complete parser will return an error
|
||||
//! assert_eq!(take_complete(&b"abc"[..]), Err(Err::Error(Error::new(&b"abc"[..], ErrorKind::Eof))));
|
||||
//!
|
||||
//! // the alpha0 function recognizes 0 or more alphabetic characters
|
||||
//! fn alpha0_streaming(i: &str) -> IResult<&str, &str> {
|
||||
//! character::streaming::alpha0(i)
|
||||
//! }
|
||||
//!
|
||||
//! fn alpha0_complete(i: &str) -> IResult<&str, &str> {
|
||||
//! character::complete::alpha0(i)
|
||||
//! }
|
||||
//!
|
||||
//! // if there's a clear limit to the recognized characters, both parsers work the same way
|
||||
//! assert_eq!(alpha0_streaming("abcd;"), Ok((";", "abcd")));
|
||||
//! assert_eq!(alpha0_complete("abcd;"), Ok((";", "abcd")));
|
||||
//!
|
||||
//! // but when there's no limit, the streaming version returns `Incomplete`, because it cannot
|
||||
//! // know if more input data should be recognized. The whole input could be "abcd;", or
|
||||
//! // "abcde;"
|
||||
//! assert_eq!(alpha0_streaming("abcd"), Err(Err::Incomplete(Needed::new(1))));
|
||||
//!
|
||||
//! // while the complete version knows that all of the data is there
|
||||
//! assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd")));
|
||||
//! ```
|
||||
//! **Going further:** Read the [guides](https://github.com/Geal/nom/tree/main/doc),
|
||||
//! check out the [recipes]!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(clippy::doc_markdown))]
|
||||
#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
|
||||
#![cfg_attr(feature = "docsrs", feature(extended_key_value_attributes))]
|
||||
#![deny(missing_docs)]
|
||||
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
|
||||
#[cfg(feature = "alloc")]
|
||||
#[macro_use]
|
||||
extern crate alloc;
|
||||
#[cfg(doctest)]
|
||||
extern crate doc_comment;
|
||||
|
||||
#[cfg(doctest)]
|
||||
doc_comment::doctest!("../README.md");
|
||||
|
||||
/// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does
|
||||
/// it, albeit there it is not public.
|
||||
#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
|
||||
pub mod lib {
|
||||
/// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally,
|
||||
/// as well as `core` or `std`
|
||||
#[cfg(not(feature = "std"))]
|
||||
#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
|
||||
/// internal std exports for no_std compatibility
|
||||
pub mod std {
|
||||
#[doc(hidden)]
|
||||
#[cfg(not(feature = "alloc"))]
|
||||
pub use core::borrow;
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[doc(hidden)]
|
||||
pub use alloc::{borrow, boxed, string, vec};
|
||||
|
||||
#[doc(hidden)]
|
||||
pub use core::{cmp, convert, fmt, iter, mem, ops, option, result, slice, str};
|
||||
|
||||
/// internal reproduction of std prelude
|
||||
#[doc(hidden)]
|
||||
pub mod prelude {
|
||||
pub use core::prelude as v1;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
|
||||
/// internal std exports for no_std compatibility
|
||||
pub mod std {
|
||||
#[doc(hidden)]
|
||||
pub use std::{
|
||||
alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, result,
|
||||
slice, str, string, vec,
|
||||
};
|
||||
|
||||
/// internal reproduction of std prelude
|
||||
#[doc(hidden)]
|
||||
pub mod prelude {
|
||||
pub use std::prelude as v1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub use self::bits::*;
|
||||
pub use self::internal::*;
|
||||
pub use self::traits::*;
|
||||
|
||||
pub use self::str::*;
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
#[macro_use]
|
||||
pub mod error;
|
||||
|
||||
pub mod branch;
|
||||
pub mod combinator;
|
||||
mod internal;
|
||||
pub mod multi;
|
||||
pub mod sequence;
|
||||
mod traits;
|
||||
|
||||
pub mod bits;
|
||||
pub mod bytes;
|
||||
|
||||
pub mod character;
|
||||
|
||||
mod str;
|
||||
|
||||
pub mod number;
|
||||
|
||||
#[cfg(feature = "docsrs")]
|
||||
#[cfg_attr(feature = "docsrs", cfg_attr(feature = "docsrs", doc = include_str!("../doc/nom_recipes.md")))]
|
||||
pub mod recipes {}
|
||||
23
third-party/vendor/nom/src/macros.rs
vendored
Normal file
23
third-party/vendor/nom/src/macros.rs
vendored
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
macro_rules! succ (
|
||||
(0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
|
||||
(1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
|
||||
(2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
|
||||
(3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
|
||||
(4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
|
||||
(5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
|
||||
(6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
|
||||
(7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
|
||||
(8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
|
||||
(9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
|
||||
(10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
|
||||
(11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
|
||||
(12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
|
||||
(13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
|
||||
(14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
|
||||
(15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
|
||||
(16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
|
||||
(17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
|
||||
(18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
|
||||
(19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
|
||||
(20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
|
||||
);
|
||||
1049
third-party/vendor/nom/src/multi/mod.rs
vendored
Normal file
1049
third-party/vendor/nom/src/multi/mod.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
534
third-party/vendor/nom/src/multi/tests.rs
vendored
Normal file
534
third-party/vendor/nom/src/multi/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
use super::{length_data, length_value, many0_count, many1_count};
|
||||
use crate::{
|
||||
bytes::streaming::tag,
|
||||
character::streaming::digit1 as digit,
|
||||
error::{ErrorKind, ParseError},
|
||||
internal::{Err, IResult, Needed},
|
||||
lib::std::str::{self, FromStr},
|
||||
number::streaming::{be_u16, be_u8},
|
||||
sequence::{pair, tuple},
|
||||
};
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::{
|
||||
lib::std::vec::Vec,
|
||||
multi::{
|
||||
count, fold_many0, fold_many1, fold_many_m_n, length_count, many0, many1, many_m_n, many_till,
|
||||
separated_list0, separated_list1,
|
||||
},
|
||||
};
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn separated_list0_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list0(tag(","), tag("abcd"))(i)
|
||||
}
|
||||
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list0(tag(","), tag(""))(i)
|
||||
}
|
||||
fn empty_sep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list0(tag(""), tag("abc"))(i)
|
||||
}
|
||||
fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list0(tag(".."), tag("abcd"))(i)
|
||||
}
|
||||
|
||||
let a = &b"abcdef"[..];
|
||||
let b = &b"abcd,abcdef"[..];
|
||||
let c = &b"azerty"[..];
|
||||
let d = &b",,abc"[..];
|
||||
let e = &b"abcd,abcd,ef"[..];
|
||||
let f = &b"abc"[..];
|
||||
let g = &b"abcd."[..];
|
||||
let h = &b"abcd,abc"[..];
|
||||
let i = &b"abcabc"[..];
|
||||
|
||||
let res1 = vec![&b"abcd"[..]];
|
||||
assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
|
||||
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
|
||||
assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new())));
|
||||
let res3 = vec![&b""[..], &b""[..], &b""[..]];
|
||||
assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3)));
|
||||
let i_err_pos = &i[3..];
|
||||
assert_eq!(
|
||||
empty_sep(i),
|
||||
Err(Err::Error(error_position!(
|
||||
i_err_pos,
|
||||
ErrorKind::SeparatedList
|
||||
)))
|
||||
);
|
||||
let res4 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(e), Ok((&b",ef"[..], res4)));
|
||||
|
||||
assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn separated_list1_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list1(tag(","), tag("abcd"))(i)
|
||||
}
|
||||
fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
separated_list1(tag(".."), tag("abcd"))(i)
|
||||
}
|
||||
|
||||
let a = &b"abcdef"[..];
|
||||
let b = &b"abcd,abcdef"[..];
|
||||
let c = &b"azerty"[..];
|
||||
let d = &b"abcd,abcd,ef"[..];
|
||||
|
||||
let f = &b"abc"[..];
|
||||
let g = &b"abcd."[..];
|
||||
let h = &b"abcd,abc"[..];
|
||||
|
||||
let res1 = vec![&b"abcd"[..]];
|
||||
assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
|
||||
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
|
||||
assert_eq!(
|
||||
multi(c),
|
||||
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
|
||||
);
|
||||
let res3 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(d), Ok((&b",ef"[..], res3)));
|
||||
|
||||
assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn many0_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many0(tag("abcd"))(i)
|
||||
}
|
||||
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many0(tag(""))(i)
|
||||
}
|
||||
|
||||
assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
|
||||
assert_eq!(
|
||||
multi(&b"abcdabcdefgh"[..]),
|
||||
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
|
||||
);
|
||||
assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
|
||||
assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
|
||||
assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
|
||||
assert_eq!(
|
||||
multi_empty(&b"abcdef"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"abcdef"[..],
|
||||
ErrorKind::Many0
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn many1_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many1(tag("abcd"))(i)
|
||||
}
|
||||
|
||||
let a = &b"abcdef"[..];
|
||||
let b = &b"abcdabcdefgh"[..];
|
||||
let c = &b"azerty"[..];
|
||||
let d = &b"abcdab"[..];
|
||||
|
||||
let res1 = vec![&b"abcd"[..]];
|
||||
assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
|
||||
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
|
||||
assert_eq!(
|
||||
multi(c),
|
||||
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn many_till_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
|
||||
many_till(tag("abcd"), tag("efgh"))(i)
|
||||
}
|
||||
|
||||
let a = b"abcdabcdefghabcd";
|
||||
let b = b"efghabcd";
|
||||
let c = b"azerty";
|
||||
|
||||
let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]);
|
||||
let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]);
|
||||
assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a)));
|
||||
assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b)));
|
||||
assert_eq!(
|
||||
multi(&c[..]),
|
||||
Err(Err::Error(error_node_position!(
|
||||
&c[..],
|
||||
ErrorKind::ManyTill,
|
||||
error_position!(&c[..], ErrorKind::Tag)
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "std")]
|
||||
fn infinite_many() {
|
||||
fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
println!("input: {:?}", input);
|
||||
Err(Err::Error(error_position!(input, ErrorKind::Tag)))
|
||||
}
|
||||
|
||||
// should not go into an infinite loop
|
||||
fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many0(tst)(i)
|
||||
}
|
||||
let a = &b"abcdef"[..];
|
||||
assert_eq!(multi0(a), Ok((a, Vec::new())));
|
||||
|
||||
fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many1(tst)(i)
|
||||
}
|
||||
let a = &b"abcdef"[..];
|
||||
assert_eq!(
|
||||
multi1(a),
|
||||
Err(Err::Error(error_position!(a, ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn many_m_n_test() {
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
many_m_n(2, 4, tag("Abcd"))(i)
|
||||
}
|
||||
|
||||
let a = &b"Abcdef"[..];
|
||||
let b = &b"AbcdAbcdefgh"[..];
|
||||
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
|
||||
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
|
||||
let e = &b"AbcdAb"[..];
|
||||
|
||||
assert_eq!(
|
||||
multi(a),
|
||||
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
|
||||
);
|
||||
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
|
||||
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
|
||||
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
|
||||
assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn count_test() {
|
||||
const TIMES: usize = 2;
|
||||
fn cnt_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
count(tag("abc"), TIMES)(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
cnt_2(&b"abcabcabcdef"[..]),
|
||||
Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
|
||||
);
|
||||
assert_eq!(cnt_2(&b"ab"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(cnt_2(&b"abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(
|
||||
cnt_2(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
cnt_2(&b"xxxabcabcdef"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"xxxabcabcdef"[..],
|
||||
ErrorKind::Tag
|
||||
)))
|
||||
);
|
||||
assert_eq!(
|
||||
cnt_2(&b"abcxxxabcdef"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"xxxabcdef"[..],
|
||||
ErrorKind::Tag
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn count_zero() {
|
||||
const TIMES: usize = 0;
|
||||
fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
count(tag("abc"), TIMES)(i)
|
||||
}
|
||||
|
||||
let done = &b"abcabcabcdef"[..];
|
||||
let parsed_done = Vec::new();
|
||||
let rest = done;
|
||||
let incomplete_1 = &b"ab"[..];
|
||||
let parsed_incompl_1 = Vec::new();
|
||||
let incomplete_2 = &b"abcab"[..];
|
||||
let parsed_incompl_2 = Vec::new();
|
||||
let error = &b"xxx"[..];
|
||||
let error_remain = &b"xxx"[..];
|
||||
let parsed_err = Vec::new();
|
||||
let error_1 = &b"xxxabcabcdef"[..];
|
||||
let parsed_err_1 = Vec::new();
|
||||
let error_1_remain = &b"xxxabcabcdef"[..];
|
||||
let error_2 = &b"abcxxxabcdef"[..];
|
||||
let parsed_err_2 = Vec::new();
|
||||
let error_2_remain = &b"abcxxxabcdef"[..];
|
||||
|
||||
assert_eq!(counter_2(done), Ok((rest, parsed_done)));
|
||||
assert_eq!(
|
||||
counter_2(incomplete_1),
|
||||
Ok((incomplete_1, parsed_incompl_1))
|
||||
);
|
||||
assert_eq!(
|
||||
counter_2(incomplete_2),
|
||||
Ok((incomplete_2, parsed_incompl_2))
|
||||
);
|
||||
assert_eq!(counter_2(error), Ok((error_remain, parsed_err)));
|
||||
assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1)));
|
||||
assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2)));
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct NilError;
|
||||
|
||||
impl<I> From<(I, ErrorKind)> for NilError {
|
||||
fn from(_: (I, ErrorKind)) -> Self {
|
||||
NilError
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> ParseError<I> for NilError {
|
||||
fn from_error_kind(_: I, _: ErrorKind) -> NilError {
|
||||
NilError
|
||||
}
|
||||
fn append(_: I, _: ErrorKind, _: NilError) -> NilError {
|
||||
NilError
|
||||
}
|
||||
}
|
||||
|
||||
fn number(i: &[u8]) -> IResult<&[u8], u32> {
|
||||
use crate::combinator::map_res;
|
||||
|
||||
map_res(map_res(digit, str::from_utf8), FromStr::from_str)(i)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn length_count_test() {
|
||||
fn cnt(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
length_count(number, tag("abc"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
cnt(&b"2abcabcabcdef"[..]),
|
||||
Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
|
||||
);
|
||||
assert_eq!(cnt(&b"2ab"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(cnt(&b"3abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(
|
||||
cnt(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
|
||||
);
|
||||
assert_eq!(
|
||||
cnt(&b"2abcxxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn length_data_test() {
|
||||
fn take(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
length_data(number)(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
take(&b"6abcabcabcdef"[..]),
|
||||
Ok((&b"abcdef"[..], &b"abcabc"[..]))
|
||||
);
|
||||
assert_eq!(take(&b"3ab"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(
|
||||
take(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
|
||||
);
|
||||
assert_eq!(take(&b"2abcxxx"[..]), Ok((&b"cxxx"[..], &b"ab"[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn length_value_test() {
|
||||
fn length_value_1(i: &[u8]) -> IResult<&[u8], u16> {
|
||||
length_value(be_u8, be_u16)(i)
|
||||
}
|
||||
fn length_value_2(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
|
||||
length_value(be_u8, tuple((be_u8, be_u8)))(i)
|
||||
}
|
||||
|
||||
let i1 = [0, 5, 6];
|
||||
assert_eq!(
|
||||
length_value_1(&i1),
|
||||
Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
|
||||
);
|
||||
assert_eq!(
|
||||
length_value_2(&i1),
|
||||
Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
|
||||
);
|
||||
|
||||
let i2 = [1, 5, 6, 3];
|
||||
assert_eq!(
|
||||
length_value_1(&i2),
|
||||
Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
|
||||
);
|
||||
assert_eq!(
|
||||
length_value_2(&i2),
|
||||
Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
|
||||
);
|
||||
|
||||
let i3 = [2, 5, 6, 3, 4, 5, 7];
|
||||
assert_eq!(length_value_1(&i3), Ok((&i3[3..], 1286)));
|
||||
assert_eq!(length_value_2(&i3), Ok((&i3[3..], (5, 6))));
|
||||
|
||||
let i4 = [3, 5, 6, 3, 4, 5];
|
||||
assert_eq!(length_value_1(&i4), Ok((&i4[4..], 1286)));
|
||||
assert_eq!(length_value_2(&i4), Ok((&i4[4..], (5, 6))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn fold_many0_test() {
|
||||
fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
|
||||
acc.push(item);
|
||||
acc
|
||||
}
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i)
|
||||
}
|
||||
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
fold_many0(tag(""), Vec::new, fold_into_vec)(i)
|
||||
}
|
||||
|
||||
assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
|
||||
assert_eq!(
|
||||
multi(&b"abcdabcdefgh"[..]),
|
||||
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
|
||||
);
|
||||
assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
|
||||
assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
|
||||
assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
|
||||
assert_eq!(
|
||||
multi_empty(&b"abcdef"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"abcdef"[..],
|
||||
ErrorKind::Many0
|
||||
)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn fold_many1_test() {
|
||||
fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
|
||||
acc.push(item);
|
||||
acc
|
||||
}
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i)
|
||||
}
|
||||
|
||||
let a = &b"abcdef"[..];
|
||||
let b = &b"abcdabcdefgh"[..];
|
||||
let c = &b"azerty"[..];
|
||||
let d = &b"abcdab"[..];
|
||||
|
||||
let res1 = vec![&b"abcd"[..]];
|
||||
assert_eq!(multi(a), Ok((&b"ef"[..], res1)));
|
||||
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
|
||||
assert_eq!(
|
||||
multi(c),
|
||||
Err(Err::Error(error_position!(c, ErrorKind::Many1)))
|
||||
);
|
||||
assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn fold_many_m_n_test() {
|
||||
fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
|
||||
acc.push(item);
|
||||
acc
|
||||
}
|
||||
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
|
||||
fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i)
|
||||
}
|
||||
|
||||
let a = &b"Abcdef"[..];
|
||||
let b = &b"AbcdAbcdefgh"[..];
|
||||
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
|
||||
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
|
||||
let e = &b"AbcdAb"[..];
|
||||
|
||||
assert_eq!(
|
||||
multi(a),
|
||||
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
|
||||
);
|
||||
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
|
||||
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
|
||||
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
|
||||
assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
|
||||
assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn many0_count_test() {
|
||||
fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> {
|
||||
many0_count(pair(digit, tag(",")))(i)
|
||||
}
|
||||
|
||||
assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1)));
|
||||
|
||||
assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
|
||||
|
||||
assert_eq!(
|
||||
count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
|
||||
Ok((&b"junk"[..], 10))
|
||||
);
|
||||
|
||||
assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn many1_count_test() {
|
||||
fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> {
|
||||
many1_count(pair(digit, tag(",")))(i)
|
||||
}
|
||||
|
||||
assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
|
||||
|
||||
assert_eq!(
|
||||
count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
|
||||
Ok((&b"junk"[..], 10))
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
count1_nums(&b"hello"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"hello"[..],
|
||||
ErrorKind::Many1Count
|
||||
)))
|
||||
);
|
||||
}
|
||||
2126
third-party/vendor/nom/src/number/complete.rs
vendored
Normal file
2126
third-party/vendor/nom/src/number/complete.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
15
third-party/vendor/nom/src/number/mod.rs
vendored
Normal file
15
third-party/vendor/nom/src/number/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
//! Parsers recognizing numbers
|
||||
|
||||
pub mod complete;
|
||||
pub mod streaming;
|
||||
|
||||
/// Configurable endianness
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Endianness {
|
||||
/// Big endian
|
||||
Big,
|
||||
/// Little endian
|
||||
Little,
|
||||
/// Will match the host's endianness
|
||||
Native,
|
||||
}
|
||||
2206
third-party/vendor/nom/src/number/streaming.rs
vendored
Normal file
2206
third-party/vendor/nom/src/number/streaming.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
279
third-party/vendor/nom/src/sequence/mod.rs
vendored
Normal file
279
third-party/vendor/nom/src/sequence/mod.rs
vendored
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
//! Combinators applying parsers in sequence
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::error::ParseError;
|
||||
use crate::internal::{IResult, Parser};
|
||||
|
||||
/// Gets an object from the first parser,
|
||||
/// then gets another object from the second parser.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `first` The first parser to apply.
|
||||
/// * `second` The second parser to apply.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed};
|
||||
/// # use nom::Needed::Size;
|
||||
/// use nom::sequence::pair;
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// let mut parser = pair(tag("abc"), tag("efg"));
|
||||
///
|
||||
/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg"))));
|
||||
/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg"))));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut first: F,
|
||||
mut second: G,
|
||||
) -> impl FnMut(I) -> IResult<I, (O1, O2), E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<I, O2, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = first.parse(input)?;
|
||||
second.parse(input).map(|(i, o2)| (i, (o1, o2)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches an object from the first parser and discards it,
|
||||
/// then gets an object from the second parser.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `first` The opening parser.
|
||||
/// * `second` The second parser to get object.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed};
|
||||
/// # use nom::Needed::Size;
|
||||
/// use nom::sequence::preceded;
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// let mut parser = preceded(tag("abc"), tag("efg"));
|
||||
///
|
||||
/// assert_eq!(parser("abcefg"), Ok(("", "efg")));
|
||||
/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg")));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut first: F,
|
||||
mut second: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<I, O2, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, _) = first.parse(input)?;
|
||||
second.parse(input)
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an object from the first parser,
|
||||
/// then matches an object from the second parser and discards it.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `first` The first parser to apply.
|
||||
/// * `second` The second parser to match an object.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed};
|
||||
/// # use nom::Needed::Size;
|
||||
/// use nom::sequence::terminated;
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// let mut parser = terminated(tag("abc"), tag("efg"));
|
||||
///
|
||||
/// assert_eq!(parser("abcefg"), Ok(("", "abc")));
|
||||
/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc")));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(
|
||||
mut first: F,
|
||||
mut second: G,
|
||||
) -> impl FnMut(I) -> IResult<I, O1, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<I, O2, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = first.parse(input)?;
|
||||
second.parse(input).map(|(i, _)| (i, o1))
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets an object from the first parser,
|
||||
/// then matches an object from the sep_parser and discards it,
|
||||
/// then gets another object from the second parser.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `first` The first parser to apply.
|
||||
/// * `sep` The separator parser to apply.
|
||||
/// * `second` The second parser to apply.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed};
|
||||
/// # use nom::Needed::Size;
|
||||
/// use nom::sequence::separated_pair;
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg"));
|
||||
///
|
||||
/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg"))));
|
||||
/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg"))));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
|
||||
mut first: F,
|
||||
mut sep: G,
|
||||
mut second: H,
|
||||
) -> impl FnMut(I) -> IResult<I, (O1, O3), E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<I, O2, E>,
|
||||
H: Parser<I, O3, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, o1) = first.parse(input)?;
|
||||
let (input, _) = sep.parse(input)?;
|
||||
second.parse(input).map(|(i, o2)| (i, (o1, o2)))
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches an object from the first parser and discards it,
|
||||
/// then gets an object from the second parser,
|
||||
/// and finally matches an object from the third parser and discards it.
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `first` The first parser to apply and discard.
|
||||
/// * `second` The second parser to apply.
|
||||
/// * `third` The third parser to apply and discard.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind, Needed};
|
||||
/// # use nom::Needed::Size;
|
||||
/// use nom::sequence::delimited;
|
||||
/// use nom::bytes::complete::tag;
|
||||
///
|
||||
/// let mut parser = delimited(tag("("), tag("abc"), tag(")"));
|
||||
///
|
||||
/// assert_eq!(parser("(abc)"), Ok(("", "abc")));
|
||||
/// assert_eq!(parser("(abc)def"), Ok(("def", "abc")));
|
||||
/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
|
||||
/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
|
||||
/// ```
|
||||
pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
|
||||
mut first: F,
|
||||
mut second: G,
|
||||
mut third: H,
|
||||
) -> impl FnMut(I) -> IResult<I, O2, E>
|
||||
where
|
||||
F: Parser<I, O1, E>,
|
||||
G: Parser<I, O2, E>,
|
||||
H: Parser<I, O3, E>,
|
||||
{
|
||||
move |input: I| {
|
||||
let (input, _) = first.parse(input)?;
|
||||
let (input, o2) = second.parse(input)?;
|
||||
third.parse(input).map(|(i, _)| (i, o2))
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper trait for the tuple combinator.
|
||||
///
|
||||
/// This trait is implemented for tuples of parsers of up to 21 elements.
|
||||
pub trait Tuple<I, O, E> {
|
||||
/// Parses the input and returns a tuple of results of each parser.
|
||||
fn parse(&mut self, input: I) -> IResult<I, O, E>;
|
||||
}
|
||||
|
||||
impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output, Error>>
|
||||
Tuple<Input, (Output,), Error> for (F,)
|
||||
{
|
||||
fn parse(&mut self, input: Input) -> IResult<Input, (Output,), Error> {
|
||||
self.0.parse(input).map(|(i, o)| (i, (o,)))
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! tuple_trait(
|
||||
($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
|
||||
tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
|
||||
);
|
||||
(__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
|
||||
tuple_trait_impl!($($name $ty),+);
|
||||
tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
|
||||
);
|
||||
(__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
|
||||
tuple_trait_impl!($($name $ty),+);
|
||||
tuple_trait_impl!($($name $ty),+, $name1 $ty1);
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! tuple_trait_impl(
|
||||
($($name:ident $ty: ident),+) => (
|
||||
impl<
|
||||
Input: Clone, $($ty),+ , Error: ParseError<Input>,
|
||||
$($name: Parser<Input, $ty, Error>),+
|
||||
> Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
|
||||
|
||||
fn parse(&mut self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
|
||||
tuple_trait_inner!(0, self, input, (), $($name)+)
|
||||
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
macro_rules! tuple_trait_inner(
|
||||
($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
|
||||
let (i, o) = $self.$it.parse($input.clone())?;
|
||||
|
||||
succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+))
|
||||
});
|
||||
($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
|
||||
let (i, o) = $self.$it.parse($input.clone())?;
|
||||
|
||||
succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+))
|
||||
});
|
||||
($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
|
||||
let (i, o) = $self.$it.parse($input.clone())?;
|
||||
|
||||
Ok((i, ($($parsed)* , o)))
|
||||
});
|
||||
);
|
||||
|
||||
tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
|
||||
FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
|
||||
|
||||
// Special case: implement `Tuple` for `()`, the unit type.
|
||||
// This can come up in macros which accept a variable number of arguments.
|
||||
// Literally, `()` is an empty tuple, so it should simply parse nothing.
|
||||
impl<I, E: ParseError<I>> Tuple<I, (), E> for () {
|
||||
fn parse(&mut self, input: I) -> IResult<I, (), E> {
|
||||
Ok((input, ()))
|
||||
}
|
||||
}
|
||||
|
||||
///Applies a tuple of parsers one by one and returns their results as a tuple.
|
||||
///There is a maximum of 21 parsers
|
||||
/// ```rust
|
||||
/// # use nom::{Err, error::ErrorKind};
|
||||
/// use nom::sequence::tuple;
|
||||
/// use nom::character::complete::{alpha1, digit1};
|
||||
/// let mut parser = tuple((alpha1, digit1, alpha1));
|
||||
///
|
||||
/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def"))));
|
||||
/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha))));
|
||||
/// ```
|
||||
pub fn tuple<I, O, E: ParseError<I>, List: Tuple<I, O, E>>(
|
||||
mut l: List,
|
||||
) -> impl FnMut(I) -> IResult<I, O, E> {
|
||||
move |i: I| l.parse(i)
|
||||
}
|
||||
290
third-party/vendor/nom/src/sequence/tests.rs
vendored
Normal file
290
third-party/vendor/nom/src/sequence/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,290 @@
|
|||
use super::*;
|
||||
use crate::bytes::streaming::{tag, take};
|
||||
use crate::error::{Error, ErrorKind};
|
||||
use crate::internal::{Err, IResult, Needed};
|
||||
use crate::number::streaming::be_u16;
|
||||
|
||||
#[test]
|
||||
fn single_element_tuples() {
|
||||
use crate::character::complete::alpha1;
|
||||
use crate::{error::ErrorKind, Err};
|
||||
|
||||
let mut parser = tuple((alpha1,));
|
||||
assert_eq!(parser("abc123def"), Ok(("123def", ("abc",))));
|
||||
assert_eq!(
|
||||
parser("123def"),
|
||||
Err(Err::Error(("123def", ErrorKind::Alpha)))
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
struct B {
|
||||
a: u8,
|
||||
b: u8,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
struct C {
|
||||
a: u8,
|
||||
b: Option<u8>,
|
||||
}
|
||||
|
||||
/*FIXME: convert code examples to new error management
|
||||
use util::{add_error_pattern, error_to_list, print_error};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[rustfmt::skip]
|
||||
fn error_to_string<P: Clone + PartialEq>(e: &Context<P, u32>) -> &'static str {
|
||||
let v: Vec<(P, ErrorKind<u32>)> = error_to_list(e);
|
||||
// do it this way if you can use slice patterns
|
||||
//match &v[..] {
|
||||
// [ErrorKind::Custom(42), ErrorKind::Tag] => "missing `ijkl` tag",
|
||||
// [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] => "missing `mnop` tag after `ijkl`",
|
||||
// _ => "unrecognized error"
|
||||
//}
|
||||
|
||||
let collected: Vec<ErrorKind<u32>> = v.iter().map(|&(_, ref e)| e.clone()).collect();
|
||||
if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Tag] {
|
||||
"missing `ijkl` tag"
|
||||
} else if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] {
|
||||
"missing `mnop` tag after `ijkl`"
|
||||
} else {
|
||||
"unrecognized error"
|
||||
}
|
||||
}
|
||||
|
||||
// do it this way if you can use box patterns
|
||||
//use $crate::lib::std::str;
|
||||
//fn error_to_string(e:Err) -> String
|
||||
// match e {
|
||||
// NodePosition(ErrorKind::Custom(42), i1, box Position(ErrorKind::Tag, i2)) => {
|
||||
// format!("missing `ijkl` tag, found '{}' instead", str::from_utf8(i2).unwrap())
|
||||
// },
|
||||
// NodePosition(ErrorKind::Custom(42), i1, box NodePosition(ErrorKind::Custom(128), i2, box Position(ErrorKind::Tag, i3))) => {
|
||||
// format!("missing `mnop` tag after `ijkl`, found '{}' instead", str::from_utf8(i3).unwrap())
|
||||
// },
|
||||
// _ => "unrecognized error".to_string()
|
||||
// }
|
||||
//}
|
||||
*/
|
||||
|
||||
#[test]
|
||||
fn complete() {
|
||||
use crate::bytes::complete::tag;
|
||||
fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
let (i, _) = tag("ijkl")(i)?;
|
||||
tag("mnop")(i)
|
||||
}
|
||||
let a = &b"ijklmn"[..];
|
||||
|
||||
let res_a = err_test(a);
|
||||
assert_eq!(
|
||||
res_a,
|
||||
Err(Err::Error(error_position!(&b"mn"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pair_test() {
|
||||
fn pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
|
||||
pair(tag("abc"), tag("def"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"abcdefghijkl"[..]),
|
||||
Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
|
||||
);
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"ab"[..]),
|
||||
Err(Err::Incomplete(Needed::new(1)))
|
||||
);
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"abcd"[..]),
|
||||
Err(Err::Incomplete(Needed::new(2)))
|
||||
);
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"xxxdef"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxxdef"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
pair_abc_def(&b"abcxxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn separated_pair_test() {
|
||||
fn sep_pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
|
||||
separated_pair(tag("abc"), tag(","), tag("def"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"abc,defghijkl"[..]),
|
||||
Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
|
||||
);
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"ab"[..]),
|
||||
Err(Err::Incomplete(Needed::new(1)))
|
||||
);
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"abc,d"[..]),
|
||||
Err(Err::Incomplete(Needed::new(2)))
|
||||
);
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"xxx,def"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx,def"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
sep_pair_abc_def(&b"abc,xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn preceded_test() {
|
||||
fn preceded_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
preceded(tag("abcd"), tag("efgh"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"abcdefghijkl"[..]),
|
||||
Ok((&b"ijkl"[..], &b"efgh"[..]))
|
||||
);
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"ab"[..]),
|
||||
Err(Err::Incomplete(Needed::new(2)))
|
||||
);
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"abcde"[..]),
|
||||
Err(Err::Incomplete(Needed::new(3)))
|
||||
);
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"xxxxdef"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
preceded_abcd_efgh(&b"abcdxxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn terminated_test() {
|
||||
fn terminated_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
terminated(tag("abcd"), tag("efgh"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"abcdefghijkl"[..]),
|
||||
Ok((&b"ijkl"[..], &b"abcd"[..]))
|
||||
);
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"ab"[..]),
|
||||
Err(Err::Incomplete(Needed::new(2)))
|
||||
);
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"abcde"[..]),
|
||||
Err(Err::Incomplete(Needed::new(3)))
|
||||
);
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"xxxxdef"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
terminated_abcd_efgh(&b"abcdxxxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn delimited_test() {
|
||||
fn delimited_abc_def_ghi(i: &[u8]) -> IResult<&[u8], &[u8]> {
|
||||
delimited(tag("abc"), tag("def"), tag("ghi"))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"abcdefghijkl"[..]),
|
||||
Ok((&b"jkl"[..], &b"def"[..]))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"ab"[..]),
|
||||
Err(Err::Incomplete(Needed::new(1)))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"abcde"[..]),
|
||||
Err(Err::Incomplete(Needed::new(1)))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"abcdefgh"[..]),
|
||||
Err(Err::Incomplete(Needed::new(1)))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"xxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"xxxdefghi"[..]),
|
||||
Err(Err::Error(error_position!(
|
||||
&b"xxxdefghi"[..],
|
||||
ErrorKind::Tag
|
||||
),))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"abcxxxghi"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxxghi"[..], ErrorKind::Tag)))
|
||||
);
|
||||
assert_eq!(
|
||||
delimited_abc_def_ghi(&b"abcdefxxx"[..]),
|
||||
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tuple_test() {
|
||||
fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8], &[u8])> {
|
||||
tuple((be_u16, take(3u8), tag("fg")))(i)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
tuple_3(&b"abcdefgh"[..]),
|
||||
Ok((&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..])))
|
||||
);
|
||||
assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2))));
|
||||
assert_eq!(
|
||||
tuple_3(&b"abcdejk"[..]),
|
||||
Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
|
||||
);
|
||||
}
|
||||
|
||||
#[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(("", ()))
|
||||
);
|
||||
}
|
||||
536
third-party/vendor/nom/src/str.rs
vendored
Normal file
536
third-party/vendor/nom/src/str.rs
vendored
Normal file
|
|
@ -0,0 +1,536 @@
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
#[cfg(feature = "alloc")]
|
||||
use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many1};
|
||||
use crate::{
|
||||
bytes::complete::{is_a, is_not, tag, take, take_till, take_until},
|
||||
error::{self, ErrorKind},
|
||||
Err, IResult,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn tagtr_succeed() {
|
||||
const INPUT: &str = "Hello World!";
|
||||
const TAG: &str = "Hello";
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
tag(TAG)(input)
|
||||
}
|
||||
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(extra == " World!", "Parser `tag` consumed leftover input.");
|
||||
assert!(
|
||||
output == TAG,
|
||||
"Parser `tag` doesn't return the tag it matched on success. \
|
||||
Expected `{}`, got `{}`.",
|
||||
TAG,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `tag` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tagtr_incomplete() {
|
||||
use crate::bytes::streaming::tag;
|
||||
|
||||
const INPUT: &str = "Hello";
|
||||
const TAG: &str = "Hello World!";
|
||||
|
||||
let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
|
||||
match res {
|
||||
Err(Err::Incomplete(_)) => (),
|
||||
other => {
|
||||
panic!(
|
||||
"Parser `tag` didn't require more input when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tagtr_error() {
|
||||
const INPUT: &str = "Hello World!";
|
||||
const TAG: &str = "Random"; // TAG must be closer than INPUT.
|
||||
|
||||
let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
|
||||
match res {
|
||||
Err(Err::Error(_)) => (),
|
||||
other => {
|
||||
panic!(
|
||||
"Parser `tag` didn't fail when it should have. Got `{:?}`.`",
|
||||
other
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_s_succeed() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
|
||||
let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT);
|
||||
match res {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_s` consumed leftover input. Leftover `{}`.",
|
||||
extra
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_s` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_s` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_until_succeed() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř";
|
||||
const FIND: &str = "ÂßÇ∂";
|
||||
const CONSUMED: &str = "βèƒôřè";
|
||||
const LEFTOVER: &str = "ÂßÇ∂áƒƭèř";
|
||||
|
||||
let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
|
||||
match res {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_until`\
|
||||
consumed leftover input. Leftover `{}`.",
|
||||
extra
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_until`\
|
||||
doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_until` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_s_incomplete() {
|
||||
use crate::bytes::streaming::take;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇá";
|
||||
|
||||
let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT);
|
||||
match res {
|
||||
Err(Err::Incomplete(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `take` didn't require more input when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
use crate::internal::Needed;
|
||||
|
||||
fn is_alphabetic(c: char) -> bool {
|
||||
(c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while() {
|
||||
use crate::bytes::streaming::take_while;
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
take_while(is_alphabetic)(i)
|
||||
}
|
||||
let a = "";
|
||||
let b = "abcd";
|
||||
let c = "abcd123";
|
||||
let d = "123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&c[..]), Ok((&d[..], &b[..])));
|
||||
assert_eq!(f(&d[..]), Ok((&d[..], &a[..])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while1() {
|
||||
use crate::bytes::streaming::take_while1;
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
take_while1(is_alphabetic)(i)
|
||||
}
|
||||
let a = "";
|
||||
let b = "abcd";
|
||||
let c = "abcd123";
|
||||
let d = "123";
|
||||
|
||||
assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
|
||||
assert_eq!(f(&c[..]), Ok((&"123"[..], &b[..])));
|
||||
assert_eq!(
|
||||
f(&d[..]),
|
||||
Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1)))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_till_s_succeed() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
fn till_s(c: char) -> bool {
|
||||
c == 'á'
|
||||
}
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
take_till(till_s)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_till` consumed leftover input."
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_till` doesn't return the string it consumed on success. \
|
||||
Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_till` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_succeed_none() {
|
||||
use crate::bytes::complete::take_while;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const CONSUMED: &str = "";
|
||||
const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
fn while_s(c: char) -> bool {
|
||||
c == '9'
|
||||
}
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
take_while(while_s)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_while` consumed leftover input."
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_while` doesn't return the string it consumed on success. \
|
||||
Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_while` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_not_succeed() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const AVOID: &str = "£úçƙ¥á";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
is_not(AVOID)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `is_not` consumed leftover input. Leftover `{}`.",
|
||||
extra
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `is_not` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `is_not` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while_succeed_some() {
|
||||
use crate::bytes::complete::take_while;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
fn while_s(c: char) -> bool {
|
||||
c == 'β'
|
||||
|| c == 'è'
|
||||
|| c == 'ƒ'
|
||||
|| c == 'ô'
|
||||
|| c == 'ř'
|
||||
|| c == 'è'
|
||||
|| c == 'Â'
|
||||
|| c == 'ß'
|
||||
|| c == 'Ç'
|
||||
}
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
take_while(while_s)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_while` consumed leftover input."
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_while` doesn't return the string it consumed on success. \
|
||||
Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_while` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_not_fail() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const AVOID: &str = "βúçƙ¥";
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
is_not(AVOID)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Err(Err::Error(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `is_not` didn't fail when it should have. Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while1_succeed() {
|
||||
use crate::bytes::complete::take_while1;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
fn while1_s(c: char) -> bool {
|
||||
c == 'β'
|
||||
|| c == 'è'
|
||||
|| c == 'ƒ'
|
||||
|| c == 'ô'
|
||||
|| c == 'ř'
|
||||
|| c == 'è'
|
||||
|| c == 'Â'
|
||||
|| c == 'ß'
|
||||
|| c == 'Ç'
|
||||
}
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
take_while1(while1_s)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `take_while1` consumed leftover input."
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `take_while1` doesn't return the string it consumed on success. \
|
||||
Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `take_while1` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_until_incomplete() {
|
||||
use crate::bytes::streaming::take_until;
|
||||
|
||||
const INPUT: &str = "βèƒôřè";
|
||||
const FIND: &str = "βèƒôřèÂßÇ";
|
||||
|
||||
let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
|
||||
match res {
|
||||
Err(Err::Incomplete(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `take_until` didn't require more input when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_a_succeed() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const MATCH: &str = "βèƒôřèÂßÇ";
|
||||
const CONSUMED: &str = "βèƒôřèÂßÇ";
|
||||
const LEFTOVER: &str = "áƒƭèř";
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
is_a(MATCH)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Ok((extra, output)) => {
|
||||
assert!(
|
||||
extra == LEFTOVER,
|
||||
"Parser `is_a` consumed leftover input. Leftover `{}`.",
|
||||
extra
|
||||
);
|
||||
assert!(
|
||||
output == CONSUMED,
|
||||
"Parser `is_a` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
|
||||
CONSUMED,
|
||||
output
|
||||
);
|
||||
}
|
||||
other => panic!(
|
||||
"Parser `is_a` didn't succeed when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_while1_fail() {
|
||||
use crate::bytes::complete::take_while1;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
fn while1_s(c: char) -> bool {
|
||||
c == '9'
|
||||
}
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
take_while1(while1_s)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Err(Err::Error(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `take_while1` didn't fail when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn is_a_fail() {
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const MATCH: &str = "Ûñℓúçƙ¥";
|
||||
fn test(input: &str) -> IResult<&str, &str> {
|
||||
is_a(MATCH)(input)
|
||||
}
|
||||
match test(INPUT) {
|
||||
Err(Err::Error(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `is_a` didn't fail when it should have. Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn take_until_error() {
|
||||
use crate::bytes::streaming::take_until;
|
||||
|
||||
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
|
||||
const FIND: &str = "Ráñδô₥";
|
||||
|
||||
let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
|
||||
match res {
|
||||
Err(Err::Incomplete(_)) => (),
|
||||
other => panic!(
|
||||
"Parser `take_until` didn't fail when it should have. \
|
||||
Got `{:?}`.",
|
||||
other
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "alloc")]
|
||||
fn recognize_is_a() {
|
||||
let a = "aabbab";
|
||||
let b = "ababcd";
|
||||
|
||||
fn f(i: &str) -> IResult<&str, &str> {
|
||||
recognize(many1(alt((tag("a"), tag("b")))))(i)
|
||||
}
|
||||
|
||||
assert_eq!(f(&a[..]), Ok((&a[6..], &a[..])));
|
||||
assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4])));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf8_indexing() {
|
||||
fn dot(i: &str) -> IResult<&str, &str> {
|
||||
tag(".")(i)
|
||||
}
|
||||
|
||||
let _ = dot("點");
|
||||
}
|
||||
|
||||
#[cfg(feature = "alloc")]
|
||||
#[test]
|
||||
fn case_insensitive() {
|
||||
fn test(i: &str) -> IResult<&str, &str> {
|
||||
tag_no_case("ABcd")(i)
|
||||
}
|
||||
assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd")));
|
||||
assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd")));
|
||||
assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD")));
|
||||
}
|
||||
}
|
||||
1441
third-party/vendor/nom/src/traits.rs
vendored
Normal file
1441
third-party/vendor/nom/src/traits.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue