summaryrefslogtreecommitdiffstats
path: root/vendor/winnow/src/_tutorial/chapter_7.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/winnow/src/_tutorial/chapter_7.rs')
-rw-r--r--vendor/winnow/src/_tutorial/chapter_7.rs111
1 files changed, 111 insertions, 0 deletions
diff --git a/vendor/winnow/src/_tutorial/chapter_7.rs b/vendor/winnow/src/_tutorial/chapter_7.rs
new file mode 100644
index 000000000..8c27cb5ad
--- /dev/null
+++ b/vendor/winnow/src/_tutorial/chapter_7.rs
@@ -0,0 +1,111 @@
+//! # Chapter 7: Integrating the Parser
+//!
+//! So far, we've highlighted how to incrementally parse, but how do we bring this all together
+//! into our application?
+//!
+//! The type we've been working with looks like:
+//! ```rust
+//! # use winnow::error::VerboseError;
+//! # use winnow::error::ErrMode;
+//! type IResult<'i, O> = Result<
+//! (&'i str, O),
+//! ErrMode<
+//! VerboseError<&'i str>
+//! >
+//! >;
+//! ```
+//! 1. We have to decide what to do about the `remainder` of the input.
+//! 2. The error type is not compatible with the rest of the Rust ecosystem
+//!
+//! Normally, Rust applications want errors that are `std::error::Error + Send + Sync + 'static`
+//! meaning:
+//! - They implement the [`std::error::Error`] trait
+//! - They can be sent across threads
+//! - They are safe to be referenced across threads
+//! - They do not borrow
+//!
+//! winnow provides some helpers for this:
+//! ```rust
+//! # use winnow::IResult;
+//! # use winnow::bytes::take_while1;
+//! # use winnow::branch::dispatch;
+//! # use winnow::bytes::take;
+//! # use winnow::combinator::fail;
+//! use winnow::Parser;
+//! use winnow::error::Error;
+//!
+//! #[derive(Debug, PartialEq, Eq)]
+//! pub struct Hex(usize);
+//!
+//! impl std::str::FromStr for Hex {
+//! type Err = Error<String>;
+//!
+//! fn from_str(input: &str) -> Result<Self, Self::Err> {
+//! parse_digits
+//! .map(Hex)
+//! .parse(input)
+//! .map_err(|e| e.into_owned())
+//! }
+//! }
+//!
+//! // ...
+//! # fn parse_digits(input: &str) -> IResult<&str, usize> {
+//! # dispatch!(take(2usize);
+//! # "0b" => parse_bin_digits.map_res(|s| usize::from_str_radix(s, 2)),
+//! # "0o" => parse_oct_digits.map_res(|s| usize::from_str_radix(s, 8)),
+//! # "0d" => parse_dec_digits.map_res(|s| usize::from_str_radix(s, 10)),
+//! # "0x" => parse_hex_digits.map_res(|s| usize::from_str_radix(s, 16)),
+//! # _ => fail,
+//! # ).parse_next(input)
+//! # }
+//! #
+//! # fn parse_bin_digits(input: &str) -> IResult<&str, &str> {
+//! # take_while1((
+//! # ('0'..='7'),
+//! # )).parse_next(input)
+//! # }
+//! #
+//! # fn parse_oct_digits(input: &str) -> IResult<&str, &str> {
+//! # take_while1((
+//! # ('0'..='7'),
+//! # )).parse_next(input)
+//! # }
+//! #
+//! # fn parse_dec_digits(input: &str) -> IResult<&str, &str> {
+//! # take_while1((
+//! # ('0'..='9'),
+//! # )).parse_next(input)
+//! # }
+//! #
+//! # fn parse_hex_digits(input: &str) -> IResult<&str, &str> {
+//! # take_while1((
+//! # ('0'..='9'),
+//! # ('A'..='F'),
+//! # ('a'..='f'),
+//! # )).parse_next(input)
+//! # }
+//!
+//! fn main() {
+//! let input = "0x1a2b";
+//! assert_eq!(input.parse::<Hex>().unwrap(), Hex(0x1a2b));
+//!
+//! let input = "0x1a2b Hello";
+//! assert!(input.parse::<Hex>().is_err());
+//! let input = "ghiHello";
+//! assert!(input.parse::<Hex>().is_err());
+//! }
+//! ```
+//! - Ensures we hit [`eof`]
+//! - Removes the [`ErrMode`] wrapper
+//!
+//! [`Error::into_owned`]:
+//! - Converts the `&str` in `Error` to `String` which enables support for [`std::error::Error`]
+
+#![allow(unused_imports)]
+use super::chapter_1;
+use crate::combinator::eof;
+use crate::error::ErrMode;
+use crate::error::Error;
+use crate::IResult;
+
+pub use super::chapter_6 as previous;