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.5.37/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 binary data, strings, or
21 //!    separate lexing and parsing phases
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(not(feature = "std"), no_std)]
53 #![warn(missing_docs)]
54 #![warn(clippy::std_instead_of_core)]
55 // BEGIN - Embark standard lints v6 for Rust 1.55+
56 // do not change or add/remove here, but one can add exceptions after this section
57 // for more info see: <https://github.com/EmbarkStudios/rust-ecosystem/issues/59>
58 // "-Dunsafe_code",
59 #![warn(clippy::all)]
60 #![warn(clippy::await_holding_lock)]
61 #![warn(clippy::char_lit_as_u8)]
62 #![warn(clippy::checked_conversions)]
63 #![warn(clippy::dbg_macro)]
64 #![warn(clippy::debug_assert_with_mut_call)]
65 #![warn(clippy::doc_markdown)]
66 #![warn(clippy::empty_enum)]
67 #![warn(clippy::enum_glob_use)]
68 #![warn(clippy::exit)]
69 #![warn(clippy::expl_impl_clone_on_copy)]
70 #![warn(clippy::explicit_deref_methods)]
71 #![warn(clippy::explicit_into_iter_loop)]
72 #![warn(clippy::fallible_impl_from)]
73 #![warn(clippy::filter_map_next)]
74 #![warn(clippy::flat_map_option)]
75 #![warn(clippy::float_cmp_const)]
76 #![warn(clippy::fn_params_excessive_bools)]
77 #![warn(clippy::from_iter_instead_of_collect)]
78 #![warn(clippy::if_let_mutex)]
79 #![warn(clippy::implicit_clone)]
80 #![warn(clippy::imprecise_flops)]
81 #![warn(clippy::inefficient_to_string)]
82 #![warn(clippy::invalid_upcast_comparisons)]
83 #![warn(clippy::large_digit_groups)]
84 #![warn(clippy::large_stack_arrays)]
85 #![warn(clippy::large_types_passed_by_value)]
86 #![warn(clippy::let_unit_value)]
87 #![warn(clippy::linkedlist)]
88 #![warn(clippy::lossy_float_literal)]
89 #![warn(clippy::macro_use_imports)]
90 #![warn(clippy::manual_ok_or)]
91 #![warn(clippy::map_err_ignore)]
92 #![warn(clippy::map_flatten)]
93 #![warn(clippy::map_unwrap_or)]
94 #![warn(clippy::match_on_vec_items)]
95 #![warn(clippy::match_same_arms)]
96 #![warn(clippy::match_wild_err_arm)]
97 #![warn(clippy::match_wildcard_for_single_variants)]
98 #![warn(clippy::mem_forget)]
99 #![warn(clippy::mismatched_target_os)]
100 #![warn(clippy::missing_enforced_import_renames)]
101 #![warn(clippy::mut_mut)]
102 #![warn(clippy::mutex_integer)]
103 #![warn(clippy::needless_borrow)]
104 #![warn(clippy::needless_continue)]
105 #![warn(clippy::needless_for_each)]
106 #![warn(clippy::option_option)]
107 #![warn(clippy::path_buf_push_overwrite)]
108 #![warn(clippy::ptr_as_ptr)]
109 #![warn(clippy::rc_mutex)]
110 #![warn(clippy::ref_option_ref)]
111 #![warn(clippy::rest_pat_in_fully_bound_structs)]
112 #![warn(clippy::same_functions_in_if_condition)]
113 #![warn(clippy::semicolon_if_nothing_returned)]
114 #![warn(clippy::single_match_else)]
115 #![warn(clippy::string_add_assign)]
116 #![warn(clippy::string_add)]
117 #![warn(clippy::string_lit_as_bytes)]
118 #![warn(clippy::string_to_string)]
119 #![warn(clippy::todo)]
120 #![warn(clippy::trait_duplication_in_bounds)]
121 #![warn(clippy::unimplemented)]
122 #![warn(clippy::unnested_or_patterns)]
123 #![warn(clippy::unused_self)]
124 #![warn(clippy::useless_transmute)]
125 #![warn(clippy::verbose_file_reads)]
126 #![warn(clippy::zero_sized_map_values)]
127 #![warn(future_incompatible)]
128 #![warn(nonstandard_style)]
129 #![warn(rust_2018_idioms)]
130 // END - Embark standard lints v6 for Rust 1.55+
131 #![allow(clippy::branches_sharing_code)]
132 #![allow(clippy::collapsible_else_if)]
133 #![allow(clippy::if_same_then_else)]
134 #![allow(clippy::bool_assert_comparison)]
135 #![allow(clippy::let_and_return)]
136 #![allow(clippy::assertions_on_constants)]
137 #![allow(clippy::map_unwrap_or)]
138 #![allow(clippy::single_match_else)]
139 #![allow(clippy::single_match)]
140 #![allow(clippy::unnested_or_patterns)]
141 #[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
142 #[cfg(feature = "alloc")]
143 #[cfg_attr(test, macro_use)]
144 extern crate alloc;
145 #[cfg(doctest)]
146 extern crate doc_comment;
147 
148 #[cfg(doctest)]
149 doc_comment::doctest!("../README.md");
150 
151 /// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does
152 /// it, albeit there it is not public.
153 #[doc(hidden)]
154 pub(crate) mod lib {
155     /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally,
156     /// as well as `core` or `std`
157     #[cfg(not(feature = "std"))]
158     /// internal std exports for no_std compatibility
159     pub mod std {
160         #[doc(hidden)]
161         #[cfg(not(feature = "alloc"))]
162         pub use core::borrow;
163 
164         #[cfg(feature = "alloc")]
165         #[doc(hidden)]
166         pub use alloc::{borrow, boxed, collections, string, vec};
167 
168         #[doc(hidden)]
169         pub use core::{cmp, convert, fmt, hash, iter, mem, ops, option, result, slice, str};
170 
171         /// internal reproduction of std prelude
172         #[doc(hidden)]
173         pub mod prelude {
174             pub use core::prelude as v1;
175         }
176     }
177 
178     #[cfg(feature = "std")]
179     /// internal std exports for `no_std` compatibility
180     pub mod std {
181         #![allow(clippy::std_instead_of_core)]
182         #[doc(hidden)]
183         pub use std::{
184             alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option,
185             result, slice, str, string, vec,
186         };
187 
188         /// internal reproduction of std prelude
189         #[doc(hidden)]
190         pub mod prelude {
191             pub use std::prelude as v1;
192         }
193     }
194 }
195 
196 #[macro_use]
197 mod macros;
198 
199 #[macro_use]
200 pub mod error;
201 
202 mod parser;
203 
204 pub mod stream;
205 
206 pub mod ascii;
207 pub mod binary;
208 pub mod combinator;
209 pub mod token;
210 pub mod trace;
211 
212 #[cfg(feature = "unstable-doc")]
213 pub mod _topic;
214 #[cfg(feature = "unstable-doc")]
215 pub mod _tutorial;
216 
217 /// Core concepts available for glob import
218 ///
219 /// Including
220 /// - [`StreamIsPartial`][crate::stream::StreamIsPartial]
221 /// - [`Parser`]
222 ///
223 /// ## Example
224 ///
225 /// ```rust
226 /// use winnow::prelude::*;
227 ///
228 /// fn parse_data(input: &mut &str) -> PResult<u64> {
229 ///     // ...
230 /// #   winnow::ascii::dec_uint(input)
231 /// }
232 ///
233 /// fn main() {
234 ///   let result = parse_data.parse("100");
235 ///   assert_eq!(result, Ok(100));
236 /// }
237 /// ```
238 pub mod prelude {
239     pub use crate::stream::StreamIsPartial as _;
240     pub use crate::IResult;
241     pub use crate::PResult;
242     pub use crate::Parser;
243     #[cfg(feature = "unstable-recover")]
244     pub use crate::RecoverableParser as _;
245 }
246 
247 pub use error::IResult;
248 pub use error::PResult;
249 pub use parser::*;
250 pub use stream::BStr;
251 pub use stream::Bytes;
252 pub use stream::Located;
253 pub use stream::Partial;
254 pub use stream::Stateful;
255 pub use stream::Str;
256