NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
crates.io · #76 most downloaded on crates.io
A byte-oriented, zero-copy, parser combinators library
Last release 2 months ago
13 Jul 2026
Release timing varies
gaps range from 8 days to 3 months
Nearly every release is documented
notes for 56 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
111 releases · first in 2023
One column per quarter.
Deprecate length_data in favor of length_take
length_data in favor of length_takelength_value in favor of length_and_thenlength_count in favor of length_repeatConsistently support FnMut for predicates, not just Fn
FnMut for predicates, not just Fnnom migration experience### Documentation - Add nom migration guide
nom migration guideCorrectly point to error location in InputErrors Display for single-line input
InputErrors Display for single-line inputSupport Accumulate for BTreeSet and HashSet
Accumulate for BTreeSet and HashSetAdd more patterns for token::take_until[01]
token::take_until[01]Optimize take_until* when parsing &str
take_until* when parsing &strDeprecated take_till0, take_till1 in favor of take_till
take_till ranged parsertake_till0, take_till1 in favor of take_tillDeprecated tag_no_case in favor of tag(Caseless(...))
Caseless to make it easier to add case insensitivity to any parser.tag_no_case in favor of tag(Caseless(...))Deprecated separated0 and separated1 in favor of separated
separated combinatorseparated0 and separated1 in favor of separatedDeprecated Uint impls for signed numbers
Accumulate for HashMap with custom hashersUint impls for signed numbersProvide lexer/parser example with details on handling of custom tokens
Correctly calculate offset_from for non-byte slices
offset_from for non-byte slicesImprove build times with debug when closures are used
debug when closures are usedSpeed up take_until when simd is enabled
take_until when simd is enabledErrMode inlining for improving gitoxide
ErrMode inlining for improving gitoxideTry inlining more wrapper functions
### Features - Impl Clone for ContextError
Clone for ContextError### Features - Impl Display for StrContext
Display for StrContextImprove rendering of ErrorKind in other errors
ErrorKind in other errorsAdd back in VerboseError to help with migrations
TreeError::into_ownedError for TreeErrorVerboseError to help with migrations### Features - Support Display for TreeError
Display for TreeErrorNew TreeError for showing full error path in tests
TreeError for showing full error path in testsInputError::map_input for making input types nicer for test failuresalt([...]) fails, or the errors together, like alt((...))
alt([...]) fails, or the errors together, like alt((...))### Internal - Update dependencies
implement AddContext for ErrMode for easier direct construction
AddContext for ErrMode for easier direct construction### Features - Allow [P; N] arrays within alt
[P; N] arrays within alt### Features - Added ParseError::into_inner
ParseError::into_innerProcess all deprecation warnings
Preparation: 0. Upgrade to the latest 0.4 release
winnow::branch with winnow::combinatorwinnow::bytes with winnow::tokenOffset::offset_to with Offset::offset_fromParseError with ParserErrorContextError with AddContextError with InputErrorimpl Parser over impl FnMut to reduce the size of the upgrade commit since the FnMut signature will changeErrModes trait impls to make the code more independent of the current error typewinnow::trace::trace to make it easier to debug problems on upgradeFor the actual upgrade, there are two approaches that can be mixed.
Switch to new, imperative APIs
IResult<I, O, E> with PResult<O, E> (E is still defaulted but to ContextError)I parameter with &mut Ifn(&mut &str) -> PResult<&str>, a lifetime will be needed: fn<'i>(&mut &'i str) -> PResult<&'i str>move |input| might need to be updated to move |input: &mut _|parse_next to return (input, output) to outputErrMode::Backtrace, you might need to input.reset(checkpoint) to revert the parser stateParser::parseMaintain pure-functional APIs
Parser::parse_next with Parser::parse_peekStream::next_token with Stream::peek_tokenStream::next_slice with Stream::peek_sliceFnMut(I) -> IResult<I, O, E> parsers with winnow::unpeekParser::parseExample: toml_edit:
Example: winnow:
Example: chumskys json bench:
Parser::parse_next (and the impl Parser for FnMut) now take &mut I and return PResult
Parser::parse to allow quality errors without requiring E to carry Iimpl ContainsToken for &str (e.g. one_of("abc") since it takes 5x more time leading to easily avoidable slow downs
['a', 'b', 'c'] or 'a'..='c' (see 08b3e57 for examples)ParserError and FromExternalError from accepting I to &IParseError to ParserErrorContextError to AddContextError to InputErrorOffset::offset_to in favor of Offset_offset_fromtrace that allowed parsers to change input to point to
a different string (this wasn't present in other parsers relying on
Offset::offset_from)Offset bounds, requiring changing a.offset_from(b) to a.offset_from(&b)bytes to token to clarify its scopecharacter to ascii to make it agnostic of char tokensbinary module
bits -> binary::bitsnumbermulti::length_*combinator
sequencebranchmultiStream trait changed
Stream::raw addedStream::next_token renamed to Stream::peek_tokenStream::next_slice renamed to Stream::peek_sliceStream::next_token and Stream::next_slice addedStream::finish and Stream::peek_finishStream::Checkpoint, Stream::checkpoint, and Stream::reset addedOffset<Stream::Checkpoint> is a new super traitContextError, a lightweight ParserError that supports AddContext (default for PResult)Stream::finish and Stream::peek_finish for making it easier to capture all remaining contentErrMode::into_inner for unifying Cut and BacktrackErrorKind as a ParserErrorBStr and Bytes Debug impl, rather than &[u8]impl ContainsToken for &str (e.g. one_of("abc") since it takes 5x more time leading to easily avoidable slow downsStream imperatively with &mut I rather than requiring returning the updating error location
parser(I) -> (I, O) to parser(&mut I) -> Ochore: Release winnow version 0.4.12
chore: Release winnow version 0.4.12
bytes, branch, and sequenceBackport v0.5 performance improvements
Additional inlining to make v0.4 and v0.5 performance differences focus on architecture and not additional changes.
Add aliases for renamed APIs in v0.5
error::AddContext which wraps error::ContextErrorerror::ParserError which wraps error::ParseErrorerror::InputError which wraps error::ErrorAdd aliases for renamed APIs in v0.5
Parser::parse_peek which wraps Parser::parse_nextStream::peek_token which wraps Stream::next_tokenStream::peek_slice which wraps Stream::next_sliceOffset::offset_from which wraps Offset::offset_tounpeek which is a no-op function in prep for v0.5ascii::escaped_transform on coreascii::float to correct parse infinityResolve a performance regression in winnow::ascii: parsers (any that use take_while)
winnow::ascii: parsers (any that use take_while)Deprecated count, repeat0, repeat1 in favor of repeat
count, repeat0, repeat1 in favor of repeattake_while0, take_while1 in favor of take_whilefold_repeat0, fold_repeat1 in favor of fold_repeatImprove partial-parsing performance by ~15%
Improve color control for debug feature
debug featureReduce risk of breaking when using glob imports
bits, bytes, character, number, sequence, branch, and multi modules are deprecated
bits, bytes, character, number, sequence, branch, and multi modules are deprecatedParser::map_res is deprecatedParser::map_res to Parser::try_map for consistencybytes to token to clarify its scopecharacter to ascii to make it agnostic of char tokensbinary module
bits -> binary::bitsnumbermulti::length_*combinator
sequencebranchmulti*many* combinators as *repeat* to make the code read more clearlyrepeat_m_n as repeat which takes any range typefold_repeat_m_n as fold_repeat which takes any range typetake_while_m_n as take_while which takes any range typeAllow array references and char arrays for ContainsToken
ContainsTokenspace0, space1, multiscape0, multispace1All winnow parsers now return impl Parser, rather than impl FnMut
Breaking:
winnow parsers now return impl Parser, rather than impl FnMutwinnow::prelude::Parser is now namedErrorKind was greatly simplifiedOther
FinishIResult"", '' parserswinnow::prelude now allows named access to ParserParser::parse added as a replacement for FinishIResult::finishescape: Remove extraneous bounds checksBackport v0.5 performance improvements
Backport v0.4 and v0.5 inlining changes for more even comparison across architectures
Backport v0.4 and v0.5 inlining changes for more even comparison across architectures
error::Error now implements Copy, Clone
error::Error now implements Copy, Clone### Fixes - Fix core and alloc support
core and alloc supportEnsure Partial can be toggled to complete.
Partial can be toggled to complete.### Documentation - Fix tutorial headers
Improve the partial parsing example
Fix bounds on Parser::flat_map so that it works with closures
Parser::flat_map so that it works with closuresResolve deprecations as described by them
v0.3.0 changes are relative to nom v7.1.3
Versioning starts at v0.3.0 due to the historical nature of how winnow was
forked from nom. See also the
nom8 changelog.
nom Migration Guidenom to winnowwinnow::Err::Error with winnow::Err::Backtrackwinnow::Err::Fatal with winnow::Err::Cutwinnow::Input* with winnow::stream::StreamE::append with err.appendE::add_context with err.add_contextmany* type inference issues by adding .map(|v: Vec<_>| v)Examples:
Parser::into in favor of Parser::output_into and Parser::err_into (#48)Parser were moved from winnow to winnow::combinator module (#4)pub use bits::*; into root namespace (#52)winnnow::error module (#73, #117)winnow::error::Err was renamed to ErrMode (#117)
Error variant was renamed to BacktrackFatal variant was renamed to Cutwinnow::error::ParserError function parameter order has changed (#92)winnow::error::Error's code field was renamed to kind (#92)(I, ErrorKind) errors in favor of winnow::error::Error (#92, #117)winnow::error::ErrorKind for infinite loops, like in winnow::multi, was changed to ErrorKind::Assert (#146)winnow::multi parsers will debug_assert by default when encountering infinite loops (#146)error::error_to_u32 (#54)FnMut (#152, #164)winnow to winnow::stream (#13, #142)winnow::stream::Stream (#105, #107, #142, #155, #157)
InputIter::Iter is now Stream::IterOffsetsInputIter::iter_indices is now Stream::iter_offsetsInputIter::position is now Stream::offset_forInputIter::slice_index is now Stream::offset_atwinnow::stream::InputLen to SliceLen (#105)winnow::stream::FindSubstring to FindSlice (#105)winnow::stream::FindTokens to ContainsToken (#105)winnow::stream::ParseTo to ParseSlice (#136)winnow::stream::Offset::offset to offset_to (#105)AsBytes into AsBytes and AsBStr (#134)winnow::stream trait impls (#105)winnow::lib from API (#118)MSRV was raised to 1.60 (#158, #160, #167)
memchr is no longer used by default; opt-in with the simd feature
character::is_* functions in favor of AsChar (#25)winnow::*::complete::* and winnow::*::streaming::* parsers in favor of the merged ones (#28)
u8 were merge into winnow::character::dec_uint (#59)i8 were merge into winnow::character::dec_int (#59)winnow::number::*::hex_u32 was replaced with winnow::character::hex_uint (#59)winnow::bytes::*::take_till was renamed to winnow::bytes::take_till0 (#132)winnow::bytes::*::take_while was renamed to winnow::bytes::take_while0 (#132)winnow::bytes::*::take_until was renamed to winnow::bytes::take_until0 (#132)winnow::multi::*::many_till was renamed to winnow::multi::many_till0 (#132)winnow::multi::*::separated_list0 was renamed to winnow::multi::separated0 (#140)winnow::multi::*::separated_list1 was renamed to winnow::multi::separated1 (#140)winnow::bytes::*::escaped was moved to winnow::character::escaped (#108)winnow::bytes::*::escaped_transform was moved to winnow::character::escaped_transform (#108)dbg_dmp in favor of -features debug (#173)all_consuming in favor of eof / FinishIResult::finish (#112)winnow::combinator to Parser trait (#37)
map, see Parser::mapflat_map, see Parser::flat_mapmap_parser, see Parser::and_thenwinnow::combinator to Parser (#40)
map_res as Parser::map_resmap_opt as Parser::verify_map (#145)complete as Parser::complete_err (#168)verify as Parser::verifyvalue as Parser::valuerecognize as Parser::recognizeconsumed as Parser::with_recognized (note: output order swapped)context as Parser::contextmany0_count, many1_count in favor of many0 and many1 (#127)into in favor of Parser::output_into and Parser::err_into (#37, #48)winnow::combinator::cut in favor of winnow::combinator::cut_err (#117)Parser::parse in favor of Parser::parse_next (#76)is_a with take_while1 thanks to new FindToken impls (#44)is_not with take_till1 thanks to new FindToken impls (#44)satisfy with one_of thanks to new FindToken impls (#44)Parser::and, Parser::or in favor of impl Parser for <tuples> and alt (#37)tuple, pair parser in favor of using tuples (#42, #46)ParseError::from_char in favor of ContextError (#45)error::make_error and error::append_error (#55)error::Finish in favor of FinishIResult (#21)error::error_position! and error::error_mode_position! (#92)winnow::prelude (#21)winnow::Stateful for attaching state to the input type (#58)winnow::Located for tracking the input's location, along with Parser::span and Parser::with_span to capture it (#61)winnow::trace::trace combinator, used by all winnow parsers (#156, #165, #176)Bytes and BStr new types with improved Debug (#144, #147, #149, #177)Partial<I> stream type (#28, #142, #166, #170, #172)
character and made generic (#38, #59)one_of, none_of from character to bytes as they are more general (#44)character::anychar to bytes::any with a more generic return type (#44)impl Parser for <tuples> as an alternative to tuple(()) (#42)impl Parser for (char|u8|&str|&[u8]) as an alternative to one_of, char, and tag (#47, #50, #171)Parser::by_ref to allow using &mut impl Parser as a Parser (#34, #41)Parser::void (#113)Parser::parse_to (#136)winnow::combinator::todo (#135)winnow::combinator::backtrack_err (#117)winnow::branch::dispatch! as a match-like alternative to alt (#119)winnow::multi::separated_foldl1 (#140)winnow::multi::separated_foldr1 (#140)Parser:
Parser::map_res (#40)Parser::verify_map (#40, #145)Parser::complete_err (#40, #168)Parser::verify (#40)Parser::value (#40)Parser::with_recognized (#40)Parser::context (#40)winnow::multi parsers (#127)u8 and char, ranges of u8 and char, functions, and tuples of the prior wherever ContainsToken is accepted (#44, #105)take_while, take_till with ContainsToken trait (#44, #105)character::is_* functions to AsChar that were missing (#2)Stream for (I, usize), allowing more combinators to work with bit-streams (#153)FinishIResult::finish for dropping the remainder (#30)FindSlice now also finds tokens, making take_until0 and friends more flexible (#105)ParseError and FromExternalError for ErrMode, making it easier to create the right kind of error (#120, #124)chars for take_while_m_n (#130)fill, iterator, bits::bits, and bits::bytes from taking a function to taking a Parser (#10, #11, #120)length_data and length_value now auto-detect complete/streaming, before were streaming only (#28)Clarify Offset::offset_to` with explicit assert (#109, rust-bakery/nom#1520)Into over From (#110, rust-bakery/nom#1460)ErrorConvert in ErrMode::convert (#124)memchr::memmem on FindSlice (#86, rust-bakery/nom#1375)Vec::with_capacity for length_count (#87, rust-bakery/nom#1462)#[doc(alias)]s for easier migration from nom, chumsky, and combine (#178)bits::tag (#88, rust-bakery/nom#1501)Your coding agent can read these notes before it upgrades. Set up the MCP server →