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