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