1 //! # Why `winnow`? 2 //! 3 //! To answer this question, it will be useful to contrast this with other approaches to parsing. 4 //! 5 //! <div class="warning"> 6 //! 7 //! **Note:** This will focus on principles and priorities. For a deeper and wider wider 8 //! comparison with other Rust parser libraries, see 9 //! [parse-rosetta-rs](https://github.com/rosetta-rs/parse-rosetta-rs). 10 //! 11 //! </div> 12 //! 13 //! ## Hand-written parsers 14 //! 15 //! Typically, a hand-written parser gives you the flexibility to get 16 //! - Fast parse performance 17 //! - Fast compile-time 18 //! - Small binary sizes 19 //! - High quality error message 20 //! - Fewer dependencies to audit 21 //! 22 //! However, this comes at the cost of doing it all yourself, including 23 //! - Optimizing for each of the above characteristics you care about 24 //! - Ensuring the safety of any `unsafe` code (buffer overflows being a common bug with parsers) 25 //! - Being aware of, familiar with, and correctly implement the relevant algorithms. 26 //! matklad, who has written two rust compile frontends, commented 27 //! ["I’ve implemented a production-grade Pratt parser once, but I no longer immediately understand that code :-)"](https://matklad.github.io/2020/04/13/simple-but-powerful-pratt-parsing.html) 28 //! 29 //! This approach works well if: 30 //! - Your format is small and is unlikely to change 31 //! - Your format is large but you have people who can focus solely on parsing, like with large 32 //! programming languages 33 //! 34 //! ## `winnow` 35 //! 36 //! Unlike traditional programming language parsers that use 37 //! [lex](https://en.wikipedia.org/wiki/Lex_(software)) or 38 //! [yacc](https://en.wikipedia.org/wiki/Yacc), you can think of `winnow` as a general version of 39 //! the helpers you would create along the way to writing a hand-written parser. 40 //! 41 //! `winnow` includes support for: 42 //! - Zero-copy parsing 43 //! - [Parse traces][trace] for easier debugging 44 //! - [Streaming parsing][Partial] for network communication or large file 45 //! - [Stateful] parsers 46 //! 47 //! For binary formats, `winnow` includes: 48 //! - [A hexadecimal view][crate::Bytes] in [trace] 49 //! - [TLV](https://en.wikipedia.org/wiki/Type-length-value) (e.g. [`length_take`]) 50 //! - Some common parsers to help get started, like numbers 51 //! 52 //! For text formats, `winnow` includes: 53 //! - [Tracking of spans][crate::LocatingSlice] 54 //! - [A textual view when parsing as bytes][crate::BStr] in [trace] 55 //! - Ability to evaluate directly, parse to an AST, or lex and parse the format 56 //! 57 //! This works well for: 58 //! - Prototyping for what will be a hand-written parser 59 //! - When you want to minimize the work to evolve your format 60 //! - When you don't have contributors focused solely on parsing and your grammar is large enough 61 //! to be unwieldy to hand write. 62 //! 63 //! ## `nom` 64 //! 65 //! `winnow` is a fork of the venerable [`nom`](https://crates.io/crates/nom). The difference 66 //! between them is largely in priorities. `nom` prioritizes: 67 //! - Lower churn for existing users while `winnow` is trying to find ways to make things better 68 //! for the parsers yet to be written. 69 //! - Having a small core, relying on external crates like 70 //! [`nom-locate`](https://crates.io/crates/nom_locate) and 71 //! [`nom-supreme`](https://crates.io/crates/nom-supreme), encouraging flexibility among users 72 //! and to not block users on new features being merged while `winnow` aims to include all the 73 //! fundamentals for parsing to ensure the experience is cohesive and high quality. 74 //! 75 //! For more details, see the [design differences][super::nom#api-differences]. 76 //! 77 //! See also our [nom migration guide][super::nom#migrating-from-nom]. 78 //! 79 //! ## `chumsky` 80 //! 81 //! [`chumsky`](https://crates.io/crates/chumsky) is an up and coming parser-combinator library 82 //! that includes advanced features like error recovery. 83 //! 84 //! Probably the biggest diverging philosophy is `chumsky`s stance: 85 //! 86 //! > "If you need to implement either `Parser` or `Strategy` by hand, that's a problem that needs fixing". 87 //! 88 //! This is under "batteries included" but it also ties into the feeling that `chumsky` acts more like 89 //! a framework. Instead of composing together helpers, you are expected to do everything through 90 //! their system to the point that it is non-trivial to implement their `Parser` trait and are 91 //! encouraged to use the 92 //! [`custom`](https://docs.rs/chumsky/0.9.0/chumsky/primitive/fn.custom.html) helper. This 93 //! requires re-framing everything to fit within their model and makes the code harder to understand 94 //! and debug as you are working with abstract operations that will eventually be applied 95 //! rather than directly with the parsers. 96 //! 97 //! In contrast, `winnow` is an introspectable toolbox that can easily be customized at any level. 98 //! Probably the biggest thing that `winnow` loses out on is optimizations from ["parse modes" via 99 //! GATs](https://github.com/zesterer/chumsky/pull/82) which allows downstream parsers to tell 100 //! upstream parsers when information will be discarded, allowing bypassing expensive operations, 101 //! like allocations. This requires a lot more complex interaction with parsers that isn't as 102 //! trivial to do with bare functions which would lose out on any of that side-band information. 103 //! Instead, we work around this with things like the [`Accumulate`] trait. 104 105 #![allow(unused_imports)] 106 use crate::binary::length_take; 107 use crate::combinator::trace; 108 use crate::stream::Accumulate; 109 use crate::stream::Partial; 110 use crate::stream::Stateful; 111