summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 18:31:44 +0000
commitc23a457e72abe608715ac76f076f47dc42af07a5 (patch)
tree2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/winnow/src
parentReleasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff)
downloadrustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz
rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow/src')
-rw-r--r--vendor/winnow/src/_topic/performance.rs1
-rw-r--r--vendor/winnow/src/_topic/why.rs4
-rw-r--r--vendor/winnow/src/_tutorial/chapter_0.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_1.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_2.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_3.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_4.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_5.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_6.rs1
-rw-r--r--vendor/winnow/src/_tutorial/chapter_7.rs1
-rw-r--r--vendor/winnow/src/_tutorial/mod.rs2
-rw-r--r--vendor/winnow/src/binary/bits/mod.rs46
-rw-r--r--vendor/winnow/src/combinator/branch.rs25
-rw-r--r--vendor/winnow/src/combinator/mod.rs4
-rw-r--r--vendor/winnow/src/combinator/parser.rs25
-rw-r--r--vendor/winnow/src/combinator/tests.rs23
-rw-r--r--vendor/winnow/src/error.rs459
-rw-r--r--vendor/winnow/src/macros.rs1
-rw-r--r--vendor/winnow/src/parser.rs18
-rw-r--r--vendor/winnow/src/stream/mod.rs30
-rw-r--r--vendor/winnow/src/trace/internals.rs63
-rw-r--r--vendor/winnow/src/trace/mod.rs18
22 files changed, 674 insertions, 53 deletions
diff --git a/vendor/winnow/src/_topic/performance.rs b/vendor/winnow/src/_topic/performance.rs
index 5bda958ee..8a6555a06 100644
--- a/vendor/winnow/src/_topic/performance.rs
+++ b/vendor/winnow/src/_topic/performance.rs
@@ -5,6 +5,7 @@
//! See also the general Rust [Performance Book](https://nnethercote.github.io/perf-book/)
//!
//! Tips
+//! - Try `cargo add winnow -F simd`. For some it offers significant performance improvements
//! - When enough cases of an [`alt`] have unique prefixes, prefer [`dispatch`]
//! - When parsing text, try to parse as bytes (`u8`) rather than `char`s ([`BStr`] can make
//! debugging easier)
diff --git a/vendor/winnow/src/_topic/why.rs b/vendor/winnow/src/_topic/why.rs
index e28181b1a..e0328f117 100644
--- a/vendor/winnow/src/_topic/why.rs
+++ b/vendor/winnow/src/_topic/why.rs
@@ -16,7 +16,7 @@
//! - Fewer dependencies to audit
//!
//! However, this comes at the cost of doing it all yourself, including
-//! - Optimizing for each of the above characteristics you are about
+//! - Optimizing for each of the above characteristics you care about
//! - Ensuring the safety of any `unsafe` code (buffer overflows being a common bug with parsers)
//! - Being aware of, familiar with, and correctly implement the relevant algorithms.
//! matklad, who has written two rust compile frontends, commented
@@ -52,7 +52,7 @@
//!
//! This works well for:
//! - Prototyping for what will be a hand-written parser
-//! - When you to minimize the work to evolve your format
+//! - When you want to minimize the work to evolve your format
//! - When you don't have contributors focused solely on parsing and your grammar is large enough
//! to be unwieldy to hand write.
//!
diff --git a/vendor/winnow/src/_tutorial/chapter_0.rs b/vendor/winnow/src/_tutorial/chapter_0.rs
index 4c768d8f8..47c196e86 100644
--- a/vendor/winnow/src/_tutorial/chapter_0.rs
+++ b/vendor/winnow/src/_tutorial/chapter_0.rs
@@ -36,3 +36,4 @@ use crate::_topic;
use std::iter::Iterator;
pub use super::chapter_1 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_1.rs b/vendor/winnow/src/_tutorial/chapter_1.rs
index 1bf146bec..b16a16657 100644
--- a/vendor/winnow/src/_tutorial/chapter_1.rs
+++ b/vendor/winnow/src/_tutorial/chapter_1.rs
@@ -83,3 +83,4 @@ use crate::Parser;
pub use super::chapter_0 as previous;
pub use super::chapter_2 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_2.rs b/vendor/winnow/src/_tutorial/chapter_2.rs
index b0daedc74..0fb80ac37 100644
--- a/vendor/winnow/src/_tutorial/chapter_2.rs
+++ b/vendor/winnow/src/_tutorial/chapter_2.rs
@@ -245,3 +245,4 @@ use std::ops::RangeInclusive;
pub use super::chapter_1 as previous;
pub use super::chapter_3 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_3.rs b/vendor/winnow/src/_tutorial/chapter_3.rs
index 83714f4d7..4dfdc31e4 100644
--- a/vendor/winnow/src/_tutorial/chapter_3.rs
+++ b/vendor/winnow/src/_tutorial/chapter_3.rs
@@ -373,3 +373,4 @@ use crate::stream::Stream;
pub use super::chapter_2 as previous;
pub use super::chapter_4 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_4.rs b/vendor/winnow/src/_tutorial/chapter_4.rs
index fb14613f3..59aa7ee87 100644
--- a/vendor/winnow/src/_tutorial/chapter_4.rs
+++ b/vendor/winnow/src/_tutorial/chapter_4.rs
@@ -107,3 +107,4 @@ use std::str::FromStr;
pub use super::chapter_3 as previous;
pub use super::chapter_5 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_5.rs b/vendor/winnow/src/_tutorial/chapter_5.rs
index 95a89dc8c..ffd8a29ce 100644
--- a/vendor/winnow/src/_tutorial/chapter_5.rs
+++ b/vendor/winnow/src/_tutorial/chapter_5.rs
@@ -279,3 +279,4 @@ use std::vec::Vec;
pub use super::chapter_4 as previous;
pub use super::chapter_6 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_6.rs b/vendor/winnow/src/_tutorial/chapter_6.rs
index d7d2c9fc8..9f4230942 100644
--- a/vendor/winnow/src/_tutorial/chapter_6.rs
+++ b/vendor/winnow/src/_tutorial/chapter_6.rs
@@ -153,3 +153,4 @@ use crate::_topic;
pub use super::chapter_5 as previous;
pub use super::chapter_7 as next;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/chapter_7.rs b/vendor/winnow/src/_tutorial/chapter_7.rs
index 45f2d2d2a..7f13f9829 100644
--- a/vendor/winnow/src/_tutorial/chapter_7.rs
+++ b/vendor/winnow/src/_tutorial/chapter_7.rs
@@ -115,3 +115,4 @@ use crate::PResult;
use crate::Parser;
pub use super::chapter_6 as previous;
+pub use crate::_tutorial as table_of_contents;
diff --git a/vendor/winnow/src/_tutorial/mod.rs b/vendor/winnow/src/_tutorial/mod.rs
index e4b8392f9..224fe6a80 100644
--- a/vendor/winnow/src/_tutorial/mod.rs
+++ b/vendor/winnow/src/_tutorial/mod.rs
@@ -1,6 +1,6 @@
//! # Tutorial
//!
-//! Table of Content
+//! Table of Contents
pub mod chapter_0;
pub mod chapter_1;
diff --git a/vendor/winnow/src/binary/bits/mod.rs b/vendor/winnow/src/binary/bits/mod.rs
index 334c6bf00..b11ba43c7 100644
--- a/vendor/winnow/src/binary/bits/mod.rs
+++ b/vendor/winnow/src/binary/bits/mod.rs
@@ -10,6 +10,9 @@ use crate::stream::{AsBytes, Stream, StreamIsPartial, ToUsize};
use crate::trace::trace;
use crate::{unpeek, IResult, PResult, Parser};
+/// Number of bits in a byte
+const BYTE: usize = u8::BITS as usize;
+
/// Converts a byte-level input to a bit-level input
///
/// See [`bytes`] to convert it back.
@@ -57,12 +60,15 @@ where
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 };
+ // That's why `offset / BYTE` isn't necessarily needed at all times.
+ let remaining_bytes_index =
+ offset / BYTE + if offset % BYTE == 0 { 0 } else { 1 };
let (input, _) = rest.peek_slice(remaining_bytes_index);
Ok((input, result))
}
- Err(ErrMode::Incomplete(n)) => Err(ErrMode::Incomplete(n.map(|u| u.get() / 8 + 1))),
+ Err(ErrMode::Incomplete(n)) => {
+ Err(ErrMode::Incomplete(n.map(|u| u.get() / BYTE + 1)))
+ }
Err(e) => Err(e.convert()),
}
}),
@@ -109,10 +115,10 @@ where
trace(
"bytes",
unpeek(move |(input, offset): (I, usize)| {
- let (inner, _) = if offset % 8 != 0 {
- input.peek_slice(1 + offset / 8)
+ let (inner, _) = if offset % BYTE != 0 {
+ input.peek_slice(1 + offset / BYTE)
} else {
- input.peek_slice(offset / 8)
+ input.peek_slice(offset / BYTE)
};
let i = (input, offset);
match parser.parse_peek(inner) {
@@ -120,13 +126,15 @@ where
Err(ErrMode::Incomplete(Needed::Unknown)) => {
Err(ErrMode::Incomplete(Needed::Unknown))
}
- Err(ErrMode::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) {
- Some(v) => ErrMode::Incomplete(Needed::new(v)),
- None => ErrMode::Cut(E2::assert(
- &i,
- "overflow in turning needed bytes into needed bits",
- )),
- }),
+ Err(ErrMode::Incomplete(Needed::Size(sz))) => {
+ Err(match sz.get().checked_mul(BYTE) {
+ Some(v) => ErrMode::Incomplete(Needed::new(v)),
+ None => ErrMode::Cut(E2::assert(
+ &i,
+ "overflow in turning needed bytes into needed bits",
+ )),
+ })
+ }
Err(e) => Err(e.convert()),
}
}),
@@ -196,8 +204,7 @@ where
if count == 0 {
Ok(((input, bit_offset), 0u8.into()))
} else {
- let cnt = (count + bit_offset).div(8);
- if input.eof_offset() * 8 < count + bit_offset {
+ if input.eof_offset() * BYTE < count + bit_offset {
if PARTIAL && input.is_partial() {
Err(ErrMode::Incomplete(Needed::new(count)))
} else {
@@ -207,6 +214,7 @@ where
))
}
} else {
+ let cnt = (count + bit_offset).div(BYTE);
let mut acc: O = 0_u8.into();
let mut offset: usize = bit_offset;
let mut remaining: usize = count;
@@ -222,13 +230,13 @@ where
(byte << offset >> offset).into()
};
- if remaining < 8 - offset {
- acc += val >> (8 - offset - remaining);
+ if remaining < BYTE - offset {
+ acc += val >> (BYTE - offset - remaining);
end_offset = remaining + offset;
break;
} else {
- acc += val << (remaining - (8 - offset));
- remaining -= 8 - offset;
+ acc += val << (remaining - (BYTE - offset));
+ remaining -= BYTE - offset;
offset = 0;
}
}
diff --git a/vendor/winnow/src/combinator/branch.rs b/vendor/winnow/src/combinator/branch.rs
index 2a712ec1d..b909ff1c7 100644
--- a/vendor/winnow/src/combinator/branch.rs
+++ b/vendor/winnow/src/combinator/branch.rs
@@ -112,6 +112,31 @@ pub fn permutation<I: Stream, O, E: ParserError<I>, List: Permutation<I, O, E>>(
trace("permutation", move |i: &mut I| l.permutation(i))
}
+impl<const N: usize, I: Stream, O, E: ParserError<I>, P: Parser<I, O, E>> Alt<I, O, E> for [P; N] {
+ fn choice(&mut self, input: &mut I) -> PResult<O, E> {
+ let mut error: Option<E> = None;
+
+ let start = input.checkpoint();
+ for branch in self {
+ input.reset(start.clone());
+ match branch.parse_next(input) {
+ Err(ErrMode::Backtrack(e)) => {
+ error = match error {
+ Some(error) => Some(error.or(e)),
+ None => Some(e),
+ };
+ }
+ res => return res,
+ }
+ }
+
+ match error {
+ Some(e) => Err(ErrMode::Backtrack(e.append(input, ErrorKind::Alt))),
+ None => Err(ErrMode::assert(input, "`alt` needs at least one parser")),
+ }
+ }
+}
+
macro_rules! alt_trait(
($first:ident $second:ident $($id: ident)+) => (
alt_trait!(__impl $first $second; $($id)+);
diff --git a/vendor/winnow/src/combinator/mod.rs b/vendor/winnow/src/combinator/mod.rs
index d76ef8e5f..ec68e48e2 100644
--- a/vendor/winnow/src/combinator/mod.rs
+++ b/vendor/winnow/src/combinator/mod.rs
@@ -8,8 +8,8 @@
//!
//! | combinator | usage | input | output | comment |
//! |---|---|---|---|---|
-//! | [`one_of`][crate::token::one_of] | `one_of("abc")` | `"abc"` | `Ok(("bc", 'a'))` |Matches one of the provided characters (works with non ASCII characters too)|
-//! | [`none_of`][crate::token::none_of] | `none_of("abc")` | `"xyab"` | `Ok(("yab", 'x'))` |Matches anything but the provided characters|
+//! | [`one_of`][crate::token::one_of] | `one_of(['a', 'b', 'c'])` | `"abc"` | `Ok(("bc", 'a'))` |Matches one of the provided characters (works with non ASCII characters too)|
+//! | [`none_of`][crate::token::none_of] | `none_of(['a', 'b', 'c'])` | `"xyab"` | `Ok(("yab", 'x'))` |Matches anything but the provided characters|
//! | [`tag`][crate::token::tag] | `"hello"` | `"hello world"` | `Ok((" world", "hello"))` |Recognizes a specific suite of characters or bytes|
//! | [`tag_no_case`][crate::token::tag_no_case] | `tag_no_case("hello")` | `"HeLLo World"` | `Ok((" World", "HeLLo"))` |Case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises|
//! | [`take`][crate::token::take] | `take(4)` | `"hello"` | `Ok(("o", "hell"))` |Takes a specific number of bytes or characters|
diff --git a/vendor/winnow/src/combinator/parser.rs b/vendor/winnow/src/combinator/parser.rs
index 969c2d525..fb11adc15 100644
--- a/vendor/winnow/src/combinator/parser.rs
+++ b/vendor/winnow/src/combinator/parser.rs
@@ -14,12 +14,16 @@ pub struct ByRef<'p, P> {
}
impl<'p, P> ByRef<'p, P> {
+ #[inline(always)]
pub(crate) fn new(p: &'p mut P) -> Self {
Self { p }
}
}
-impl<'p, I, O, E, P: Parser<I, O, E>> Parser<I, O, E> for ByRef<'p, P> {
+impl<'p, I, O, E, P> Parser<I, O, E> for ByRef<'p, P>
+where
+ P: Parser<I, O, E>,
+{
#[inline(always)]
fn parse_next(&mut self, i: &mut I) -> PResult<O, E> {
self.p.parse_next(i)
@@ -46,6 +50,7 @@ where
F: Parser<I, O, E>,
G: Fn(O) -> O2,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, map: G) -> Self {
Self {
parser,
@@ -97,6 +102,7 @@ where
I: Stream,
E: FromExternalError<I, E2>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, map: G) -> Self {
Self {
parser,
@@ -154,6 +160,7 @@ where
I: Stream,
E: ParserError<I>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, map: G) -> Self {
Self {
parser,
@@ -210,6 +217,7 @@ where
O: StreamIsPartial,
I: Stream,
{
+ #[inline(always)]
pub(crate) fn new(outer: F, inner: G) -> Self {
Self {
outer,
@@ -265,6 +273,7 @@ where
O: crate::stream::ParseSlice<O2>,
E: ParserError<I>,
{
+ #[inline(always)]
pub(crate) fn new(p: P) -> Self {
Self {
p,
@@ -319,6 +328,7 @@ where
G: FnMut(O) -> H,
H: Parser<I, O2, E>,
{
+ #[inline(always)]
pub(crate) fn new(f: F, g: G) -> Self {
Self {
f,
@@ -352,6 +362,7 @@ pub struct CompleteErr<F> {
}
impl<F> CompleteErr<F> {
+ #[inline(always)]
pub(crate) fn new(f: F) -> Self {
Self { f }
}
@@ -405,6 +416,7 @@ where
O2: ?Sized,
E: ParserError<I>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, filter: G) -> Self {
Self {
parser,
@@ -458,6 +470,7 @@ where
F: Parser<I, O, E>,
O2: Clone,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, val: O2) -> Self {
Self {
parser,
@@ -496,6 +509,7 @@ impl<F, I, O, E> Void<F, I, O, E>
where
F: Parser<I, O, E>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -534,6 +548,7 @@ where
F: Parser<I, O, E>,
I: Stream,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -582,6 +597,7 @@ where
F: Parser<I, O, E>,
I: Stream,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -630,6 +646,7 @@ where
F: Parser<I, O, E>,
I: Stream + Location,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -673,6 +690,7 @@ where
F: Parser<I, O, E>,
I: Stream + Location,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -717,6 +735,7 @@ where
F: Parser<I, O, E>,
O: Into<O2>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -758,6 +777,7 @@ where
F: Parser<I, O, E>,
E: Into<E2>,
{
+ #[inline(always)]
pub(crate) fn new(parser: F) -> Self {
Self {
parser,
@@ -808,6 +828,7 @@ where
E: AddContext<I, C>,
C: Clone + crate::lib::std::fmt::Debug,
{
+ #[inline(always)]
pub(crate) fn new(parser: F, context: C) -> Self {
Self {
parser,
@@ -835,7 +856,7 @@ where
trace(name, move |i: &mut I| {
(self.parser)
.parse_next(i)
- .map_err(|err| err.map(|err| err.add_context(i, self.context.clone())))
+ .map_err(|err| err.add_context(i, self.context.clone()))
})
.parse_next(i)
}
diff --git a/vendor/winnow/src/combinator/tests.rs b/vendor/winnow/src/combinator/tests.rs
index 62dc420e5..9d2b49d80 100644
--- a/vendor/winnow/src/combinator/tests.rs
+++ b/vendor/winnow/src/combinator/tests.rs
@@ -13,6 +13,7 @@ use crate::stream::Stream;
use crate::token::take;
use crate::unpeek;
use crate::IResult;
+use crate::PResult;
use crate::Parser;
use crate::Partial;
@@ -649,6 +650,28 @@ fn alt_incomplete() {
}
#[test]
+fn alt_array() {
+ fn alt1<'i>(i: &mut &'i [u8]) -> PResult<&'i [u8]> {
+ alt(["a", "bc", "def"]).parse_next(i)
+ }
+
+ let i = &b"a"[..];
+ assert_eq!(alt1.parse_peek(i), Ok((&b""[..], (&b"a"[..]))));
+
+ let i = &b"bc"[..];
+ assert_eq!(alt1.parse_peek(i), Ok((&b""[..], (&b"bc"[..]))));
+
+ let i = &b"defg"[..];
+ assert_eq!(alt1.parse_peek(i), Ok((&b"g"[..], (&b"def"[..]))));
+
+ let i = &b"z"[..];
+ assert_eq!(
+ alt1.parse_peek(i),
+ Err(ErrMode::Backtrack(error_position!(&i, ErrorKind::Tag)))
+ );
+}
+
+#[test]
fn permutation_test() {
#[allow(clippy::type_complexity)]
fn perm(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, (&[u8], &[u8], &[u8])> {
diff --git a/vendor/winnow/src/error.rs b/vendor/winnow/src/error.rs
index d40e8244b..449bebc55 100644
--- a/vendor/winnow/src/error.rs
+++ b/vendor/winnow/src/error.rs
@@ -17,6 +17,7 @@
//! - [`ErrorKind`]
//! - [`InputError`] (mostly for testing)
//! - [`ContextError`]
+//! - [`TreeError`] (mostly for testing)
//! - [Custom errors][crate::_topic::error]
#[cfg(feature = "alloc")]
@@ -88,7 +89,7 @@ impl Needed {
}
}
-/// The `Err` enum indicates the parser was not successful
+/// Add parse error state to [`ParserError`]s
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub enum ErrMode<E> {
@@ -120,6 +121,7 @@ pub enum ErrMode<E> {
impl<E> ErrMode<E> {
/// Tests if the result is Incomplete
+ #[inline]
pub fn is_incomplete(&self) -> bool {
matches!(self, ErrMode::Incomplete(_))
}
@@ -164,6 +166,7 @@ impl<E> ErrMode<E> {
///
/// Returns `None` for [`ErrMode::Incomplete`]
#[cfg_attr(debug_assertions, track_caller)]
+ #[inline(always)]
pub fn into_inner(self) -> Option<E> {
match self {
ErrMode::Backtrack(e) | ErrMode::Cut(e) => Some(e),
@@ -173,11 +176,13 @@ impl<E> ErrMode<E> {
}
impl<I, E: ParserError<I>> ParserError<I> for ErrMode<E> {
+ #[inline(always)]
fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
ErrMode::Backtrack(E::from_error_kind(input, kind))
}
#[cfg_attr(debug_assertions, track_caller)]
+ #[inline(always)]
fn assert(input: &I, message: &'static str) -> Self
where
I: crate::lib::std::fmt::Debug,
@@ -185,6 +190,7 @@ impl<I, E: ParserError<I>> ParserError<I> for ErrMode<E> {
ErrMode::Backtrack(E::assert(input, message))
}
+ #[inline]
fn append(self, input: &I, kind: ErrorKind) -> Self {
match self {
ErrMode::Backtrack(e) => ErrMode::Backtrack(e.append(input, kind)),
@@ -205,11 +211,19 @@ impl<I, EXT, E> FromExternalError<I, EXT> for ErrMode<E>
where
E: FromExternalError<I, EXT>,
{
+ #[inline(always)]
fn from_external_error(input: &I, kind: ErrorKind, e: EXT) -> Self {
ErrMode::Backtrack(E::from_external_error(input, kind, e))
}
}
+impl<I, C, E: AddContext<I, C>> AddContext<I, C> for ErrMode<E> {
+ #[inline(always)]
+ fn add_context(self, input: &I, ctx: C) -> Self {
+ self.map(|err| err.add_context(input, ctx))
+ }
+}
+
impl<T: Clone> ErrMode<InputError<T>> {
/// Maps `ErrMode<InputError<T>>` to `ErrMode<InputError<U>>` with the given `F: T -> U`
pub fn map_input<U: Clone, F>(self, f: F) -> ErrMode<InputError<U>>
@@ -276,6 +290,7 @@ pub trait ParserError<I>: Sized {
///
/// For example, this would be used by [`alt`][crate::combinator::alt] to report the error from
/// each case.
+ #[inline]
fn or(self, other: Self) -> Self {
other
}
@@ -330,19 +345,25 @@ impl<I: Clone> InputError<I> {
pub fn new(input: I, kind: ErrorKind) -> Self {
Self { input, kind }
}
+
+ /// Translate the input type
+ #[inline]
+ pub fn map_input<I2: Clone, O: Fn(I) -> I2>(self, op: O) -> InputError<I2> {
+ InputError {
+ input: op(self.input),
+ kind: self.kind,
+ }
+ }
}
#[cfg(feature = "alloc")]
-impl<'i, I: Clone + ToOwned + ?Sized> InputError<&'i I>
+impl<'i, I: ToOwned> InputError<&'i I>
where
<I as ToOwned>::Owned: Clone,
{
/// Obtaining ownership
pub fn into_owned(self) -> InputError<<I as ToOwned>::Owned> {
- InputError {
- input: self.input.to_owned(),
- kind: self.kind,
- }
+ self.map_input(ToOwned::to_owned)
}
}
@@ -397,7 +418,12 @@ impl<I: Clone> ErrorConvert<InputError<I>> for InputError<(I, usize)> {
/// The Display implementation allows the `std::error::Error` implementation
impl<I: Clone + fmt::Display> fmt::Display for InputError<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- write!(f, "{} error starting at: {}", self.kind, self.input)
+ write!(
+ f,
+ "{} error starting at: {}",
+ self.kind.description(),
+ self.input
+ )
}
}
@@ -464,6 +490,16 @@ impl<C> ContextError<C> {
}
}
+impl<C: Clone> Clone for ContextError<C> {
+ fn clone(&self) -> Self {
+ Self {
+ context: self.context.clone(),
+ #[cfg(feature = "std")]
+ cause: self.cause.as_ref().map(|e| e.to_string().into()),
+ }
+ }
+}
+
impl<C> Default for ContextError<C> {
#[inline]
fn default() -> Self {
@@ -606,6 +642,15 @@ pub enum StrContext {
Expected(StrContextValue),
}
+impl crate::lib::std::fmt::Display for StrContext {
+ fn fmt(&self, f: &mut crate::lib::std::fmt::Formatter<'_>) -> crate::lib::std::fmt::Result {
+ match self {
+ Self::Label(name) => write!(f, "invalid {name}"),
+ Self::Expected(value) => write!(f, "expected {value}"),
+ }
+ }
+}
+
/// See [`StrContext`]
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
@@ -619,12 +664,14 @@ pub enum StrContextValue {
}
impl From<char> for StrContextValue {
+ #[inline]
fn from(inner: char) -> Self {
Self::CharLiteral(inner)
}
}
impl From<&'static str> for StrContextValue {
+ #[inline]
fn from(inner: &'static str) -> Self {
Self::StringLiteral(inner)
}
@@ -645,6 +692,395 @@ impl crate::lib::std::fmt::Display for StrContextValue {
}
}
+/// Trace all error paths, particularly for tests
+#[derive(Debug)]
+#[cfg(feature = "std")]
+pub enum TreeError<I, C = StrContext> {
+ /// Initial error that kicked things off
+ Base(TreeErrorBase<I>),
+ /// Traces added to the error while walking back up the stack
+ Stack {
+ /// Initial error that kicked things off
+ base: Box<Self>,
+ /// Traces added to the error while walking back up the stack
+ stack: Vec<TreeErrorFrame<I, C>>,
+ },
+ /// All failed branches of an `alt`
+ Alt(Vec<Self>),
+}
+
+/// See [`TreeError::Stack`]
+#[derive(Debug)]
+#[cfg(feature = "std")]
+pub enum TreeErrorFrame<I, C = StrContext> {
+ /// See [`ParserError::append`]
+ Kind(TreeErrorBase<I>),
+ /// See [`AddContext::add_context`]
+ Context(TreeErrorContext<I, C>),
+}
+
+/// See [`TreeErrorFrame::Kind`], [`ParserError::append`]
+#[derive(Debug)]
+#[cfg(feature = "std")]
+pub struct TreeErrorBase<I> {
+ /// Parsed input, at the location where the error occurred
+ pub input: I,
+ /// Debug context
+ pub kind: ErrorKind,
+ /// See [`FromExternalError::from_external_error`]
+ pub cause: Option<Box<dyn std::error::Error + Send + Sync + 'static>>,
+}
+
+/// See [`TreeErrorFrame::Context`], [`AddContext::add_context`]
+#[derive(Debug)]
+#[cfg(feature = "std")]
+pub struct TreeErrorContext<I, C = StrContext> {
+ /// Parsed input, at the location where the error occurred
+ pub input: I,
+ /// See [`AddContext::add_context`]
+ pub context: C,
+}
+
+#[cfg(feature = "std")]
+impl<'i, I: ToOwned, C> TreeError<&'i I, C>
+where
+ <I as ToOwned>::Owned: Clone,
+{
+ /// Obtaining ownership
+ pub fn into_owned(self) -> TreeError<<I as ToOwned>::Owned, C> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, C> TreeError<I, C>
+where
+ I: Clone,
+{
+ /// Translate the input type
+ pub fn map_input<I2: Clone, O: Clone + Fn(I) -> I2>(self, op: O) -> TreeError<I2, C> {
+ match self {
+ TreeError::Base(base) => TreeError::Base(TreeErrorBase {
+ input: op(base.input),
+ kind: base.kind,
+ cause: base.cause,
+ }),
+ TreeError::Stack { base, stack } => {
+ let base = Box::new(base.map_input(op.clone()));
+ let stack = stack
+ .into_iter()
+ .map(|frame| match frame {
+ TreeErrorFrame::Kind(kind) => TreeErrorFrame::Kind(TreeErrorBase {
+ input: op(kind.input),
+ kind: kind.kind,
+ cause: kind.cause,
+ }),
+ TreeErrorFrame::Context(context) => {
+ TreeErrorFrame::Context(TreeErrorContext {
+ input: op(context.input),
+ context: context.context,
+ })
+ }
+ })
+ .collect();
+ TreeError::Stack { base, stack }
+ }
+ TreeError::Alt(alt) => {
+ TreeError::Alt(alt.into_iter().map(|e| e.map_input(op.clone())).collect())
+ }
+ }
+ }
+
+ fn append_frame(self, frame: TreeErrorFrame<I, C>) -> Self {
+ match self {
+ TreeError::Stack { base, mut stack } => {
+ stack.push(frame);
+ TreeError::Stack { base, stack }
+ }
+ base => TreeError::Stack {
+ base: Box::new(base),
+ stack: vec![frame],
+ },
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, C> ParserError<I> for TreeError<I, C>
+where
+ I: Clone,
+{
+ fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
+ TreeError::Base(TreeErrorBase {
+ input: input.clone(),
+ kind,
+ cause: None,
+ })
+ }
+
+ fn append(self, input: &I, kind: ErrorKind) -> Self {
+ let frame = TreeErrorFrame::Kind(TreeErrorBase {
+ input: input.clone(),
+ kind,
+ cause: None,
+ });
+ self.append_frame(frame)
+ }
+
+ fn or(self, other: Self) -> Self {
+ match (self, other) {
+ (TreeError::Alt(mut first), TreeError::Alt(second)) => {
+ // Just in case an implementation does a divide-and-conquer algorithm
+ //
+ // To prevent mixing `alt`s at different levels, parsers should
+ // `alt_err.append(input, ErrorKind::Alt)`.
+ first.extend(second);
+ TreeError::Alt(first)
+ }
+ (TreeError::Alt(mut alt), new) | (new, TreeError::Alt(mut alt)) => {
+ alt.push(new);
+ TreeError::Alt(alt)
+ }
+ (first, second) => TreeError::Alt(vec![first, second]),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, C> AddContext<I, C> for TreeError<I, C>
+where
+ I: Clone,
+{
+ fn add_context(self, input: &I, context: C) -> Self {
+ let frame = TreeErrorFrame::Context(TreeErrorContext {
+ input: input.clone(),
+ context,
+ });
+ self.append_frame(frame)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, C, E: std::error::Error + Send + Sync + 'static> FromExternalError<I, E> for TreeError<I, C>
+where
+ I: Clone,
+{
+ fn from_external_error(input: &I, kind: ErrorKind, e: E) -> Self {
+ TreeError::Base(TreeErrorBase {
+ input: input.clone(),
+ kind,
+ cause: Some(Box::new(e)),
+ })
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, C> TreeError<I, C>
+where
+ I: Clone + std::fmt::Display,
+ C: fmt::Display,
+{
+ fn write(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result {
+ let child_indent = indent + 2;
+ match self {
+ TreeError::Base(base) => {
+ writeln!(f, "{:indent$}{base}", "")?;
+ }
+ TreeError::Stack { base, stack } => {
+ base.write(f, indent)?;
+ for (level, frame) in stack.iter().enumerate() {
+ match frame {
+ TreeErrorFrame::Kind(frame) => {
+ writeln!(f, "{:child_indent$}{level}: {frame}", "")?;
+ }
+ TreeErrorFrame::Context(frame) => {
+ writeln!(f, "{:child_indent$}{level}: {frame}", "")?;
+ }
+ }
+ }
+ }
+ TreeError::Alt(alt) => {
+ writeln!(f, "{:indent$}during one of:", "")?;
+ for child in alt {
+ child.write(f, child_indent)?;
+ }
+ }
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I: Clone + fmt::Display> fmt::Display for TreeErrorBase<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ if let Some(cause) = self.cause.as_ref() {
+ write!(f, "caused by {cause}")?;
+ } else {
+ let kind = self.kind.description();
+ write!(f, "in {kind}")?;
+ }
+ let input = abbreviate(self.input.to_string());
+ write!(f, " at '{input}'")?;
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for TreeErrorContext<I, C> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let context = &self.context;
+ let input = abbreviate(self.input.to_string());
+ write!(f, "{context} at '{input}'")?;
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<
+ I: Clone + fmt::Debug + fmt::Display + Sync + Send + 'static,
+ C: fmt::Display + fmt::Debug,
+ > std::error::Error for TreeError<I, C>
+{
+}
+
+#[cfg(feature = "std")]
+fn abbreviate(input: String) -> String {
+ let mut abbrev = None;
+
+ if let Some((line, _)) = input.split_once('\n') {
+ abbrev = Some(line);
+ }
+
+ let max_len = 20;
+ let current = abbrev.unwrap_or(&input);
+ if max_len < current.len() {
+ if let Some((index, _)) = current.char_indices().nth(max_len) {
+ abbrev = Some(&current[..index]);
+ }
+ }
+
+ if let Some(abbrev) = abbrev {
+ format!("{abbrev}...")
+ } else {
+ input
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for TreeError<I, C> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.write(f, 0)
+ }
+}
+
+/// Deprecated, replaced with [`ContextError`]
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+#[deprecated(since = "0.5.8", note = "Replaced with `ContextError`")]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct VerboseError<I: Clone, C = &'static str> {
+ /// Accumulated error information
+ pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind<C>)>,
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<'i, I: ToOwned, C> VerboseError<&'i I, C>
+where
+ <I as ToOwned>::Owned: Clone,
+{
+ /// Obtaining ownership
+ pub fn into_owned(self) -> VerboseError<<I as ToOwned>::Owned, C> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<I: Clone, C> VerboseError<I, C> {
+ /// Translate the input type
+ pub fn map_input<I2: Clone, O>(self, op: O) -> VerboseError<I2, C>
+ where
+ O: Fn(I) -> I2,
+ {
+ VerboseError {
+ errors: self.errors.into_iter().map(|(i, k)| (op(i), k)).collect(),
+ }
+ }
+}
+
+/// Deprecated, replaced with [`ContextError`]
+#[cfg(feature = "std")]
+#[deprecated(since = "0.5.8", note = "Replaced with `ContextError`")]
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub enum VerboseErrorKind<C = &'static str> {
+ /// Static string added by the `context` function
+ Context(C),
+ /// Error kind given by various parsers
+ Winnow(ErrorKind),
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<I: Clone, C> ParserError<I> for VerboseError<I, C> {
+ fn from_error_kind(input: &I, kind: ErrorKind) -> Self {
+ VerboseError {
+ errors: vec![(input.clone(), VerboseErrorKind::Winnow(kind))],
+ }
+ }
+
+ fn append(mut self, input: &I, kind: ErrorKind) -> Self {
+ self.errors
+ .push((input.clone(), VerboseErrorKind::Winnow(kind)));
+ self
+ }
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<I: Clone, C> AddContext<I, C> for VerboseError<I, C> {
+ fn add_context(mut self, input: &I, ctx: C) -> Self {
+ self.errors
+ .push((input.clone(), VerboseErrorKind::Context(ctx)));
+ self
+ }
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<I: Clone, C, E> FromExternalError<I, E> for VerboseError<I, C> {
+ /// 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 = "std")]
+#[allow(deprecated)]
+impl<I: Clone + fmt::Display, C: fmt::Display> fmt::Display for VerboseError<I, C> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(f, "Parse error:")?;
+ for (input, error) in &self.errors {
+ match error {
+ VerboseErrorKind::Winnow(e) => writeln!(f, "{} at: {}", e.description(), input)?,
+ VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
+ }
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+#[allow(deprecated)]
+impl<
+ I: Clone + fmt::Debug + fmt::Display + Sync + Send + 'static,
+ C: fmt::Display + fmt::Debug,
+ > std::error::Error for VerboseError<I, C>
+{
+}
+
/// Provide some minor debug context for errors
#[rustfmt::skip]
#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
@@ -684,10 +1120,12 @@ impl ErrorKind {
}
impl<I> ParserError<I> for ErrorKind {
+ #[inline]
fn from_error_kind(_input: &I, kind: ErrorKind) -> Self {
kind
}
+ #[inline]
fn append(self, _: &I, _: ErrorKind) -> Self {
self
}
@@ -697,6 +1135,7 @@ impl<I, C> AddContext<I, C> for ErrorKind {}
impl<I, E> FromExternalError<I, E> for ErrorKind {
/// Create a new error from an input position and an external error
+ #[inline]
fn from_external_error(_input: &I, kind: ErrorKind, _e: E) -> Self {
kind
}
@@ -750,6 +1189,12 @@ impl<I, E> ParseError<I, E> {
pub fn inner(&self) -> &E {
&self.inner
}
+
+ /// The original [`ParserError`]
+ #[inline]
+ pub fn into_inner(self) -> E {
+ self.inner
+ }
}
impl<I, E> core::fmt::Display for ParseError<I, E>
diff --git a/vendor/winnow/src/macros.rs b/vendor/winnow/src/macros.rs
index b3078c605..35279bae8 100644
--- a/vendor/winnow/src/macros.rs
+++ b/vendor/winnow/src/macros.rs
@@ -38,6 +38,7 @@
/// assert_eq!(escaped.parse_peek("\\nHello"), Ok(("Hello", '\n')));
/// ```
#[macro_export]
+#[doc(hidden)] // forced to be visible in intended location
macro_rules! dispatch {
($match_parser: expr; $( $pat:pat $(if $pred:expr)? => $expr: expr ),+ $(,)? ) => {
$crate::trace::trace("dispatch", move |i: &mut _|
diff --git a/vendor/winnow/src/parser.rs b/vendor/winnow/src/parser.rs
index d160a8ef8..b59e4cd83 100644
--- a/vendor/winnow/src/parser.rs
+++ b/vendor/winnow/src/parser.rs
@@ -128,6 +128,7 @@ pub trait Parser<I, O, E> {
/// }
/// }
/// ```
+ #[inline(always)]
fn by_ref(&mut self) -> ByRef<'_, Self>
where
Self: core::marker::Sized,
@@ -151,6 +152,7 @@ pub trait Parser<I, O, E> {
/// # }
/// ```
#[doc(alias = "to")]
+ #[inline(always)]
fn value<O2>(self, val: O2) -> Value<Self, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -174,6 +176,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parser.parse_peek("123abcd;"), Err(ErrMode::Backtrack(InputError::new("123abcd;", ErrorKind::Slice))));
/// # }
/// ```
+ #[inline(always)]
fn void(self) -> Void<Self, I, O, E>
where
Self: core::marker::Sized,
@@ -202,6 +205,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
/// # }
/// ```
+ #[inline(always)]
fn output_into<O2>(self) -> OutputInto<Self, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -227,6 +231,7 @@ pub trait Parser<I, O, E> {
/// # }
/// ```
#[doc(alias = "concat")]
+ #[inline(always)]
fn recognize(self) -> Recognize<Self, I, O, E>
where
Self: core::marker::Sized,
@@ -272,6 +277,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(recognize_parser.parse_peek("abcd"), consumed_parser.parse_peek("abcd"));
/// ```
#[doc(alias = "consumed")]
+ #[inline(always)]
fn with_recognized(self) -> WithRecognized<Self, I, O, E>
where
Self: core::marker::Sized,
@@ -296,6 +302,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parser.parse(Located::new("abcd,efgh")), Ok((0..4, 5..9)));
/// assert_eq!(parser.parse_peek(Located::new("abcd;")),Err(ErrMode::Backtrack(InputError::new(Located::new("abcd;").peek_slice(4).0, ErrorKind::Verify))));
/// ```
+ #[inline(always)]
fn span(self) -> Span<Self, I, O, E>
where
Self: core::marker::Sized,
@@ -344,6 +351,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(recognize_parser.parse_peek(Located::new("abcd")), consumed_parser.parse_peek(Located::new("abcd")));
/// # }
/// ```
+ #[inline(always)]
fn with_span(self) -> WithSpan<Self, I, O, E>
where
Self: core::marker::Sized,
@@ -370,6 +378,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parser.parse_peek("abc"), Err(ErrMode::Backtrack(InputError::new("abc", ErrorKind::Slice))));
/// # }
/// ```
+ #[inline(always)]
fn map<G, O2>(self, map: G) -> Map<Self, G, I, O, O2, E>
where
G: Fn(O) -> O2,
@@ -399,6 +408,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parse.parse_peek("123456"), Err(ErrMode::Backtrack(InputError::new("123456", ErrorKind::Verify))));
/// # }
/// ```
+ #[inline(always)]
fn try_map<G, O2, E2>(self, map: G) -> TryMap<Self, G, I, O, O2, E, E2>
where
Self: core::marker::Sized,
@@ -433,6 +443,7 @@ pub trait Parser<I, O, E> {
#[doc(alias = "satisfy_map")]
#[doc(alias = "filter_map")]
#[doc(alias = "map_opt")]
+ #[inline(always)]
fn verify_map<G, O2>(self, map: G) -> VerifyMap<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -475,6 +486,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(length_data.parse_peek(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
/// assert_eq!(length_data.parse_peek(&[4, 0, 1, 2][..]), Err(ErrMode::Backtrack(InputError::new(&[0, 1, 2][..], ErrorKind::Slice))));
/// ```
+ #[inline(always)]
fn flat_map<G, H, O2>(self, map: G) -> FlatMap<Self, G, H, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -501,6 +513,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(digits.parse_peek("123"), Err(ErrMode::Backtrack(InputError::new("123", ErrorKind::Slice))));
/// # }
/// ```
+ #[inline(always)]
fn and_then<G, O2>(self, inner: G) -> AndThen<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -531,6 +544,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parser.parse_peek("abc"), Err(ErrMode::Backtrack(InputError::new("abc", ErrorKind::Slice))));
/// ```
#[doc(alias = "from_str")]
+ #[inline(always)]
fn parse_to<O2>(self) -> ParseTo<Self, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -562,6 +576,7 @@ pub trait Parser<I, O, E> {
/// ```
#[doc(alias = "satisfy")]
#[doc(alias = "filter")]
+ #[inline(always)]
fn verify<G, O2>(self, filter: G) -> Verify<Self, G, I, O, O2, E>
where
Self: core::marker::Sized,
@@ -579,6 +594,7 @@ pub trait Parser<I, O, E> {
/// This is used mainly to add user friendly information
/// to errors when backtracking through a parse tree.
#[doc(alias = "labelled")]
+ #[inline(always)]
fn context<C>(self, context: C) -> Context<Self, I, O, E, C>
where
Self: core::marker::Sized,
@@ -604,6 +620,7 @@ pub trait Parser<I, O, E> {
/// assert_eq!(parser.parse_peek(Partial::new("abcd")), Err(ErrMode::Backtrack(InputError::new(Partial::new("abcd"), ErrorKind::Complete))));
/// # }
/// ```
+ #[inline(always)]
fn complete_err(self) -> CompleteErr<Self>
where
Self: core::marker::Sized,
@@ -612,6 +629,7 @@ pub trait Parser<I, O, E> {
}
/// Convert the parser's error to another type using [`std::convert::From`]
+ #[inline(always)]
fn err_into<E2>(self) -> ErrInto<Self, I, O, E, E2>
where
Self: core::marker::Sized,
diff --git a/vendor/winnow/src/stream/mod.rs b/vendor/winnow/src/stream/mod.rs
index fcacbd78f..5f2152e27 100644
--- a/vendor/winnow/src/stream/mod.rs
+++ b/vendor/winnow/src/stream/mod.rs
@@ -2684,7 +2684,35 @@ fn memchr(token: u8, slice: &[u8]) -> Option<usize> {
#[cfg(feature = "simd")]
#[inline(always)]
fn memmem(slice: &[u8], tag: &[u8]) -> Option<usize> {
- memchr::memmem::find(slice, tag)
+ if tag.len() > slice.len() {
+ return None;
+ }
+
+ let (&substr_first, substr_rest) = match tag.split_first() {
+ Some(split) => split,
+ // an empty substring is found at position 0
+ // This matches the behavior of str.find("").
+ None => return Some(0),
+ };
+
+ if substr_rest.is_empty() {
+ return memchr::memchr(substr_first, slice);
+ }
+
+ let mut offset = 0;
+ let haystack = &slice[..slice.len() - substr_rest.len()];
+
+ while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) {
+ offset += position;
+ let next_offset = offset + 1;
+ if &slice[next_offset..][..substr_rest.len()] == substr_rest {
+ return Some(offset);
+ }
+
+ offset = next_offset;
+ }
+
+ None
}
#[cfg(not(feature = "simd"))]
diff --git a/vendor/winnow/src/trace/internals.rs b/vendor/winnow/src/trace/internals.rs
index b990ae7c7..c38b11eea 100644
--- a/vendor/winnow/src/trace/internals.rs
+++ b/vendor/winnow/src/trace/internals.rs
@@ -4,6 +4,63 @@ use std::io::Write;
use crate::error::ErrMode;
use crate::stream::Stream;
+use crate::*;
+
+pub struct Trace<P, D, I, O, E>
+where
+ P: Parser<I, O, E>,
+ I: Stream,
+ D: std::fmt::Display,
+{
+ parser: P,
+ name: D,
+ call_count: usize,
+ i: core::marker::PhantomData<I>,
+ o: core::marker::PhantomData<O>,
+ e: core::marker::PhantomData<E>,
+}
+
+impl<P, D, I, O, E> Trace<P, D, I, O, E>
+where
+ P: Parser<I, O, E>,
+ I: Stream,
+ D: std::fmt::Display,
+{
+ #[inline(always)]
+ pub fn new(parser: P, name: D) -> Self {
+ Self {
+ parser,
+ name,
+ call_count: 0,
+ i: Default::default(),
+ o: Default::default(),
+ e: Default::default(),
+ }
+ }
+}
+
+impl<P, D, I, O, E> Parser<I, O, E> for Trace<P, D, I, O, E>
+where
+ P: Parser<I, O, E>,
+ I: Stream,
+ D: std::fmt::Display,
+{
+ #[inline]
+ fn parse_next(&mut self, i: &mut I) -> PResult<O, E> {
+ let depth = Depth::new();
+ let original = i.checkpoint();
+ start(*depth, &self.name, self.call_count, i);
+
+ let res = self.parser.parse_next(i);
+
+ let consumed = i.offset_from(&original);
+ let severity = Severity::with_result(&res);
+ end(*depth, &self.name, self.call_count, consumed, severity);
+ self.call_count += 1;
+
+ res
+ }
+}
pub struct Depth {
depth: usize,
@@ -107,7 +164,7 @@ pub fn start<I: Stream>(
(debug_slice, eof)
};
- let writer = anstyle_stream::stderr();
+ let writer = anstream::stderr();
let mut writer = writer.lock();
let _ = writeln!(
writer,
@@ -159,7 +216,7 @@ pub fn end(
),
};
- let writer = anstyle_stream::stderr();
+ let writer = anstream::stderr();
let mut writer = writer.lock();
let _ = writeln!(
writer,
@@ -197,7 +254,7 @@ pub fn result(depth: usize, name: &dyn crate::lib::std::fmt::Display, severity:
),
};
- let writer = anstyle_stream::stderr();
+ let writer = anstream::stderr();
let mut writer = writer.lock();
let _ = writeln!(
writer,
diff --git a/vendor/winnow/src/trace/mod.rs b/vendor/winnow/src/trace/mod.rs
index 316733e9a..cd96e0258 100644
--- a/vendor/winnow/src/trace/mod.rs
+++ b/vendor/winnow/src/trace/mod.rs
@@ -49,25 +49,11 @@ compile_error!("`debug` requires `std`");
#[cfg_attr(not(feature = "debug"), inline(always))]
pub fn trace<I: Stream, O, E>(
name: impl crate::lib::std::fmt::Display,
- mut parser: impl Parser<I, O, E>,
+ parser: impl Parser<I, O, E>,
) -> impl Parser<I, O, E> {
#[cfg(feature = "debug")]
{
- let mut call_count = 0;
- move |i: &mut I| {
- let depth = internals::Depth::new();
- let original = i.checkpoint();
- internals::start(*depth, &name, call_count, i);
-
- let res = parser.parse_next(i);
-
- let consumed = i.offset_from(&original);
- let severity = internals::Severity::with_result(&res);
- internals::end(*depth, &name, call_count, consumed, severity);
- call_count += 1;
-
- res
- }
+ internals::Trace::new(parser, name)
}
#[cfg(not(feature = "debug"))]
{