winnow/
lib.rs

1//! > winnow, making parsing a breeze
2//!
3//! `winnow` is a parser combinator library
4//!
5//! Quick links:
6//! - [List of combinators][crate::combinator]
7//! - [Tutorial][_tutorial::chapter_0]
8//! - [Special Topics][_topic]
9//! - [Discussions](https://github.com/winnow-rs/winnow/discussions)
10//! - [CHANGELOG](https://github.com/winnow-rs/winnow/blob/v0.7.10/CHANGELOG.md) (includes major version migration
11//!   guides)
12//!
13//! ## Aspirations
14//!
15//! `winnow` aims to be your "do everything" parser, much like people treat regular expressions.
16//!
17//! In roughly priority order:
18//! 1. Support writing parser declaratively while not getting in the way of imperative-style
19//!    parsing when needed, working as an open-ended toolbox rather than a close-ended framework.
20//! 2. Flexible enough to be used for any application, including parsing strings, binary data,
21//!    or separate [lexing and parsing phases][_topic::lexing]
22//! 3. Zero-cost abstractions, making it easy to write high performance parsers
23//! 4. Easy to use, making it trivial for one-off uses
24//!
25//! In addition:
26//! - Resilient maintainership, including
27//!   - Willing to break compatibility rather than batching up breaking changes in large releases
28//!   - Leverage feature flags to keep one active branch
29//! - We will support the last 6 months of rust releases (MSRV, currently 1.64.0)
30//!
31//! See also [Special Topic: Why winnow?][crate::_topic::why]
32//!
33//! ## Example
34//!
35//! Run
36//! ```console
37//! $ cargo add winnow
38//! ```
39//!
40//! Then use it to parse:
41//! ```rust
42//! # #[cfg(feature = "alloc")] {
43#![doc = include_str!("../examples/css/parser.rs")]
44//! # }
45//! ```
46//!
47//! See also the [Tutorial][_tutorial::chapter_0] and [Special Topics][_topic]
48
49#![cfg_attr(docsrs, feature(doc_auto_cfg))]
50#![cfg_attr(docsrs, feature(doc_cfg))]
51#![cfg_attr(docsrs, feature(extended_key_value_attributes))]
52#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
53#![warn(missing_docs)]
54#![warn(clippy::std_instead_of_core)]
55#![warn(clippy::std_instead_of_alloc)]
56#![warn(clippy::print_stderr)]
57#![warn(clippy::print_stdout)]
58
59#[cfg(feature = "alloc")]
60#[cfg_attr(test, macro_use)]
61#[allow(unused_extern_crates)]
62extern crate alloc;
63
64#[doc = include_str!("../README.md")]
65#[cfg(doctest)]
66pub struct ReadmeDoctests;
67
68/// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does
69/// it, albeit there it is not public.
70#[doc(hidden)]
71pub(crate) mod lib {
72    #![allow(unused_imports)]
73
74    /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally,
75    /// as well as `core` or `std`
76    #[cfg(not(feature = "std"))]
77    /// internal std exports for no_std compatibility
78    pub(crate) mod std {
79        #[doc(hidden)]
80        #[cfg(not(feature = "alloc"))]
81        pub(crate) use core::borrow;
82
83        #[cfg(feature = "alloc")]
84        #[doc(hidden)]
85        pub(crate) use alloc::{borrow, boxed, collections, string, vec};
86
87        #[doc(hidden)]
88        pub(crate) use core::{
89            cmp, convert, fmt, hash, iter, mem, ops, option, result, slice, str,
90        };
91    }
92
93    #[cfg(feature = "std")]
94    /// internal std exports for `no_std` compatibility
95    pub(crate) mod std {
96        #![allow(clippy::std_instead_of_core)]
97        #![allow(clippy::std_instead_of_alloc)]
98        #[doc(hidden)]
99        pub(crate) use std::{
100            borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, result, slice,
101            str, string, vec,
102        };
103    }
104}
105
106pub(crate) mod util {
107    #[allow(dead_code)]
108    pub(crate) fn from_fn<F: Fn(&mut core::fmt::Formatter<'_>) -> core::fmt::Result>(
109        f: F,
110    ) -> FromFn<F> {
111        FromFn(f)
112    }
113
114    pub(crate) struct FromFn<F>(F)
115    where
116        F: Fn(&mut core::fmt::Formatter<'_>) -> core::fmt::Result;
117
118    impl<F> core::fmt::Debug for FromFn<F>
119    where
120        F: Fn(&mut core::fmt::Formatter<'_>) -> core::fmt::Result,
121    {
122        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123            (self.0)(f)
124        }
125    }
126
127    impl<F> core::fmt::Display for FromFn<F>
128    where
129        F: Fn(&mut core::fmt::Formatter<'_>) -> core::fmt::Result,
130    {
131        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
132            (self.0)(f)
133        }
134    }
135}
136
137#[macro_use]
138mod macros;
139
140#[macro_use]
141pub mod error;
142
143mod parser;
144
145pub mod stream;
146
147pub mod ascii;
148pub mod binary;
149pub mod combinator;
150pub mod token;
151
152#[cfg(feature = "unstable-doc")]
153pub mod _topic;
154#[cfg(feature = "unstable-doc")]
155pub mod _tutorial;
156
157/// Core concepts available for glob import
158///
159/// Including
160/// - [`StreamIsPartial`][crate::stream::StreamIsPartial]
161/// - [`Parser`]
162///
163/// ## Example
164///
165/// ```rust
166/// use winnow::prelude::*;
167///
168/// fn parse_data(input: &mut &str) -> ModalResult<u64> {
169///     // ...
170/// #   winnow::ascii::dec_uint(input)
171/// }
172///
173/// fn main() {
174///   let result = parse_data.parse("100");
175///   assert_eq!(result, Ok(100));
176/// }
177/// ```
178pub mod prelude {
179    pub use crate::error::ModalError as _;
180    pub use crate::error::ParserError as _;
181    pub use crate::stream::AsChar as _;
182    pub use crate::stream::ContainsToken as _;
183    pub use crate::stream::Stream as _;
184    pub use crate::stream::StreamIsPartial as _;
185    pub use crate::ModalParser;
186    pub use crate::ModalResult;
187    pub use crate::Parser;
188    #[cfg(feature = "unstable-recover")]
189    #[cfg(feature = "std")]
190    pub use crate::RecoverableParser as _;
191
192    #[cfg(test)]
193    pub(crate) use crate::TestResult;
194}
195
196pub use error::ModalResult;
197pub use error::Result;
198pub use parser::*;
199pub use stream::BStr;
200pub use stream::Bytes;
201pub use stream::LocatingSlice;
202pub use stream::Partial;
203pub use stream::Stateful;
204pub use stream::Str;
205
206#[cfg(test)]
207pub(crate) use error::TestResult;