summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/examples/json/parser_dispatch.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/winnow/examples/json/parser_dispatch.rs')
-rw-r--r--vendor/winnow/examples/json/parser_dispatch.rs103
1 files changed, 55 insertions, 48 deletions
diff --git a/vendor/winnow/examples/json/parser_dispatch.rs b/vendor/winnow/examples/json/parser_dispatch.rs
index 29d6d5f90..6fa722b45 100644
--- a/vendor/winnow/examples/json/parser_dispatch.rs
+++ b/vendor/winnow/examples/json/parser_dispatch.rs
@@ -11,7 +11,7 @@ use winnow::{
combinator::{alt, dispatch},
combinator::{delimited, preceded, separated_pair, terminated},
combinator::{fold_repeat, separated0},
- error::{ContextError, ParseError},
+ error::{AddContext, ParserError},
token::{any, none_of, take, take_while},
};
@@ -22,8 +22,8 @@ pub type Stream<'i> = &'i str;
/// The root element of a JSON parser is any value
///
/// A parser has the following signature:
-/// `Stream -> IResult<Stream, Output, Error>`, with `IResult` defined as:
-/// `type IResult<I, O, E = (I, ErrorKind)> = Result<(I, O), Err<E>>;`
+/// `&mut Stream -> PResult<Output, InputError>`, with `PResult` defined as:
+/// `type PResult<O, E = ErrorKind> = Result<O, ErrMode<E>>;`
///
/// most of the times you can ignore the error type and use the default (but this
/// examples shows custom error types later on!)
@@ -31,17 +31,17 @@ pub type Stream<'i> = &'i str;
/// Here we use `&str` as input type, but parsers can be generic over
/// the input type, work directly with `&[u8]`, or any other type that
/// implements the required traits.
-pub fn json<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, JsonValue, E> {
+pub fn json<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<JsonValue, E> {
delimited(ws, json_value, ws).parse_next(input)
}
/// `alt` is a combinator that tries multiple parsers one by one, until
/// one of them succeeds
-fn json_value<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, JsonValue, E> {
+fn json_value<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<JsonValue, E> {
// `dispatch` gives you `match`-like behavior compared to `alt` successively trying different
// implementations.
dispatch!(peek(any);
@@ -62,7 +62,7 @@ fn json_value<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static
/// `tag(string)` generates a parser that recognizes the argument string.
///
/// This also shows returning a sub-slice of the original input
-fn null<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, &'i str, E> {
+fn null<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<&'i str, E> {
// This is a parser that returns `"null"` if it sees the string "null", and
// an error otherwise
"null".parse_next(input)
@@ -70,7 +70,7 @@ fn null<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>,
/// We can combine `tag` with other functions, like `value` which returns a given constant value on
/// success.
-fn true_<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, bool, E> {
+fn true_<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<bool, E> {
// This is a parser that returns `true` if it sees the string "true", and
// an error otherwise
"true".value(true).parse_next(input)
@@ -78,7 +78,7 @@ fn true_<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>
/// We can combine `tag` with other functions, like `value` which returns a given constant value on
/// success.
-fn false_<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, bool, E> {
+fn false_<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<bool, E> {
// This is a parser that returns `false` if it sees the string "false", and
// an error otherwise
"false".value(false).parse_next(input)
@@ -86,9 +86,9 @@ fn false_<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i
/// This parser gathers all `char`s up into a `String`with a parse to recognize the double quote
/// character, before the string (using `preceded`) and after the string (using `terminated`).
-fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, String, E> {
+fn string<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<String, E> {
preceded(
'\"',
// `cut_err` transforms an `ErrMode::Backtrack(e)` to `ErrMode::Cut(e)`, signaling to
@@ -111,8 +111,8 @@ fn string<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
/// You can mix the above declarative parsing with an imperative style to handle more unique cases,
/// like escaping
-fn character<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, char, E> {
- let (input, c) = none_of("\"").parse_next(input)?;
+fn character<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<char, E> {
+ let c = none_of('\"').parse_next(input)?;
if c == '\\' {
dispatch!(any;
'"' => success('"'),
@@ -128,13 +128,11 @@ fn character<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream
)
.parse_next(input)
} else {
- Ok((input, c))
+ Ok(c)
}
}
-fn unicode_escape<'i, E: ParseError<Stream<'i>>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, char, E> {
+fn unicode_escape<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<char, E> {
alt((
// Not a surrogate
u16_hex
@@ -156,7 +154,7 @@ fn unicode_escape<'i, E: ParseError<Stream<'i>>>(
.parse_next(input)
}
-fn u16_hex<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, u16, E> {
+fn u16_hex<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<u16, E> {
take(4usize)
.verify_map(|s| u16::from_str_radix(s, 16).ok())
.parse_next(input)
@@ -166,9 +164,9 @@ fn u16_hex<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
-fn array<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, Vec<JsonValue>, E> {
+fn array<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<Vec<JsonValue>, E> {
preceded(
('[', ws),
cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))),
@@ -177,9 +175,9 @@ fn array<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>
.parse_next(input)
}
-fn object<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, HashMap<String, JsonValue>, E> {
+fn object<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<HashMap<String, JsonValue>, E> {
preceded(
('{', ws),
cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))),
@@ -188,22 +186,22 @@ fn object<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>
.parse_next(input)
}
-fn key_value<'i, E: ParseError<Stream<'i>> + ContextError<Stream<'i>, &'static str>>(
- input: Stream<'i>,
-) -> IResult<Stream<'i>, (String, JsonValue), E> {
+fn key_value<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
+ input: &mut Stream<'i>,
+) -> PResult<(String, JsonValue), E> {
separated_pair(string, cut_err((ws, ':', ws)), json_value).parse_next(input)
}
/// Parser combinators are constructed from the bottom up:
/// first we write parsers for the smallest elements (here a space character),
/// then we'll combine them in larger parsers
-fn ws<'i, E: ParseError<Stream<'i>>>(input: Stream<'i>) -> IResult<Stream<'i>, &'i str, E> {
+fn ws<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<&'i str, E> {
// Combinators like `take_while` return a function. That function is the
// parser,to which we can pass the input
take_while(0.., WS).parse_next(input)
}
-const WS: &str = " \t\r\n";
+const WS: &[char] = &[' ', '\t', '\r', '\n'];
#[cfg(test)]
mod test {
@@ -213,28 +211,37 @@ mod test {
#[allow(clippy::useless_attribute)]
#[allow(dead_code)] // its dead for benches
- type Error<'i> = winnow::error::Error<&'i str>;
+ type Error<'i> = winnow::error::InputError<&'i str>;
#[test]
fn json_string() {
- assert_eq!(string::<Error<'_>>("\"\""), Ok(("", "".to_string())));
- assert_eq!(string::<Error<'_>>("\"abc\""), Ok(("", "abc".to_string())));
assert_eq!(
- string::<Error<'_>>("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""),
+ string::<Error<'_>>.parse_peek("\"\""),
+ Ok(("", "".to_string()))
+ );
+ assert_eq!(
+ string::<Error<'_>>.parse_peek("\"abc\""),
+ Ok(("", "abc".to_string()))
+ );
+ assert_eq!(
+ string::<Error<'_>>
+ .parse_peek("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""),
Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01β€”β€”def".to_string())),
);
assert_eq!(
- string::<Error<'_>>("\"\\uD83D\\uDE10\""),
+ string::<Error<'_>>.parse_peek("\"\\uD83D\\uDE10\""),
Ok(("", "😐".to_string()))
);
- assert!(string::<Error<'_>>("\"").is_err());
- assert!(string::<Error<'_>>("\"abc").is_err());
- assert!(string::<Error<'_>>("\"\\\"").is_err());
- assert!(string::<Error<'_>>("\"\\u123\"").is_err());
- assert!(string::<Error<'_>>("\"\\uD800\"").is_err());
- assert!(string::<Error<'_>>("\"\\uD800\\uD800\"").is_err());
- assert!(string::<Error<'_>>("\"\\uDC00\"").is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"").is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"abc").is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"\\\"").is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"\\u123\"").is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"\\uD800\"").is_err());
+ assert!(string::<Error<'_>>
+ .parse_peek("\"\\uD800\\uD800\"")
+ .is_err());
+ assert!(string::<Error<'_>>.parse_peek("\"\\uDC00\"").is_err());
}
#[test]
@@ -252,7 +259,7 @@ mod test {
.collect(),
);
- assert_eq!(json::<Error<'_>>(input), Ok(("", expected)));
+ assert_eq!(json::<Error<'_>>.parse_peek(input), Ok(("", expected)));
}
#[test]
@@ -263,7 +270,7 @@ mod test {
let expected = Array(vec![Num(42.0), Str("x".to_string())]);
- assert_eq!(json::<Error<'_>>(input), Ok(("", expected)));
+ assert_eq!(json::<Error<'_>>.parse_peek(input), Ok(("", expected)));
}
#[test]
@@ -285,7 +292,7 @@ mod test {
"#;
assert_eq!(
- json::<Error<'_>>(input),
+ json::<Error<'_>>.parse_peek(input),
Ok((
"",
Object(