summaryrefslogtreecommitdiffstats
path: root/vendor/nom8
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/nom8')
-rw-r--r--vendor/nom8/.cargo-checksum.json1
-rw-r--r--vendor/nom8/CHANGELOG.md1557
-rw-r--r--vendor/nom8/Cargo.lock283
-rw-r--r--vendor/nom8/Cargo.toml201
-rw-r--r--vendor/nom8/LICENSE20
-rw-r--r--vendor/nom8/README.md330
-rw-r--r--vendor/nom8/src/_cookbook.rs378
-rw-r--r--vendor/nom8/src/_tutorial.rs217
-rw-r--r--vendor/nom8/src/bits/complete.rs177
-rw-r--r--vendor/nom8/src/bits/mod.rs179
-rw-r--r--vendor/nom8/src/bits/streaming.rs162
-rw-r--r--vendor/nom8/src/bits/tests.rs142
-rw-r--r--vendor/nom8/src/branch/mod.rs267
-rw-r--r--vendor/nom8/src/branch/tests.rs146
-rw-r--r--vendor/nom8/src/bytes/complete.rs1258
-rw-r--r--vendor/nom8/src/bytes/mod.rs924
-rw-r--r--vendor/nom8/src/bytes/streaming.rs1465
-rw-r--r--vendor/nom8/src/bytes/tests.rs807
-rw-r--r--vendor/nom8/src/character/complete.rs1366
-rw-r--r--vendor/nom8/src/character/mod.rs1217
-rw-r--r--vendor/nom8/src/character/streaming.rs1441
-rw-r--r--vendor/nom8/src/character/tests.rs1030
-rw-r--r--vendor/nom8/src/combinator/mod.rs1528
-rw-r--r--vendor/nom8/src/combinator/tests.rs398
-rw-r--r--vendor/nom8/src/error.rs1055
-rw-r--r--vendor/nom8/src/input.rs2929
-rw-r--r--vendor/nom8/src/lib.rs430
-rw-r--r--vendor/nom8/src/macros.rs23
-rw-r--r--vendor/nom8/src/multi/mod.rs1029
-rw-r--r--vendor/nom8/src/multi/tests.rs645
-rw-r--r--vendor/nom8/src/number/complete.rs2289
-rw-r--r--vendor/nom8/src/number/mod.rs2197
-rw-r--r--vendor/nom8/src/number/streaming.rs2508
-rw-r--r--vendor/nom8/src/number/tests.rs1096
-rw-r--r--vendor/nom8/src/parser.rs1159
-rw-r--r--vendor/nom8/src/sequence/mod.rs291
-rw-r--r--vendor/nom8/src/sequence/tests.rs310
-rw-r--r--vendor/nom8/src/str.rs539
-rw-r--r--vendor/nom8/tests/arithmetic.rs92
-rw-r--r--vendor/nom8/tests/arithmetic_ast.rs159
-rw-r--r--vendor/nom8/tests/css.rs45
-rw-r--r--vendor/nom8/tests/custom_errors.rs49
-rw-r--r--vendor/nom8/tests/escaped.rs28
-rw-r--r--vendor/nom8/tests/float.rs46
-rw-r--r--vendor/nom8/tests/fnmut.rs39
-rw-r--r--vendor/nom8/tests/ini.rs202
-rw-r--r--vendor/nom8/tests/ini_str.rs217
-rw-r--r--vendor/nom8/tests/issues.rs248
-rw-r--r--vendor/nom8/tests/json.rs228
-rw-r--r--vendor/nom8/tests/mp4.rs324
-rw-r--r--vendor/nom8/tests/multiline.rs31
-rw-r--r--vendor/nom8/tests/overflow.rs162
-rw-r--r--vendor/nom8/tests/reborrow_fold.rs30
53 files changed, 33894 insertions, 0 deletions
diff --git a/vendor/nom8/.cargo-checksum.json b/vendor/nom8/.cargo-checksum.json
new file mode 100644
index 000000000..c4e49793b
--- /dev/null
+++ b/vendor/nom8/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"f3b4bd6b41fe87e0dce819f7aa57c783d65576c06819d87552a8c6d321098963","Cargo.lock":"b1839293f147b382109c9b739dbe17aa18c09942eb68005a8f0e418aa69b101d","Cargo.toml":"f2380517d8ff03fc069dd0593aaeb935f52cabbb0f94a758eb7f16fb93153d48","LICENSE":"4dbda04344456f09a7a588140455413a9ac59b6b26a1ef7cdf9c800c012d87f0","README.md":"b1b278a30065c260d4984508e4e4a3ec9b6b583646ee9c30ac9367328c3067fd","src/_cookbook.rs":"be0e800a3aaa016e3b149156ce1cc25844bc9407d622099c0af6aec51bcdb0b1","src/_tutorial.rs":"ea785518e4ede677462caae38cfb7fade7ca3d9e9cc78c46101e69b301449222","src/bits/complete.rs":"2a436628dd45dc9314ff79b22ce47e63f94c24fc65dd75bf96fa5505ea6917df","src/bits/mod.rs":"5b23eb0f340835295dba87197e724364c6e5c899d29fafc652ea299fce96edf7","src/bits/streaming.rs":"dd6e43c6aa63c4ce9e6bd9c5eefd7dbdc32d7378c0353509183895a93846022a","src/bits/tests.rs":"75d5d1a2a9d5f2452423be2396785725a44df1223319efd3738e4346c206f11e","src/branch/mod.rs":"978650a0e9a13c307a8dae1afd8543a56c8dbd9eb87bc88159a425ecc35ab1e8","src/branch/tests.rs":"fb954d2924617c79d9eb41ced4670e48088cc0432d74562d9f80101e20ba809b","src/bytes/complete.rs":"a9b423327806bcb60415d13e14f9ace205f50e694b6a82ba7df75c574a410262","src/bytes/mod.rs":"05bf92efaeef35034b9a54d81554f0fd69caab2c19d32b676c4ee4e592192edc","src/bytes/streaming.rs":"587ed253ce88f5fa1059966a75633ac437050e7c9941a12530ad71af41f232c7","src/bytes/tests.rs":"b7ef2cae1729a2eb63af334a849c69c653d9d6f7e6a5d3535b251504354c4eb3","src/character/complete.rs":"7e04bc72126afb55cb411b21845a12c42929c38a3291c95aaa1c16895c203801","src/character/mod.rs":"89f1651cb947ac86451369eacc04bb369c00e6f0ebe6923e08fdec5761f4148d","src/character/streaming.rs":"c2f9b9692ae1f84ffef699f27b07154aedf0aaf55fa2ad474d7e7661e2bf7a6b","src/character/tests.rs":"57bd0bf736ab675da9b3485e2eb48c766719ce9792d5edf41786ca5e46e1ee22","src/combinator/mod.rs":"1ac8dbda67ca6d4d2d64c11f2577dd74d4bf9515fb949f769a80df0b92e7e830","src/combinator/tests.rs":"0f5049967222b66b1936433c693011a3e268082afa3fe3576cfc3e940c62b82b","src/error.rs":"3134cf1fa1a4e8322aec127b57a153ba047e0d40f736e680c1e3daffdf3d2e70","src/input.rs":"7a96ac7bc9ae6e17a8b438d6cc47af77c38b05bf9150a50696ecaf3d108356e1","src/lib.rs":"98985af25e8624f0ff9df7845cb61c1f8c647953092458685a9c8f4fdd307e43","src/macros.rs":"11ac3dee346e5bf61015f328975cf6ea6f438683eb3b8b6c7c8e6383b0c5b7af","src/multi/mod.rs":"33adaec4a019845bb4300fdda29a4933e5a2059f60427574c54687049b74227b","src/multi/tests.rs":"3e65c828fd44ca07c06bc5866d00aae48938af97de53c5ced4fd781a5d0a5c5d","src/number/complete.rs":"89b82b0d40180b80930f24628c0f75f4196bccf374b0feb5fd337ac599548f3c","src/number/mod.rs":"3200b900c2f0a71b7888833b2352bf004570fba685f2c6bd87df9d745d93630b","src/number/streaming.rs":"788131865b91f5447251c577bb2412b7b710a60e63c7c71c11d23d12b63ef2ba","src/number/tests.rs":"0df18ecc3a61d4f887a1481f3aada137a89871708ee893e5ee608e46a734bd2b","src/parser.rs":"ad034670da5165582cb962ee4987aaa6e390979fb8a557a67ee670e78e2f53e0","src/sequence/mod.rs":"bc7d73b3e19a13ec85472d147227c51f8d055afe2c04d4c2d89d2feb96a3813a","src/sequence/tests.rs":"aafd0c58fa2ec67643b3f66a0e0fcc2d3aafe27562d4cf3afdb291215f681baf","src/str.rs":"38895ddd4c565e3274eb11cf34b841caa78287713048d482a774a61caac03775","tests/arithmetic.rs":"46939560719063d47980762eaa8df7e37c74bef1ea3e64523dadb3f4472e3d54","tests/arithmetic_ast.rs":"96ccd3d15ada85989d2c50e2d3b974654d3bf32e284df5e9a088bb85b4ca2abd","tests/css.rs":"2e5586ee3941160fda9c15a7f8d038958b376102df7d621a66d9e075f252b168","tests/custom_errors.rs":"bfdf8ecf00a9b6c24b668906f3be3b9c379f6e9de01355c40fd6082428620b8c","tests/escaped.rs":"b6d2869deec93fc18d7c56fe155763d67b60ecf69a9d98aecee2213c5caf241b","tests/float.rs":"d1a1256af4ee9151ae456092bdca2a9df2d521d8ae4cc0ce79cd7192ba530da1","tests/fnmut.rs":"2368a735e1d558cf8877fc5a51072a8f712527a3bd024e6a1a649fe968cf1ce7","tests/ini.rs":"bc74e69de68b8788ae98fe2f5a59e7348b45f9dc9668be30dea515303d079040","tests/ini_str.rs":"55e776e0a94509e0cfe06b37a87f6910ea4670d199cda40133f596a2ed929aef","tests/issues.rs":"81a347e4386846baf465ddfd7eda8cfe8ee541a0a6fe7807649f16df1e6826a6","tests/json.rs":"f3ccd277d6875c927aa5c8076a54f25c437bdbf8b8b4618923df3489305353cf","tests/mp4.rs":"fe47e64b7402ebda850179f6fa3a0983e2d8df17f3bc577644466e8f42ab2cc8","tests/multiline.rs":"778e80f3a8c8a63cbf7a72fed6abdab8c1e451f9b266fe3e5e4283951f406258","tests/overflow.rs":"11690372e4a1e2e32b9daf66fd4e62151ed3b12910df7e1363aebe8264164a56","tests/reborrow_fold.rs":"4494ed00bea291fe3deb16d5642fa600685399cec9574ae0298a09e2f6214e61"},"package":"ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"} \ No newline at end of file
diff --git a/vendor/nom8/CHANGELOG.md b/vendor/nom8/CHANGELOG.md
new file mode 100644
index 000000000..52d2c5f2b
--- /dev/null
+++ b/vendor/nom8/CHANGELOG.md
@@ -0,0 +1,1557 @@
+# Change Log
+
+<!-- next-header -->
+## [Unreleased] - ReleaseDate
+
+## [0.2.0] - 2022-12-27
+
+### Breaking Changes
+
+From nom8
+- Removed `pub use bits::*;` into root namespace (epage/nom-experiment#52)
+- Removed `error::error_to_u32` (epage/nom-experiment#54)a
+
+From 0.1.0
+- Removed `nom::character::char` in favor of `nom::bytes::one_of` (epage/nom-experiment#45)
+- Changed `IntoOutput` to allow reconstructing state (epage/nom-experiment#57)
+
+### Deprecations
+
+- Deprecated `ParseError::from_char` in favor of `ContextError` (epage/nom-experiment#45)
+- Deprecated `error::make_error` and `error::append_error` (epage/nom-experiment#55)
+
+### Feature
+
+- `nom::input::Stateful` for attaching state to the input type (epage/nom-experiment#58)
+- `nom::input::Located` for tracking the input's location, along with `Parser::span` and `Parser::with_span` to capture it (epage/nom-experiment#58)
+
+### Fixes
+
+From 0.1.0
+- Generalize `InputTakeAtPosition` for `Streaming`
+
+## [0.1.0] - 2022-12-23
+
+### Breaking Changes
+
+- Moved input traits from `nom` to `nom::input` (epage/nom-experiment#13)
+- Renamed `InputTakeAtPosition` functions to be explicit about complete vs streaming policy
+- Removed `impl ExtendInto for char` (epage/nom-experiment#19)
+- Combinator structs returned by `Parser` were moved to `combinator` module (epage/nom-experiment#4)
+- Tweaks were made to what input traits are needed for various types
+
+### Deprecations
+
+- `character::is_*` functions in favor of `AsChar` (epage/nom-experiment#25)
+- `*::complete::*` and `*::streaming::*` parsers in favor of merged ones (epage/nom-experiment#28)
+- Freestanding `map`, `flat_map`, `map_parser` in favor of `Parser` functions (epage/nom-experiment#37)
+- Freestanding `map_res`, `map_opt`, `complete`, `verify`, `value`, `recognize_with_value`, `context`, `dbg_dmp` in favor of `Parser` methods (epage/nom-experiment#40)
+- Freestanding `into` in favor of `Parser::output_into` and `Parser::err_into` (epage/nom-experiment#37, epage/nom-experiment#48)
+- `is_a` with `take_while1` thanks to new `FindToken` impls (epage/nom-experiment#44)
+- `is_not` with `take_till1` thanks to new `FindToken` impls (epage/nom-experiment#44)
+- `satisfy` with `one_of` thanks to new `FindToken` impls (epage/nom-experiment#44)
+- `Parser::and`, `Parser::or` in favor of `impl Parser for <tuples>` and `alt` (epage/nom-experiment#37)
+- `tuple`, `pair` parser in favor of using tuples (epage/nom-experiment#42, epage/nom-experiment#46)
+
+### Features
+
+- Merged streaming/complete parsers, opting in to streaming with the `Streaming<I>` input type (epage/nom-experiment#28)
+ - Merged ASCII float parsers moved to `character` and renamed to their rust types (epage/nom-experiment#38)
+ - Moved `one_of`, `none_of` from `character` to `bytes` as they are more general (epage/nom-experiment#44)
+ - Moved `character::anychar` to `bytes::any` with a more generic return type (epage/nom-experiment#44)
+- Allow generic context in errors (epage/nom-experiment#49)
+- `Parser::by_ref` to allow using `&mut impl Parser` as a `Parser` (epage/nom-experiment#34, epage/nom-experiment#41)
+- `impl Parser for <tuples>` as an alternative to `tuple(())` (epage/nom-experiment#42)
+- `impl Parser for (char|u8|&str|&[u8])` as an alternative to `one_of`, `char`, and `tag` (epage/nom-experiment#47, epage/nom-experiment#50)
+- Add `Parser::map_res`, `Parser::map_opt`, `Parser::complete`, `Parser::verify`, `Parser::value`, `Parser::with_recognized`, `Parser::context`, `Parser::dbg_err` (epage/nom-experiment#40)
+- Allow `u8` / `char` / ranges of the prior, functions, and tuples of the prior whereever `FindToken` is accepted (epage/nom-experiment#44)
+- Generalize `take_while`, `take_till` with `FindToken` trait (epage/nom-experiment#44)
+- Add `character::is_*` functions to `AsChar` that were missing (epage/nom-experiment#2)
+
+### Fixes
+
+- Change `fill`, `iterator`, `bits::bits`, and `bits::byutes` from taking a function to taking a `Parser` (epage/nom-experiment#10, epage/nom-experiment#11, epage/nom-experiment#120)
+- Allow byte arrays of any size (epage/nom-experiment#14)
+- `length_data` and `length_value` now auto-detect complete/streaming, before were streaming only (epage/nom-experiment#28)
+- `hex_u32` is now generic over input (epage/nom-experiment#32)
+- Clamp allocations in `many_m_n`, `count` (Geal/nom#1545)
+
+### Documentation
+
+- Pulled loose markdown into rustdoc (epage/nom-experiment#1)
+
+## [7.1.0] - 2021-11-04
+
+### Thanks
+
+- @nickelc
+- @Stargateur
+- @NilsIrl
+- @clonejo
+- @Strytyp
+- @schubart
+- @jihchi
+- @nipunn1313
+- @Gungy2
+- @Drumato
+- @Alexhuszagh
+- @Aehmlo
+- @homersimpsons
+- @dne
+- @epage
+- @saiintbrisson
+- @pymongo
+
+### Changed
+
+- documentation fixes
+- Ci fixes
+- the move to minimal-lexical for float parsing introduced bugs that cannot be resolved right now, so this version moves back to using the standard lib' parser. *This is a performance regression**. If you have specific requirements around float parsing, you are strongly encouraged to use [recognize_float](https://docs.rs/nom/latest/nom/number/complete/fn.recognize_float.html) and another library to convert to a f32 or f64
+
+### Added
+
+- alt now works with 1 elment tuples
+
+## [7.0.0] - 2021-08-21
+
+This release fixes dependency compilation issues and strengthen the minimum supported Rust version (MSRV) policy. This is also the first release without the macros that were used since nom's beginning.
+
+### Thanks
+
+- @djc
+- @homersimpsons
+- @lo48576
+- @myrrlyn
+- @RalXYZ
+- @nickelc
+- @cenodis
+
+### Added
+
+- `take_until1` combinator
+- more `to_owned` implementations
+- `fail`: a parser that always fail, useful as default condition in other combinators
+- text to number parsers: in the `character::streaming` and `character::complete` modules, there are parsers named `i8, u16, u32, u64, u128` and `u8 ,u16, u32, u64, u128` that recognize decimal digits and directly convert to a number in the target size (checking for max int size)
+
+### Removed
+
+- now that function combinators are the main way to write parsers, the old macro combinators are confusing newcomers. THey have been removed
+- the `BitSlice` input type from bitvec has been moved into the [nom-bitvec](https://crates.io/crates/nom-bitvec) crate. nom does not depend on bitvec now
+- regex parsers have been moved into the [nom-regex](https://crates.io/crates/nom-regex) crate. nom does not depend on regex now
+- `ErrorKind::PArseTo` was not needed anymore
+
+### Changed
+
+- relax trait bounds
+- some performance fixes
+- `split_at_position*` functions should now be guaranteed panic free
+- the `lexical-core` crate used for float parsing has now been replaced with `minimal-lexical`: the new crate is faster to compile, faster to parse, and has no dependencies
+
+### Fixed
+
+- infinite loop in `escaped` combinator
+- `many_m_n` now fails if min > max
+
+
+## [6.2.1] - 2021-06-23
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+
+- @homersimpsons
+
+### Fixed
+
+- fix documentation building
+
+## [6.2.0] - 2021-02-15
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+
+- @DavidKorczynski
+- @homersimpsons
+- @kornelski
+- @lf-
+- @lewisbelcher
+- @ronan-d
+- @weirane
+- @heymind
+- @marcianx
+- @Nukesor
+
+### Added
+
+- nom is now regularly fuzzed through the OSSFuzz project
+
+### Changed
+
+- lots of documentation fixes
+- relax trait bounds
+- workarounds for dependency issues with bitvec and memchr
+
+## [6.1.2] - 2021-02-15
+
+### Changed
+
+- Fix cargo feature usage in previous release
+
+## [6.1.1] - 2021-02-15
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+
+- @nickelc
+
+### Changed
+
+- Fix dependenciy incompatibilities: Restrict the bitvec->funty dependency to <=1.1
+
+## [6.1.0] - 2021-01-23
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+
+- @sachaarbonel
+- @vallentin
+- @Lucretiel
+- @meiomorphism
+- @jufajardini
+- @neithernut
+- @drwilco
+
+### Changed
+
+- readme and documentation fixes
+- rewrite of fold_many_m_n
+- relax trait bounds on some parsers
+- implement `std::error::Error` on `VerboseError`
+
+
+## [6.0.1] - 2020-11-24
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+
+- @Leonqn
+- @nickelc
+- @toshokan
+- @juchiast
+- @shssoichiro
+- @jlkiri
+- @chifflier
+- @fkloiber
+- @Kaoet
+- @Matthew Plant
+
+### Added
+
+- `ErrorConvert` implementation for `VerboseError`
+
+### Changed
+
+- CI fixes
+- `fold_many*` now accept `FnMut` for the accumulation function
+- relaxed input bounds on `length_count`
+
+# Fixed
+
+- documentation fixes
+- the `#[deprecated]` attribute was removed from traits because it does not compile anymore on nightly
+- bits and bytes combinators from the bits modules are now converted to use `FnMut`
+
+## [6.0.0] - 2020-10-31
+
+### Thanks
+
+This release was done thanks to the hard work of (by order of appearance in the commit list):
+- @chifflier
+- @shepmaster
+- @amerelo
+- @razican
+- @Palladinium
+- @0ndorio
+- Sebastian Zivota
+- @keruspe
+- @devonhollowood
+- @parasyte
+- @nnt0
+- @AntoineCezar
+- @GuillaumeGomez
+- @eijebong
+- @stadelmanma
+- @sphynx
+- @snawaz
+- @fosskers
+- @JamesHarrison
+- @calebsander
+- @jthornber
+- @ahmedcharles
+- @rljacobson
+- @benkay86
+- @georgeclaghorn
+- @TianyiShi2001
+- @shnewto
+- @alfriadox
+- @resistor
+- @myrrlyn
+- @chipsenkbeil
+- @ruza-net
+- @fanf2
+- @jameysharp
+- @FallenWarrior2k
+- @jmg-duarte
+- @ericseppanen
+- @hbina
+- Andreas Molzer
+- @nickelc
+- @bgourlie
+
+## Notable changes
+
+This release is a more polished version of nom 5, that came with a focus on
+function parsers, by relaxing the requirements: combinators will return a
+`impl FnMut` instead of `impl Fn`, allowing closures that change their context,
+and parsers can be any type now, as long as they implement the new `Parser` trait.
+That parser trait also comes with a few helper methods.
+
+Error management was often a pain point, so a lot of work went into making it easier.
+Now it integrates with `std:error::Error`, the `IResult::finish()` method allows you
+to convert to a more usable type, the `into` combinator can convert the error type
+if there's a `From` implementation, and there are more specific error traits like
+`ContextError` for the `context` combinator, and `FromExternalError` for `map_res`.
+While the `VerboseError` type and its `convert_error` function saw some changes,
+not many features ill be added to it, instead you are encouraged to build the error
+type that corresponds to your needs if you are building a language parser.
+
+This version also integrates with the excellent [bitvec](https://crates.io/crates/bitvec)
+crate for better bit level parsing. This part of nom was not great and a bit of a hack,
+so this will give better options for those parsers.
+
+At last, documentation! There are now more code examples, functions and macros that require
+specific cargo features are now clearly indicated, and there's a new `recipes` module
+containing example patterns.
+
+### Breaking changes
+
+- the minimal Rust version is now 1.44 (1.37 if building without the `alloc` or `std` features)
+- streaming parsers return the number of additional bytes they need, not the total. This was supposed to be the case everywhere, but some parsers were forgotten
+- removed the `regexp_macros` cargo feature
+- the `context` combinator is not linked to `ParseError` anymore, instead it come with its own `ContextError` trait
+- `Needed::Size` now contains a `NonZeroUsize`, so we can reduce the structure's size by 8 bytes. When upgrading, `Needed::Size(number)` can be replaced with `Needed::new(number)`
+- there is now a more general `Parser` trait, so parsers can be something else than a function. This trait also comes with combinator methods like `map`, `flat_map`, `or`. Since it is implemented on `Fn*` traits, it should not affect existing code too much
+- combinators that returned a `impl Fn` now return a `impl FnMut` to allow parser closures that capture some mutable value from the context
+- `separated_list` is now `separated_list0`
+- removed the deprecated `methods` module
+- removed the deprecated `whitespace` module
+- the default error type is now a struct (`nom::error::Error`) instead of a tuple
+- the `FromExternalError` allows wrapping the error returned by the function in the `map_res` combinator
+- renamed the `dbg!` macro to avoid conflicts with `std::dbg!`
+- `separated_list` now allows empty elements
+
+
+### Added
+
+- function version of regex parsers
+- `fill`: attempts to fill the output slice passed as argument
+- `success`: returns a value without consuming the input
+- `satisfy`: checks a predicate over the next character
+- `eof` function combinator
+- `consumed`: returns the produced value and the consumed input
+- `length_count` function combinator
+- `into`: converts a parser's output and error values if `From` implementations are available
+- `IResult::finish()`: converts a parser's result to `Result<(I, O), E>` by removing the distinction between `Error` and `Failure` and panicking on `Incomplete`
+- non macro versions of `u16`, `i32`, etc, with configurable endianness
+- `is_newline` function
+- `std::error::Error` implementation for nom's error types
+- recipes section of the documentation, outlining common patterns in nom
+- custom errors example
+- bitstream parsing with the `BitSlice` type from the bitvec crate
+- native endianness parsers
+- github actions for CI
+
+### Changed
+
+- allows lexical-core 0.7
+- number parsers are now generic over the input type
+- stabilized the `alloc` feature
+- `convert_error` accepts a type that derefs to `&str`
+- the JSON example now follows the spec better
+
+### Fixed
+- use `fold_many0c` in the `fold_many0` macro
+
+## [5.1.1] - 2020-02-24
+
+### Thanks
+
+- @Alexhuszagh for float fixes
+- @AlexanderEkdahl, @JoshOrndorff, @akitsu-sanae for docs fixes
+- @ignatenkobrain: dependency update
+- @derekdreery: `map` implementation for errors
+- @Lucretiel for docs fixes and compilation fixes
+- adytzu2007: warning fixes
+- @lo48576: error management fixes
+
+### Fixed
+
+- C symbols compilation errors due to old lexical-core version
+
+### Added
+
+- `Err` now has a `map` function
+
+### Changed
+
+- Make `error::context()` available without `alloc` feature
+
+## [5.1.0] - 2020-01-07
+
+### Thanks
+
+- @Hywan, @nickmooney, @jplatte, @ngortheone, @ejmg, @SirWindfield, @demurgos, @spazm, @nyarly, @guedou, @adamnemecek, for docs fixes
+- @Alxandr for error management bugfixes
+- @Lucretiel for example fixes and optimizations
+- @adytzu2007 for optimizations
+- @audunhalland for utf8 fixes
+
+### Fixed
+
+- panic in `convert_error`
+- `compile_error` macro usage
+
+### Added
+
+- `std::error::Error`, `std::fmt::Display`, `Eq`, `ToOwned` implementations for errors
+- inline attribute for `ToUsize`
+
+### Changed
+
+- `convert_error` optimization
+- `alt` optimization
+
+## [5.0.1] - 2019-08-22
+
+### Thanks
+
+- @waywardmonkeys, @phaazon, @dalance for docs fixes
+- @kali for `many0_m_n` fixes
+- @ia0 for macros fixes
+
+### Fixed
+
+- `many0_m_n` now supports the n=1 case
+- relaxed trait requirements in `cut`
+- `peek!` macro reimplementation
+- type inference in `value!`
+
+## [5.0.0] - 2019-06-24
+
+This version comes with a complete rewrite of nom internals to use functions as a base
+for parsers, instead of macros. Macros have been updated to use functions under
+the hood, so that most existing parsers will work directly or require minimal changes.
+
+The `CompleteByteSlice` and `CompleteStr` input types were removed. To get different
+behaviour related to streaming or complete input, there are different versions of some
+parsers in different submodules, like `nom::character::streaming::alpha0` and
+`nom::character::complete::alpha0`.
+
+The `verbose-errors` feature is gone, now the error type is decided through a generic
+bound. To get equivalent behaviour to `verbose-errors`, check out `nom::error::VerboseError`
+
+### Thanks
+
+- @lowenheim helped in refactoring and error management
+- @Keruspe helped in refactoring and fixing tests
+- @pingiun, @Songbird0, @jeremystucki, @BeatButton, @NamsooCho, @Waelwindows, @rbtcollins, @MarkMcCaskey for a lot of help in rewriting the documentation and adding code examples
+- @GuillaumeGomez for documentation rewriting and checking
+- @iosmanthus for bug fixes
+- @lo48576 for error management fixes
+- @vaffeine for macros visibility fixes
+- @webholik and @Havvy for `escaped` and `escaped_transform` fixes
+- @proman21 for help on porting bits parsers
+
+### Added
+
+- the `VerboseError` type accumulates position info and error codes, and can generate a trace with span information
+- the `lexical-core` crate is now used by default (through the `lexical` compilation feature) to parse floats from text
+- documentation and code examples for all functions and macros
+
+### Changed
+
+- nom now uses functions instead of macros to generate parsers
+- macros now use the functions under the hood
+- the minimal Rust version is now 1.31
+- the verify combinator's condition function now takes its argument by reference
+- `cond` will now return the error of the parser instead of None
+- `alpha*`, `digit*`, `hex_digit*`, `alphanumeric*` now recognize only ASCII characters
+
+### Removed
+
+- deprecated string parsers (with the `_s` suffix), the normal version can be used instead
+- `verbose-errors` is not needed anymore, now the error type can be decided when writing the parsers, and parsers provided by nom are generic over the error type
+- `AtEof`, `CompleteByteSlice` and `CompleteStr` are gone, instead some parsers are specialized to work on streaming or complete input, and provided in different modules
+- character parsers that were aliases to their `*1` version: eol, alpha, digit, hex_digit, oct_digit, alphanumeric, space, multispace
+- `count_fixed` macro
+- `whitespace::sp` can be replaced by `character::complete::multispace0`
+- method combinators are now in the nom-methods crate
+- `take_until_either`, `take_until_either1`, `take_until_either_and_consume` and `take_until_either_and_consume1`: they can be replaced with `is_not` (possibly combined with something else)
+- `take_until_and_consume`, `take_until_and_consume1`: they can be replaced with `take_until` combined with `take`
+- `sized_buffer` and `length_bytes!`: they can be replaced with the `length_data` function
+- `non_empty`, `begin` and `rest_s` function
+- `cond_reduce!`, `cond_with_error!`, `closure!`, `apply`, `map_res_err!`, `expr_opt!`, `expr_res!`
+- `alt_complete`, `separated_list_complete`, `separated_nonempty_list_complete`
+
+## [4.2.3] - 2019-03-23
+
+### Fixed
+
+- add missing `build.rs` file to the package
+- fix code comparison links in changelog
+
+## [4.2.2] - 2019-03-04
+
+### Fixed
+
+- regression in do_parse macro import for edition 2018
+
+## [4.2.1] - 2019-02-27
+
+### Fixed
+
+- macro expansion error in `do_parse` due to `compile_error` macro usage
+
+## [4.2.0] - 2019-01-29
+
+### Thanks
+
+- @JoshMcguigan for unit test fixes
+- @oza for documentation fixes
+- @wackywendell for better error conversion
+- @Zebradil for documentation fixes
+- @tsraom for new combinators
+- @hcpl for minimum Rust version tests
+- @KellerFuchs for removing some unsafe uses in float parsing
+
+### Changed
+
+- macro import in edition 2018 code should work without importing internal macros now
+- the regex parsers do not require the calling code to have imported the regex crate anymore
+- error conversions are more ergonomic
+- method combinators are now deprecated. They might be moved to a separate crate
+- nom now specifies Rust 1.24.1 as minimum version. This was already the case before, now it is made explicit
+
+### Added
+
+- `many0_count` and `many1_count` to count applications of a parser instead of
+accumulating its results in a `Vec`
+
+### Fixed
+
+- overflow in the byte wrapper for bit level parsers
+- `f64` parsing does not use `transmute` anymore
+
+## [4.1.1] - 2018-10-14
+
+### Fixed
+
+- compilation issue in verbose-errors mode for `add_return_error`
+
+## [4.1.0] - 2018-10-06
+
+### Thanks
+
+- @xfix for fixing warnings, simplifying examples and performance fixes
+- @dvberkel for documentation fixes
+- @chifflier for fixing warnings
+- @myrrlyn for dead code elimination
+- @petrochenkov for removing redundant test macros
+- @tbelaire for documentation fixes
+- @khernyo for fixing warnings
+- @linkmauve for documentation fixes
+- @ProgVal for documentation fixes, warning fixes and error management
+- @Nemo157 for compilation fixes
+- @RReverser for documentation fixes
+- @xpayn for fixing warnings
+- Blas Rodriguez Irizar for documentation fixes
+- @badboy for documentation fixes
+- @kyrias for compilation fixes
+- @kurnevsky for the `rest_len` parser
+- @hjr3 for new documentation examples
+- @fengalin for error management
+- @ithinuel for the pcap example project
+- @phaazon for documentation fixes
+- @juchiast for documentation fixes
+- @jrakow for the `u128` and `i128` parsers
+- @smarnach for documentation fixes
+- @derekdreery for `pub(crate)` support
+- @YaLTeR for `map_res_err!`
+
+### Added
+
+- `rest_len` parser, returns the length of the remaining input
+- `parse_to` has its own error code now
+- `u128` and `i128` parsers in big and little endian modes
+- support for `pub(crate)` syntax
+- `map_res_err!` combinator that appends the error of its argument function in verbose errors mode
+
+### Fixed
+
+- lots of unused imports warnings were removed
+- the `bytes` combinator was not compiling in some cases
+- the big and little endian combinators now work without external imports
+- CI is now faster and uses less cache
+- in `add_return_error`, the provided error code is now evaluated only once
+
+### Changed
+
+- `fold_many1` will now transmit a `Failure` instead of transforming it to an `Error`
+- `float` and `double` now work on all of nom's input types (`&[u8]`, `&str`, `CompleteByteSlice`, `CompleteStr` and any type that implements the required traits). `float_s` and `double_s` got the same modification, but are now deprecated
+- `CompleteByteSlice` and `CompleteStr` get a small optimization by inlining some functions
+
+
+## [4.0.0] - 2018-05-14
+
+### Thanks
+
+- @jsgf for the new `AtEof` trait
+- @tmccombs for fixes on `escaped*` combinators
+- @s3bk for fixes around non Copy input types and documentation help
+- @kamarkiewicz for fixes to no_std and CI
+- @bheisler for documentation and examples
+- @target-san for simplifying the `InputIter` trait for `&[u8]`
+- @willmurphyscode for documentation and examples
+- @Chaitanya1416 for typo fixes
+- @fflorent for `input_len()` usage fixes
+- @dbrgn for typo fixes
+- @iBelieve for no_std fixes
+- @kpp for warning fixes and clippy fixes
+- @keruspe for fixes on FindToken
+- @dtrebbien for fixes on take_until_and_consume1
+- @Henning-K for typo fixes
+- @vthriller for documentation fixes
+- @federicomenaquintero and @veprbl for their help fixing the float parsers
+- @vmchale for new named_args versions
+- @hywan for documentation fixes
+- @fbenkstein for typo fixes
+- @CAD97 for catching missing trait implementations
+- @goldenlentils for &str optimizations
+- @passy for typo fixes
+- @ayrat555 for typo fixes
+- @GuillaumeGomez for documentation fixes
+- @jrakow for documentation fixes and fixes for `switch!`
+- @phlosioneer for documentation fixes
+- @creativcoder for typo fixes
+- @derekdreery for typo fixes
+- @lucasem for implementing `Deref` on `CompleteStr` and `CompleteByteSlice`
+- @lowenheim for `parse_to!` fixes
+- @myrrlyn for trait fixes around `CompleteStr` and `CompleteByteSlice`
+- @NotBad4U for fixing code coverage analysis
+- @murarth for code formatting
+- @glandium for fixing build in no_std
+- @csharad for regex compatibility with `CompleteStr`
+- @FauxFaux for implementing `AsRef<str>` on `CompleteStr`
+- @jaje for implementing `std::Error` on `nom:Err`
+- @fengalin for warning fixes
+- @@khernyo for doc formatting
+
+Special thanks to @corkami for the logo :)
+
+### Breaking changes
+
+- the `IResult` type now becomes a `Result` from the standard library
+- `Incomplete` now returns the additional data size needed, not the total data size needed
+- verbose-errors is now a superset of basic errors
+- all the errors now include the related input slice
+- the arguments from `error_position` and other such macros were swapped to be more consistent with the rest of nom
+- automatic error conversion: to fix error type inference issues, a custom error type must now implement `std::convert::From<u32>`
+- the `not!` combinator returns unit `()`
+- FindToken's calling convention was swapped
+- the `take_*` combinators are now more coherent and stricter, see commit 484f6724ea3ccb for more information
+- `many0` and other related parsers will now return `Incomplete` if the reach the end of input without an error of the child parser. They will also return `Incomplete` on an empty input
+- the `sep!` combinator for whitespace only consumes whitespace in the prefix, while the `ws!` combinator takes care of consuming the remaining whitespace
+
+### Added
+
+- the `AtEof` trait for input type: indicate if we can get more input data later (related to streaming parsers and `Incomplete` handling)
+- the `escaped*` parsers now support the `&str`input type
+- the `Failure` error variant represents an unrecoverable error, for which `alt` and other combinators will not try other branches. This error means we got in the right part of the code (like, a prefix was checked correctly), but there was an error in the following parts
+- the `CompleteByteSlice` and `CompleteStr` input types consider there will be no more refill of the input. They fixed the `Incomplete` related issues when we have all of the data
+- the `exact!()` combinator will fail if we did not consume the whole input
+- the `take_while_m_n!` combinator will match a specified number of characters
+- `ErrorKind::TakeUntilAndConsume1`
+- the `recognize_float` parser will match a float number's characters, but will not transform to a `f32` or `f64`
+- `alpha` and other basic parsers are now much stricter about partial inputs. We also introduce the `*0` and `*1` versions of those parsers
+- `named_args` can now specify the input type as well
+- `HexDisplay` is now implemented for `&str`
+- `alloc` feature
+- the `InputTakeAtposition` trait allows specialized implementations of parsers like `take_while!`
+
+### Removed
+
+- the producers and consumers were removed
+- the `error_code` and `error_node` macros are not used anymore
+
+### Fixed
+
+- `anychar!` now works correctly with multibyte characters
+- `take_until_and_consume1!` no longer results in "no method named \`find_substring\`" and "no method named \`slice\`" compilation errors
+- `take_until_and_consume1!` returns the correct Incomplete(Needed) amount
+- `no_std` compiles properly, and nom can work with `alloc` too
+- `parse_to!` now consumes its input
+
+### Changed
+
+- `alt` and other combinators will now clone the input if necessary. If the input is already `Copy` there is no performance impact
+- the `rest` parser now works on various input types
+- `InputIter::Item` for `&[u8]` is now a `u8` directly, not a reference
+- we now use the `compile_error` macro to return a compile time error if there was a syntax issue
+- the permutation combinator now supports optional child parsers
+- the float numbers parsers have been refactored to use one common implementation that is nearly 2 times faster than the previous one
+- the float number parsers now accept more variants
+
+
+## [3.2.1] - 2017-10-27
+
+### Thanks
+
+- @ordian for `alt_complete` fixes
+- @friedm for documentation fixes
+- @kali for improving error management
+
+### Fixed
+
+- there were cases where `alt_complete` could return `Incomplete`
+
+### Added
+
+- an `into_error_kind` method can be used to transform any error to a common value. This helps when the library is included multiple times as dependency with different feature sets
+
+
+## [3.2.0] - 2017-07-24
+
+### Thanks
+
+- @jedireza for documentation fixes
+- @gmorenz for the `bytes` combinator
+- @meh for character combinator fixes for UTF-8
+- @jethrogb for avoiding move issues in `separated_list`
+
+### Changed
+
+- new layout for the main page of documentation
+- `anychar` can now work on any input type
+- `length_bytes` is now an alias for `length_data`
+
+### Fixed
+
+- `one_of`, `none_of` and `char` will now index correctly UTF-8 characters
+- the `compiler_error` macro is now correctly exported
+
+
+### Added
+
+- the `bytes` combinator transforms a bit stream back to a byte slice for child parsers
+
+## [3.1.0] - 2017-06-16
+
+### Thanks
+
+- @sdroege: implementing be_i24 and le_i24
+- @Hywan: integrating faster substring search using memchr
+- @nizox: fixing type issues in bit stream parsing
+- @grissiom: documentation fixes
+- @doomrobo: implementing separated_list_complete and separated_nonempty_list_complete
+- @CWood1: fixing memchr integration in no_std
+- @lu_zero: integrating the compiler_error crate
+- @dtolnay: helping debug a type inference issue in map
+
+### Changed
+
+- memchr is used for substring search if possible
+- if building on nightly, some common syntax errors will display a specific error message. If building no stable, display the documentation to activate those messages
+- `count` no longer preallocates its vector
+
+### Fixed
+
+- better type inference in alt_complete
+- `alt` should now work with whitespace parsing
+- `map` should not make type inference errors anymore
+
+### Added
+
+- be_i24 and le_i24, parsing big endian and little endian signed 24 bit integers
+- `separated_list_complete` and `separated_nonempty_list_complete` will treat incomplete from sub parsers as error
+
+## [3.0.0] - 2017-05-12
+
+### Thanks
+
+- Chris Pick for some `Incomplete` related refactors
+- @dbrgn for documentation fixes
+- @valarauca for adding `be_u24`
+- @ithinuel for usability fixes
+- @evuez for README readability fixes and improvements to `IResult`
+- @s3bk for allowing non-`Copy` types as input
+- @keruspe for documentation fixes
+- @0xd34d10cc for trait fixes on `InputIter`
+- @sdleffler for lifetime shenanigans on `named_args`
+- @chengsun for type inference fixes in `alt`
+- @iBelieve for adding str to no_std
+- @Hywan for simplifying code in input traits
+- @azerupi for extensive documentation of `alt` and `alt_complete`
+
+### Breaking Changes
+
+- `escaped`, `separated_list` and `separated_nonempty_list` can now return `Incomplete` when necessary
+- `InputIter` does not require `AsChar` on its `Item` type anymore
+- the `core` feature that was putting nom in `no_std` mode has been removed. There is now a `std` feature, activated by default. If it is not activated, nom is in `no_std`
+- in `verbose-errors` mode, the error list is now stored in a `Vec` instead of a box based linked list
+- `chain!` has finally been removed
+
+### Changed
+
+- `Endianness` now implements `Debug`, `PartialEq`, `Eq`, `Clone` and `Copy`
+- custom input types can now be cloned if they're not `Copy`
+- the infamous 'Cannot infer type for E' error should happen less often now
+- `str` is now available in `no_std` mode
+
+### Fixed
+
+- `FileProducer` will be marked as `Eof` on full buffer
+- `named_args!` now has lifetimes that cannot conflict with the lifetimes from other arguments
+
+### Added
+
+- `be_u24`: big endian 24 bit unsigned integer parsing
+- `IResult` now has a `unwrap_or` method
+
+
+## [2.2.1] - 2017-04-03
+
+### Thanks
+
+- @Victor-Savu for formatting fixes in the README
+- @chifflier for detecting and fixing integer overflows
+- @utkarshkukreti for some performance improvements in benchmarks
+
+### Changed
+
+- when calculating how much data is needed in `IResult::Incomplete`, the addition could overflow (it is stored as a usize). This would apparently not result in any security vulnerability on release code
+
+## [2.2.0] - 2017-03-20
+
+### Thanks
+
+- @seppo0010 for fixing `named_args`
+- @keruspe for implementing or() on `IResult`, adding the option of default cases in `switch!`, adding support for `cargo-travis`
+- @timlyo for documentation fixes
+- @JayKickliter for extending `hex_u32`
+- @1011X for fixing regex integration
+- @Kerollmops for actually marking `chain!` as deprecated
+- @joliss for documentation fixes
+- @utkarshkukreti for tests refactoring and performance improvement
+- @tmccombs for documentation fixes
+
+### Added
+
+- `IResult` gets an `or()` method
+- `take_until1`, `take_until_and_consume1`, `take_till1!` and `take_till1_s!` require at least 1 character
+
+### Changed
+
+- `hex_u32` accepts uppercase digits as well
+- the character based combinators leverage the input traits
+- the whitespace parsers now work on &str and other types
+- `take_while1` returns `Incomplete` on empty input
+- `switch!` can now take a default case
+
+### Fixed
+
+- `named_args!` now imports `IResult` directly
+- the upgrade to regex 0.2 broke the regex combinators, they work now
+
+## [2.1.0] - 2017-01-27
+
+### Thanks
+
+- @nickbabcock for documentation fixes
+- @derekdreery for documentation fixes
+- @DirkyJerky for documentation fixes
+- @saschagrunert for documentation fixes
+- @lucab for documentation fixes
+- @hyone for documentation fixes
+- @tstorch for factoring `Slice`
+- @shepmaster for adding crate categories
+- @antoyo for adding `named_args!`
+
+### Added
+
+- `verify!` uses a first parser, then applies a function to check that its result satisfies some conditions
+- `named_args!` creates a parser function that can accept other arguments along with the input
+- `parse_to!` will use the `parse` method from `FromStr` to parse a value. It will automatically translate the input to a string if necessary
+- `float`, `float_s`, `double`, `double_s` can recognize floating point numbers in text
+
+### Changed
+
+- `escaped!` will now return `Incomplete` if needed
+- `permutation!` supports up to 20 child parsers
+
+## [2.0.1] - 2016-12-10
+
+Bugfix release
+
+*Warning*: there is a small breaking change, `add_error!` is renamed to `add_return_error!`. This was planned for the 2.0 release but was forgotten. This is a small change in a feature that not many people use, for a release that is not yet widely in use, so there will be no 3.0 release for that change.
+
+### Thanks
+
+- @nickbabcock for catching and fixing the `add_error!` mixup
+- @lucab for documentation fixes
+- @jtdowney for noticing that `tag_no_case!` was not working at all for byte slices
+
+### Fixed
+
+- `add_error!` has been renamed to `add_return_error!`
+- the `not!` combinator now accepts functions
+- `tag_no_case!` is now working as accepted (before, it accepted everything)
+
+
+## [2.0] - 2016-11-25
+
+The 2.0 release is one of the biggest yet. It was a good opportunity to clean up some badly named combinators and fix invalid behaviours.
+
+Since this version introduces a few breaking changes, an [upgrade documentation](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_2.md) is available, detailing the steps to fix the most common migration issues. After testing on a set of 30 crates, most of them will build directly, a large part will just need to activate the "verbose-errors" compilation feature. The remaining fixes are documented.
+
+This version also adds a lot of interesting features, like the permutation combinator or whitespace separated formats support.
+
+### Thanks
+
+- @lu-zero for license help
+- @adamgreig for type inference fixes
+- @keruspe for documentation and example fixes, for the `IResult => Result` conversion work, making `AsChar`'s method more consistent, and adding `many_till!`
+- @jdeeny for implementing `Offset` on `&str`
+- @vickenty for documentation fixes and his refactoring of `length_value!` and `length_bytes!`
+- @overdrivenpotato for refactoring some combinators
+- @taralx for documentation fixes
+- @keeperofdakeys for fixing eol behaviour, writing documentation and adding `named_attr!`
+- @jturner314 for writing documentation
+- @bozaro for fixing compilation errors
+- @uniphil for adding a `crates.io` badge
+- @badboy for documentation fixes
+- @jugglerchris for fixing `take_s!`
+- @AndyShiue for implementing `Error` and `Display` on `ErrorKind` and detecting incorrect UTF-8 string indexing
+
+### Added
+
+- the "simple" error management system does not accumulates errors when backtracking. This is a big perf gain, and is activated by default in nom 2.0
+- nom can now work on any type that implement the traits defined in `src/traits.rs`: `InputLength`, `InputIter`, `InputTake`, `Compare`, `FindToken`, `FindSubstring`, `Slice`
+- the documentation from Github's wiki has been moved to the `doc/` directory. They are markdown files that you can build with [cargo-external-doc](https://crates.io/crates/cargo-external-doc)
+- whitespace separated format support: with the `ws!` combinator, you can automatically introduce whitespace parsers between all parsers and combinators
+- the `permutation!` combinator applies its child parsers in any order, as long as they all succeed once, and return a tuple of the results
+- `do_parse!` is a simpler alternative to `chain!`, which is now deprecated
+- you can now transform an `IResult` in a `std::result::Result`
+- `length_data!` parses a length, and returns a subslice of that length
+- `tag_no_case!` provides case independent comparison. It works nicely, without any allocation, for ASCII strings, but for UTF-8 strings, it defaults to an unsatisfying (and incorrect) comparison by lowercasing both strings
+- `named_attr!` creates functions like `named!` but can add attributes like documentation
+- `many_till!` applies repeatedly its first child parser until the second succeeds
+
+### Changed
+
+- the "verbose" error management that was available in previous versions is now activated by the "verbose-errors" compilation feature
+- code reorganization: most of the parsers were moved in separate files to make the source easier to navigate
+- most of the combinators are now independent from the input type
+- the `eof` function was replaced with the `eof!` macro
+- `error!` and `add_error!` were replaced with `return_error!` and `add_return_error!` to fix the name conflict with the log crate
+- the `offset()` method is now in the `Offset` trait
+- `length_value!` has been renamed to `length_count!`. The new `length_value!` selects a slice and applies the second parser once on that slice
+- `AsChar::is_0_to_9` is now `AsChar::is_dec_digit`
+- the combinators with configurable endianness now take an enum instead of a boolean as parameter
+
+### Fixed
+- the `count!`, `count_fixed!` and `length_*!` combinator calculate incomplete data needs correctly
+- `eol`, `line_ending` and `not_line_ending` now have a consistent behaviour that works correctly with incomplete data
+- `take_s!` didn't correctly handle the case when the slice is exactly the right length
+
+## [1.2.4] - 2016-07-20
+
+### Thanks
+- @Phlosioneer for documentation fixes
+- @sourrust for fixing offsets in `take_bits!`
+- @ChrisMacNaughton for the XFS crate
+- @pwoolcoc for `rest_s`
+- @fitzgen for more `IResult` methods
+- @gtors for the negative lookahead feature
+- @frk1 and @jeandudey for little endian float parsing
+- @jethrogb for fixing input usage in `many1`
+- @acatton for beating me at nom golf :D
+
+### Added
+- the `rest_s` method on `IResult` returns the remaining `&str` input
+- `unwrap_err` and `unwrap_inc` methods on `IResult`
+- `not!` will peek at the input and return `Done` if the underlying parser returned `Error` or `Incomplete`, without consuming the input
+- `le_f32` and `le_f64` parse little endian floating point numbers (IEEE 754)
+-
+
+### Fixed
+- documentation fixes
+- `take_bits!` is now more precise
+- `many1` inccorectly used the `len` function instead of `input_len`
+- the INI parser is simpler
+- `recognize!` had an early `return` that is removed now
+
+## [1.2.3] - 2016-05-10
+
+### Thanks
+- @lu-zero for the contribution guidelines
+- @GuillaumeGomez for fixes on `length_bytes` and some documentation
+- @Hywan for documentation and test fixes
+- @Xirdus for correct trait import issues
+- @mspiegel for the new AST example
+- @cholcombe973 for adding the `cond_with_error!` combinator
+- @tstorch for refactoring `many0!`
+- @panicbit for the folding combinators
+- @evestera for `separated_list!` fixes
+- @DanielKeep for correcting some enum imports
+
+### Added
+- Regular expression combinators starting with `re_bytes_` work on byte slices
+- example parsing arithmetic expressions to an AST
+- `cond_with_error!` works like `cond!` but will return `None` if the condition is false, and `Some(value)` if the underlying parser succeeded
+- `fold_many0!`, `fold_many1!` and `fold_many_m_n!` will take a parser, an initial value and a combining function, and fold over the successful applications of the parser
+
+### Fixed
+- `length_bytes!` converts the result of its child parser to usize
+- `take_till!` now imports `InputLength` instead of assuming it's in scope
+- `separated_list!` and `separated_nonempty_list!` will not consume the separator if there's no following successfully parsed value
+- no more warnings on build
+
+### Changed
+- simpler implementation of `many0!`
+
+## [1.2.2] - 2016-03-09
+
+### Thanks
+- @conradev for fixing `take_until_s!`
+- @GuillaumeGomez for some documentation fixes
+- @frewsxcv for some documentation fixes
+- @tstorch for some test refactorings
+
+### Added
+- `nom::Err` now implements `std::error::Error`
+
+### Fixed
+- `hex_u32` does not parses more than 8 chars now
+- `take_while!` and `take_while1!` will not perturb the behaviour of `recognize!` anymore
+
+## [1.2.1] - 2016-02-23
+
+### Thanks
+- @sourrust for adding methods to `IResult`
+- @tstorch for the test refactoring, and for adding methods to `IResult` and `Needed`
+- @joelself for fixing the method system
+
+### Added
+
+- mapping methods over `IResult` and `Needed`
+
+### Changed
+
+- `apply_rf` is renamed to `apply_m`. This will not warrant a major version, since it is part missing from the methods feture added in the 1.2.0 release
+- the `regexp_macros` feature that used `regex!` to precompile regular expressions has been replaced by the normal regex engine combined with `lazy_static`
+
+### Fixed
+
+- when a parser or combinator was returning an empty buffer as remaining part, it was generating one from a static empty string. This was messing with buffer offset calculation. Now, that empty slice is taken like this: `&input[input.len()..]`.
+- The `regexp_macros` and `no_std` feature build again and are now tested with Travis CI
+
+## [1.2.0] - 2016-02-08
+
+### Thanks
+- @zentner-kyle for type inference fixes
+- @joelself for his work on `&str` parsing and method parsers
+- @GuillaumeGomez for implementing methods on `IResult`
+- @dirk for the `alt_complete!` combinator
+- @tstorch for a lot of refactoring work and unit tests additions
+- @jansegre for the hex digit parsers
+- @belgum for some documentation fixes
+- @lwandrebeck for some documentation fixes and code fixes in `hex_digit`
+
+### Added
+- `take_until_and_consume_s!` for consumption of string data until a tag
+- more function patterns in `named!`. The error type can now be specified
+- `alt_complete!` works like the `alt!` combinator, but tries the next branch if the current one returned `Incomplete`, instead of returning directly
+- more unit tests for a lot of combinators
+- hexadecimal digit parsers
+- the `tuple!` combinator takes a list of parsers as argument, and applies them serially on the input. If all of them are successful, it willr eturn a tuple accumulating all the values. This combinator will (hopefully) replace most uses of `chain!`
+- parsers can now be implemented as a method for a struct thanks to the `method!`, `call_m!` and `apply_rf!` combinators
+
+### Fixed
+- there were type inference issues in a few combinators. They will now be easier to compile
+- `peek!` compilation with bare functions
+- `&str` parsers were splitting data at the byte level, not at the char level, which can result in inconsistencies in parsing UTF-8 characters. They now use character indexes
+- some method implementations were missing on `IResult<I,O,E>` (with specified error type instead of implicit)
+
+## [1.1.0] - 2016-01-01
+
+This release adds a lot of features related to `&str` parsing. The previous versions
+were focused on `&[u8]` and bit streams parsing, but there's a need for more text
+parsing with nom. The parsing functions like `alpha`, `digit` and others will now
+accept either a `&[u8]` or a `&str`, so there is no breaking change on that part.
+
+There are also a few performance improvements and documentation fixes.
+
+### Thanks
+- @Binero for pushing the work on `&str` parsing
+- @meh for fixing `Option` and `Vec` imports
+- @hoodie for a documentation fix
+- @joelself for some documentation fixes
+- @vberger for his traits magic making nom functions more generic
+
+### Added
+
+- string related parsers: `tag_s!`, `take_s!`, `is_a_s!`, `is_not_s!`, `take_while_s!`, `take_while1_s!`, `take_till_s!`
+- `value!` is a combinator that always returns the same value. If a child parser is passed as second argument, that value is returned when the child parser succeeds
+
+### Changed
+
+- `tag!` will now compare even on partial input. If it expects "abcd" but receives "ef", it will now return an `Error` instead of `Incomplete`
+- `many0!` and others will preallocate a larger vector to avoid some copies and reallocations
+- `alpha`, `digit`, `alphanumeric`, `space` and `multispace` now accept as input a `&[u8]` or a `&str`. Additionally, they return an error if they receive an empty input
+- `take_while!`, `take_while1!`, `take_while_s!`, `take_while1_s!` wilreturn an error on empty input
+
+### Fixed
+
+- if the child parser of `many0!` or `many1!` returns `Incomplete`, it will return `Incomplete` too, possibly updating the needed size
+- `Option,` `Some`, `None` and `Vec` are now used with full path imports
+
+## [1.0.1] - 2015-11-22
+
+This releases makes the 1.0 version compatible with Rust 1.2 and 1.3
+
+### Thanks
+- @steveklabnik for fixing lifetime issues in Producers and Consumers
+
+## [1.0.0] - 2015-11-16
+
+Stable release for nom. A lot of new features, a few breaking changes
+
+### Thanks
+- @ahenry for macro fixes
+- @bluss for fixing documentation
+- @sourrust for cleaning code and debugging the new streaming utilities
+- @meh for inline optimizations
+- @ccmtaylor for fixing function imports
+- @soro for improvements to the streaming utilities
+- @breard-r for catching my typos
+- @nelsonjchen for catching my typos too
+- @divarvel for hex string parsers
+- @mrordinaire for the `length_bytes!` combinator
+
+### Breaking changes
+- `IResult::Error` can now use custom error types, and is generic over the input type
+- Producers and consumers have been replaced. The new implementation uses less memory and integrates more with parsers
+- `nom::ErrorCode` is now `nom::ErrorKind`
+- `filter!` has been renamed to `take_while!`
+- `chain!` will count how much data is consumed and use that number to calculate how much data is needed if a parser returned `Incomplete`
+- `alt!` returns `Incomplete` if a child parser returned `Incomplete`, instead of skipping to the next parser
+- `IResult` does not require a lifetime tag anymore, yay!
+
+### Added
+
+- `complete!` will return an error if the child parser returned `Incomplete`
+- `add_error!` will wrap an error, but allow backtracking
+- `hex_u32` parser
+
+### Fixed
+- the behaviour around `Incomplete` is better for most parsers now
+
+## [0.5.0] - 2015-10-16
+
+This release fixes a few issues and stabilizes the code.
+
+### Thanks
+- @nox for documentation fixes
+- @daboross for linting fixes
+- @ahenry for fixing `tap!` and extending `dbg!` and `dbg_dmp!`
+- @bluss for tracking down and fixing issues with unsafe code
+- @meh for inlining parser functions
+- @ccmtaylor for fixing import of `str::from_utf8`
+
+### Fixed
+- `tap!`, `dbg!` and `dbg_dmp!` now accept function parameters
+
+### Changed
+- the type used in `count_fixed!` must be `Copy`
+- `chain!` calculates how much data is needed if one of the parsers returns `Incomplete
+- optional parsers in `chain!` can return `Incomplete`
+
+## [0.4.0] - 2015-09-08
+
+Considering the number of changes since the last release, this version can contain breaking changes, so the version number becomes 0.4.0. A lot of new features and performance improvements!
+
+### Thanks
+- @frewsxcv for documentation fixes
+- @ngrewe for his work on producers and consumers
+- @meh for fixes on `chain!` and for the `rest` parser
+- @daboross for refactoring `many0!` and `many1!`
+- @aleksander for the `switch!` combinator idea
+- @TechnoMancer for his help with bit level parsing
+- @sxeraverx for pointing out a bug in `is_a!`
+
+### Fixed
+- `count_fixed!` must take an explicit type as argument to generate the fixed-size array
+- optional parsing behaviour in `chain!`
+- `count!` can take 0 elements
+- `is_a!` and `is_not!` can now consume the whole input
+
+### Added
+- it is now possible to seek to the end of a `MemProducer`
+- `opt!` returns `Done(input, None)` if `the child parser returned `Incomplete`
+- `rest` will return the remaining input
+- consumers can now seek to and from the end of input
+- `switch!` applies a first parser then matches on its result to choose the next parser
+- bit-level parsers
+- character-level parsers
+- regular expression parsers
+- implementation of `take_till!`, `take_while!` and `take_while1!`
+
+### Changed
+- `alt!` can return `Incomplete`
+- the error analysis functions will now take references to functions instead of moving them
+- performance improvements on producers
+- performance improvement for `filter!`
+- performance improvement for `count!`: a `Vec` of the right size is directly allocated
+
+## [0.3.11] - 2015-08-04
+
+### Thanks
+- @bluss for remarking that the crate included random junk lying non committed in my local repository
+
+### Fixed
+- cleanup of my local repository will ship less files in the crates, resulting in a smaller download
+
+## [0.3.10] - 2015-08-03
+
+### Added
+
+- `bits!` for bit level parsing. It indicates that all child parsers will take a `(&[u8], usize)`as input, with the second parameter indicating the bit offset in the first byte. This allows viewing a byte slice as a bit stream. Most combinators can be used directly under `bits!`
+- `take_bits!` takes an integer type and a number of bits, consumes that number of bits and updates the offset, possibly by crossing byte boundaries
+- bit level parsers are all written in `src/bits.rs`
+
+### Changed
+
+- Parsers that specifically handle bytes have been moved to src/bytes.rs`. This applies to `tag!`, `is_not!`, `is_a!`, `filter!`, `take!`, `take_str!`, `take_until_and_consume!`, `take_until!`, `take_until_either_and_consume!`, `take_until_either!`
+
+## [0.3.9] - 2015-07-20
+
+### Thanks
+- @badboy for fixing `filter!`
+- @idmit for some documentation fixes
+
+### Added
+- `opt_res!` applies a parser and transform its result in a Result. This parser never fails
+- `cond_reduce!` takes an expression as parameter, applies the parser if the expression is true, and returns an error if the expression is false
+- `tap!` pass the result of a parser to a block to manipulate it, but do not affect the parser's result
+- `AccReader` is a Read+BufRead that supports data accumulation and partial consumption. The `consume` method must be called afterwardsto indicate how much was consumed
+- Arithmetic expression evaluation and parsing example
+- `u16!`, `u32!`, `u64!`, `i16!`, `i32!`, `i64!` take an expression as parameter, if the expression is true, apply the big endian integer parser, if false, the little endian version
+- type information for combinators. This will make the documentation a bit easier to navigate
+
+### Fixed
+- `map_opt!` and `map_res!` had issues with argument order due to bad macros
+- `delimited!` did not compile for certain combinations of arguments
+- `filter!` did not return a byte slice but a fixed array
+
+## [0.3.8] - 2015-07-03
+
+### Added
+- code coverage is now calculated automatically on Travis CI
+- `Stepper`: wrap a `Producer`, and call the method `step` with a parser. This method will buffer data if there is not enough, apply the parser if there is, and keep the rest of the input in memory for the next call
+- `ReadProducer`: takes something implementing `Read`, and makes a `Producer` out of it
+
+### Fixed
+- the combinators `separated_pair!` and `delimited!` did not work because an implementation macro was not exported
+- if a `MemProducer` reached its end, it should always return `Eof`
+- `map!` had issues with argument matching
+
+## [0.3.7] - 2015-06-24
+
+### Added
+- `expr_res!` and `expr_opt!` evaluate an expression returning a Result or Opt and convert it to IResult
+- `AsBytes` is implemented for fixed size arrays. This allows `tag!([41u8, 42u8])`
+
+### Fixed
+- `count_fixed!` argument parsing works again
+
+## [0.3.6] - 2015-06-15
+
+### Added
+- documentation for a few functions
+- the consumer trait now requires the `failed(&self, error_code)` method in case of parsing error
+- `named!` now handles the alternative `named!(pub fun_name<OutputType>, ...)`
+
+### Fixed
+- `filter!` now returns the whole input if the filter function never returned false
+- `take!` casts its argument as usize, so it can accepts any integer type now
+
+## [0.3.5] - 2015-06-10
+
+### Thanks
+- @cmr for some documentation fixes
+
+### Added
+- `count_fixed!` returns a fixed array
+
+### Fixed
+- `count!` is back to the previous behaviour, returning a `Vec` for sizes known at runtime
+
+### Changed
+- functions and traits exported from `nom::util` are now directly in `nom::`
+
+## [0.3.4] - 2015-06-09
+
+### Thanks
+- @andrew-d for fixes on `cond!`
+- @keruspe for features in `chain!`
+
+### Added
+- `chain!` can now have mutable fields
+
+### Fixed
+- `cond!` had an infinite macro recursion
+
+### Changed
+- `chain!` generates less code now. No apprent compilation time improvement
+
+## [0.3.3] - 2015-06-09
+
+### Thanks
+- @andrew-d for the little endian signed integer parsers
+- @keruspe for fixes on `count!`
+
+### Added
+- `le_i8`, `le_i16`, `le_i32`, `le_i64`: little endian signed integer parsers
+
+### Changed
+- the `alt!` parser compiles much faster, even with more than 8 branches
+- `count!` can now return a fixed size array instead of a growable vector
+
+## [0.3.2] - 2015-05-31
+
+### Thanks
+- @keruspe for the `take_str` parser and the function application combinator
+
+### Added
+- `take_str!`: takes the specified number of bytes and return a UTF-8 string
+- `apply!`: do partial application on the parameters of a function
+
+### Changed
+- `Needed::Size` now contains a `usize` instead of a `u32`
+
+## [0.3.1] - 2015-05-21
+
+### Thanks
+- @divarvel for the big endian signed integer parsers
+
+### Added
+- `be_i8`, `be_i16`, `be_i32`, `be_i64`: big endian signed integer parsers
+- the `core` feature can be passed to cargo to build with `no_std`
+- colored hexdump can be generated from error chains
+
+## [0.3.0] - 2015-05-07
+
+### Thanks
+- @filipegoncalves for some documentation and the new eof parser
+- @CrimsonVoid for putting fully qualified types in the macros
+- @lu_zero for some documentation fixes
+
+### Added
+- new error types that can contain an error code, an input slice, and a list of following errors
+- `error!` will cut backtracking and return directly from the parser, with a specified error code
+- `eof` parser, successful if there is no more input
+- specific error codes for the parsers provided by nom
+
+### Changed
+- fully qualified types in macros. A lot of imports are not needed anymore
+
+### Removed
+- `FlatMap`, `FlatpMapOpt` and `Functor` traits (replaced by `map!`, `map_opt!` and `map_res!`)
+
+## [0.2.2] - 2015-04-12
+
+### Thanks
+- @filipegoncalves and @thehydroimpulse for debugging an infinite loop in many0 and many1
+- @thehydroimpulse for suggesting public named parsers
+- @skade for removing the dependency on the collections gate
+
+### Added
+- `named!` can now declare public functions like this: `named!(pub tst, tag!("abcd"));`
+- `pair!(X,Y)` returns a tuple `(x, y)`
+- `separated_pair!(X, sep, Y)` returns a tuple `(x, y)`
+- `preceded!(opening, X)` returns `x`
+- `terminated!(X, closing)` returns `x`
+- `delimited(opening, X, closing)` returns `x`
+- `separated_list(sep, X)` returns a `Vec<X>`
+- `separated_nonempty_list(sep, X)` returns a `Vec<X>` of at list one element
+
+### Changed
+- `many0!` and `many1!` forbid parsers that do not consume input
+- `is_a!`, `is_not!`, `alpha`, `digit`, `space`, `multispace` will now return an error if they do not consume at least one byte
+
+## [0.2.1] - 2015-04-04
+
+### Thanks
+- @mtsr for catching the remaining debug println!
+- @jag426 who killed a lot of warnings
+- @skade for removing the dependency on the core feature gate
+
+
+### Added
+- little endian unsigned int parsers le_u8, le_u16, le_u32, le_u64
+- `count!` to apply a parser a specified number of times
+- `cond!` applies a parser if the condition is met
+- more parser development tools in `util::*`
+
+### Fixed
+- in one case, `opt!` would not compile
+
+### Removed
+- most of the feature gates are now removed. The only one still needed is `collections`
+
+## [0.2.0] - 2015-03-24
+*works with `rustc 1.0.0-dev (81e2396c7 2015-03-19) (built 2015-03-19)`*
+
+### Thanks
+- Ryman for the AsBytes implementation
+- jag426 and jaredly for documentation fixes
+- eternaleye on #rust IRC for his help on the new macro syntax
+
+### Changed
+- the AsBytes trait improves readability, no more b"...", but "..." instead
+- Incomplete will now hold either Needed;;Unknown, or Needed::Size(u32). Matching on Incomplete without caring for the value is done with `Incomplete(_)`, but if more granularity is mandatory, `Needed` can be matched too
+- `alt!` can pass the result of the parser to a closure
+- the `take_*` macros changed behaviour, the default case is now not to consume the separator. The macros have been renamed as follows: `take_until!` -> `take_until_and_consume!`, `take_until_and_leave!` -> `take_until!`, `take_until_either_and_leave!` -> `take_until_either!`, `take_until_either!` -> `take_until_either_and_consume!`
+
+### Added
+- `peek!` macro: matches the future input but does not consume it
+- `length_value!` macro: the first argument is a parser returning a `n` that can cast to usize, then applies the second parser `n` times. The macro has a variant with a third argument indicating the expected input size for the second parser
+- benchmarks are available at https://github.com/Geal/nom_benchmarks
+- more documentation
+- **Unnamed parser syntax**: warning, this is a breaking change. With this new syntax, the macro combinators do not generate functions anymore, they create blocks. That way, they can be nested, for better readability. The `named!` macro is provided to create functions from parsers. Please be aware that nesting parsers comes with a small cost of compilation time, negligible in most cases, but can quickly get to the minutes scale if not careful. If this happens, separate your parsers in multiple subfunctions.
+- `named!`, `closure!` and `call!` macros used to support the unnamed syntax
+- `map!`, `map_opt!` and `map_res!` to combine a parser with a normal function, transforming the input directly, or returning an `Option` or `Result`
+
+### Fixed
+- `is_a!` is now working properly
+
+### Removed
+- the `o!` macro does less than `chain!`, so it has been removed
+- the `fold0!` and `fold1!` macros were too complex and awkward to use, the `many*` combinators will be useful for most uses for now
+
+## [0.1.6] - 2015-02-24
+### Changed
+- consumers must have an end method that will be called after parsing
+
+### Added
+- big endian unsigned int and float parsers: be_u8, be_u16, be_u32, be_u64, be_f32, be_f64
+- producers can seek
+- function and macros documentation
+- README documentation
+### Fixed
+- lifetime declarations
+- tag! can return Incomplete
+
+## [0.1.5] - 2015-02-17
+### Changed
+- traits were renamed: FlatMapper -> FlatMap, Mapper -> FlatMapOpt, Mapper2 -> Functor
+
+### Fixed
+- woeks with rustc f1bb6c2f4
+
+## [0.1.4] - 2015-02-17
+### Changed
+- the chaining macro can take optional arguments with '?'
+
+## [0.1.3] - 2015-02-16
+### Changed
+- the chaining macro now takes the closure at the end of the argument list
+
+## [0.1.2] - 2015-02-16
+### Added
+- flat_map implementation for <&[u8], &[u8]>
+- chaining macro
+- partial MP4 parser example
+
+
+## [0.1.1] - 2015-02-06
+### Fixed
+- closure syntax change
+
+<!-- next-url -->
+[Unreleased]: https://github.com/epage/nom8/compare/v0.2.0...HEAD
+[0.2.0]: https://github.com/epage/nom8/compare/v0.1.0...v0.2.0
+[0.1.0]: https://github.com/Geal/nom/compare/294ffb3d9e0ade2c3b7ddfff52484b6d643dcce1...v0.1.0
+[7.0.0]: https://github.com/Geal/nom/compare/6.2.1...7.0.0
+[6.2.1]: https://github.com/Geal/nom/compare/6.2.0...6.2.1
+[6.2.0]: https://github.com/Geal/nom/compare/6.1.2...6.2.0
+[6.1.2]: https://github.com/Geal/nom/compare/6.1.1...6.1.2
+[6.1.1]: https://github.com/Geal/nom/compare/6.1.0...6.1.1
+[6.1.0]: https://github.com/Geal/nom/compare/6.0.1...6.1.0
+[6.0.1]: https://github.com/Geal/nom/compare/6.0.0...6.0.1
+[6.0.0]: https://github.com/Geal/nom/compare/5.1.1...6.0.0
+[5.1.1]: https://github.com/Geal/nom/compare/5.1.0...5.1.1
+[5.1.0]: https://github.com/Geal/nom/compare/5.0.1...5.1.0
+[5.0.1]: https://github.com/Geal/nom/compare/5.0.0...5.0.1
+[5.0.0]: https://github.com/Geal/nom/compare/4.2.3...5.0.0
+[4.2.3]: https://github.com/Geal/nom/compare/4.2.2...4.2.3
+[4.2.2]: https://github.com/Geal/nom/compare/4.2.1...4.2.2
+[4.2.1]: https://github.com/Geal/nom/compare/4.2.0...4.2.1
+[4.2.0]: https://github.com/Geal/nom/compare/4.1.1...4.2.0
+[4.1.1]: https://github.com/Geal/nom/compare/4.1.0...4.1.1
+[4.1.0]: https://github.com/Geal/nom/compare/4.0.0...4.1.0
+[4.0.0]: https://github.com/Geal/nom/compare/3.2.1...4.0.0
+[3.2.1]: https://github.com/Geal/nom/compare/3.2.0...3.2.1
+[3.2.0]: https://github.com/Geal/nom/compare/3.1.0...3.2.0
+[3.1.0]: https://github.com/Geal/nom/compare/3.0.0...3.1.0
+[3.0.0]: https://github.com/Geal/nom/compare/2.2.1...3.0.0
+[2.2.1]: https://github.com/Geal/nom/compare/2.2.0...2.2.1
+[2.2.0]: https://github.com/Geal/nom/compare/2.1.0...2.2.0
+[2.1.0]: https://github.com/Geal/nom/compare/2.0.1...2.1.0
+[2.0.1]: https://github.com/Geal/nom/compare/2.0.0...2.0.1
+[2.0.0]: https://github.com/Geal/nom/compare/1.2.4...2.0.0
+[1.2.4]: https://github.com/Geal/nom/compare/1.2.3...1.2.4
+[1.2.3]: https://github.com/Geal/nom/compare/1.2.2...1.2.3
+[1.2.2]: https://github.com/Geal/nom/compare/1.2.1...1.2.2
+[1.2.1]: https://github.com/Geal/nom/compare/1.2.0...1.2.1
+[1.2.0]: https://github.com/Geal/nom/compare/1.1.0...1.2.0
+[1.1.0]: https://github.com/Geal/nom/compare/1.0.1...1.1.0
+[1.0.1]: https://github.com/Geal/nom/compare/1.0.0...1.0.1
+[1.0.0]: https://github.com/Geal/nom/compare/0.5.0...1.0.0
+[0.5.0]: https://github.com/geal/nom/compare/0.4.0...0.5.0
+[0.4.0]: https://github.com/geal/nom/compare/0.3.11...0.4.0
+[0.3.11]: https://github.com/geal/nom/compare/0.3.10...0.3.11
+[0.3.10]: https://github.com/geal/nom/compare/0.3.9...0.3.10
+[0.3.9]: https://github.com/geal/nom/compare/0.3.8...0.3.9
+[0.3.8]: https://github.com/Geal/nom/compare/0.3.7...0.3.8
+[0.3.7]: https://github.com/Geal/nom/compare/0.3.6...0.3.7
+[0.3.6]: https://github.com/Geal/nom/compare/0.3.5...0.3.6
+[0.3.5]: https://github.com/Geal/nom/compare/0.3.4...0.3.5
+[0.3.4]: https://github.com/Geal/nom/compare/0.3.3...0.3.4
+[0.3.3]: https://github.com/Geal/nom/compare/0.3.2...0.3.3
+[0.3.2]: https://github.com/Geal/nom/compare/0.3.1...0.3.2
+[0.3.1]: https://github.com/Geal/nom/compare/0.3.0...0.3.1
+[0.3.0]: https://github.com/Geal/nom/compare/0.2.2...0.3.0
+[0.2.2]: https://github.com/Geal/nom/compare/0.2.1...0.2.2
+[0.2.1]: https://github.com/Geal/nom/compare/0.2.0...0.2.1
+[0.2.0]: https://github.com/Geal/nom/compare/0.1.6...0.2.0
+[0.1.6]: https://github.com/Geal/nom/compare/0.1.5...0.1.6
+[0.1.5]: https://github.com/Geal/nom/compare/0.1.4...0.1.5
+[0.1.4]: https://github.com/Geal/nom/compare/0.1.3...0.1.4
+[0.1.3]: https://github.com/Geal/nom/compare/0.1.2...0.1.3
+[0.1.2]: https://github.com/Geal/nom/compare/0.1.1...0.1.2
+[0.1.1]: https://github.com/Geal/nom/compare/0.1.0...0.1.1
diff --git a/vendor/nom8/Cargo.lock b/vendor/nom8/Cargo.lock
new file mode 100644
index 000000000..ee1cc52a5
--- /dev/null
+++ b/vendor/nom8/Cargo.lock
@@ -0,0 +1,283 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[package]]
+name = "bit-set"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1"
+dependencies = [
+ "bit-vec",
+]
+
+[[package]]
+name = "bit-vec"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb"
+
+[[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "doc-comment"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
+
+[[package]]
+name = "fastrand"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "fnv"
+version = "1.0.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
+
+[[package]]
+name = "getrandom"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
+name = "instant"
+version = "0.1.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.135"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "nom8"
+version = "0.2.0"
+dependencies = [
+ "doc-comment",
+ "memchr",
+ "proptest",
+]
+
+[[package]]
+name = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "ppv-lite86"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proptest"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5"
+dependencies = [
+ "bit-set",
+ "bitflags",
+ "byteorder",
+ "lazy_static",
+ "num-traits",
+ "quick-error 2.0.1",
+ "rand",
+ "rand_chacha",
+ "rand_xorshift",
+ "regex-syntax",
+ "rusty-fork",
+ "tempfile",
+]
+
+[[package]]
+name = "quick-error"
+version = "1.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
+
+[[package]]
+name = "quick-error"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
+
+[[package]]
+name = "rand"
+version = "0.8.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+dependencies = [
+ "libc",
+ "rand_chacha",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core",
+]
+
+[[package]]
+name = "rand_core"
+version = "0.6.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+dependencies = [
+ "getrandom",
+]
+
+[[package]]
+name = "rand_xorshift"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f"
+dependencies = [
+ "rand_core",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "rusty-fork"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
+dependencies = [
+ "fnv",
+ "quick-error 1.2.3",
+ "tempfile",
+ "wait-timeout",
+]
+
+[[package]]
+name = "tempfile"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "libc",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
+]
+
+[[package]]
+name = "wait-timeout"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/vendor/nom8/Cargo.toml b/vendor/nom8/Cargo.toml
new file mode 100644
index 000000000..0f638e6b5
--- /dev/null
+++ b/vendor/nom8/Cargo.toml
@@ -0,0 +1,201 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+rust-version = "1.51.0"
+name = "nom8"
+version = "0.2.0"
+include = [
+ "CHANGELOG.md",
+ "LICENSE",
+ "README.md",
+ ".gitignore",
+ "Cargo.toml",
+ "src/*.rs",
+ "src/*/*.rs",
+ "tests/*.rs",
+]
+autoexamples = false
+description = "A byte-oriented, zero-copy, parser combinators library (fork for proposals for v8)"
+readme = "README.md"
+keywords = [
+ "parser",
+ "parser-combinators",
+ "parsing",
+ "streaming",
+ "bit",
+]
+categories = ["parsing"]
+license = "MIT"
+repository = "https://github.com/epage/nom-experimental"
+
+[package.metadata.docs.rs]
+features = ["unstable-doc"]
+rustdoc-args = [
+ "--cfg",
+ "docsrs",
+]
+cargo-args = [
+ "-Zunstable-options",
+ "-Zrustdoc-scrape-examples",
+]
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = "Unreleased"
+replace = "{{version}}"
+min = 1
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = '\.\.\.HEAD'
+replace = "...{{tag_name}}"
+exactly = 1
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = "ReleaseDate"
+replace = "{{date}}"
+min = 1
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = "<!-- next-header -->"
+replace = """
+<!-- next-header -->
+## [Unreleased] - ReleaseDate
+"""
+exactly = 1
+
+[[package.metadata.release.pre-release-replacements]]
+file = "CHANGELOG.md"
+search = "<!-- next-url -->"
+replace = """
+<!-- next-url -->
+[Unreleased]: https://github.com/epage/nom8/compare/{{tag_name}}...HEAD"""
+exactly = 1
+
+[profile.bench]
+lto = true
+codegen-units = 1
+debug = true
+
+[[example]]
+name = "custom_error"
+path = "examples/custom_error.rs"
+required-features = ["alloc"]
+
+[[example]]
+name = "json"
+path = "examples/json.rs"
+required-features = ["alloc"]
+
+[[example]]
+name = "json_iterator"
+path = "examples/json_iterator.rs"
+required-features = ["alloc"]
+
+[[example]]
+name = "iterator"
+path = "examples/iterator.rs"
+
+[[example]]
+name = "s_expression"
+path = "examples/s_expression.rs"
+required-features = ["alloc"]
+
+[[example]]
+name = "string"
+path = "examples/string.rs"
+required-features = ["alloc"]
+
+[[test]]
+name = "arithmetic"
+
+[[test]]
+name = "arithmetic_ast"
+required-features = ["alloc"]
+
+[[test]]
+name = "css"
+
+[[test]]
+name = "custom_errors"
+
+[[test]]
+name = "float"
+
+[[test]]
+name = "ini"
+required-features = ["alloc"]
+
+[[test]]
+name = "ini_str"
+required-features = ["alloc"]
+
+[[test]]
+name = "issues"
+required-features = ["alloc"]
+
+[[test]]
+name = "json"
+
+[[test]]
+name = "mp4"
+required-features = ["alloc"]
+
+[[test]]
+name = "multiline"
+required-features = ["alloc"]
+
+[[test]]
+name = "overflow"
+
+[[test]]
+name = "reborrow_fold"
+
+[[test]]
+name = "fnmut"
+required-features = ["alloc"]
+
+[dependencies.memchr]
+version = "2.3"
+default-features = false
+
+[dev-dependencies.doc-comment]
+version = "0.3"
+
+[dev-dependencies.proptest]
+version = "1.0.0"
+
+[features]
+alloc = []
+default = ["std"]
+std = [
+ "alloc",
+ "memchr/std",
+]
+unstable-doc = [
+ "alloc",
+ "std",
+]
+
+[badges.coveralls]
+branch = "main"
+repository = "Geal/nom"
+service = "github"
+
+[badges.maintenance]
+status = "actively-developed"
+
+[badges.travis-ci]
+repository = "Geal/nom"
diff --git a/vendor/nom8/LICENSE b/vendor/nom8/LICENSE
new file mode 100644
index 000000000..88557e44e
--- /dev/null
+++ b/vendor/nom8/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2014-2019 Geoffroy Couprie
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/vendor/nom8/README.md b/vendor/nom8/README.md
new file mode 100644
index 000000000..55ed37759
--- /dev/null
+++ b/vendor/nom8/README.md
@@ -0,0 +1,330 @@
+# nom, eating data byte by byte
+
+**NOTE:** This is an unofficial, short-lived fork. I'm nominating nom8 to be nom v8.
+- `main` branch is for proposed changes to `nom`
+- `nom8` branch adapts `main` for `nom8` releases
+
+[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
+[![Join the chat at https://gitter.im/Geal/nom](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Geal/nom?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Build Status](https://github.com/Geal/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/Geal/nom/actions/workflows/ci.yml)
+[![Coverage Status](https://coveralls.io/repos/github/Geal/nom/badge.svg?branch=main)](https://coveralls.io/github/Geal/nom?branch=main)
+[![Crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom)
+
+nom is a parser combinators library written in Rust. Its goal is to provide tools
+to build safe parsers without compromising the speed or memory consumption. To
+that end, it uses extensively Rust's *strong typing* and *memory safety* to produce
+fast and correct parsers, and provides functions, macros and traits to abstract most of the
+error prone plumbing.
+
+![nom logo in CC0 license, by Ange Albertini](https://raw.githubusercontent.com/Geal/nom/main/assets/nom.png)
+
+*nom will happily take a byte out of your files :)*
+
+<!-- toc -->
+
+- [Example](#example)
+- [Documentation](#documentation)
+- [Why use nom?](#why-use-nom)
+ - [Binary format parsers](#binary-format-parsers)
+ - [Text format parsers](#text-format-parsers)
+ - [Programming language parsers](#programming-language-parsers)
+ - [Streaming formats](#streaming-formats)
+- [Parser combinators](#parser-combinators)
+- [Technical features](#technical-features)
+- [Rust version requirements](#rust-version-requirements-msrv)
+- [Installation](#installation)
+- [Related projects](#related-projects)
+- [Parsers written with nom](#parsers-written-with-nom)
+- [Contributors](#contributors)
+
+<!-- tocstop -->
+
+## Example
+
+[Hexadecimal color](https://developer.mozilla.org/en-US/docs/Web/CSS/color) parser:
+
+```rust
+use nom8::prelude::*;
+use nom8::{
+ IResult,
+ bytes::complete::{tag, take_while_m_n},
+ sequence::tuple
+};
+
+#[derive(Debug,PartialEq)]
+pub struct Color {
+ pub red: u8,
+ pub green: u8,
+ pub blue: u8,
+}
+
+fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
+ u8::from_str_radix(input, 16)
+}
+
+fn is_hex_digit(c: char) -> bool {
+ c.is_digit(16)
+}
+
+fn hex_primary(input: &str) -> IResult<&str, u8> {
+ take_while_m_n(2, 2, is_hex_digit).map_res(from_hex).parse(input)
+}
+
+fn hex_color(input: &str) -> IResult<&str, Color> {
+ let (input, _) = tag("#")(input)?;
+ let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?;
+
+ Ok((input, Color { red, green, blue }))
+}
+
+fn main() {}
+
+#[test]
+fn parse_color() {
+ assert_eq!(hex_color("#2F14DF"), Ok(("", Color {
+ red: 47,
+ green: 20,
+ blue: 223,
+ })));
+}
+```
+
+## Documentation
+
+- [Reference documentation](https://docs.rs/nom)
+- [Various design documents and tutorials](https://github.com/Geal/nom/tree/main/doc)
+- [List of combinators and their behaviour](https://docs.rs/nom/latest/nom/combinator/index.html)
+
+If you need any help developing your parsers, please ping `geal` on IRC (libera, geeknode, oftc), go to `#nom-parsers` on Libera IRC, or on the [Gitter chat room](https://gitter.im/Geal/nom).
+
+## Why use nom
+
+If you want to write:
+
+### Binary format parsers
+
+nom was designed to properly parse binary formats from the beginning. Compared
+to the usual handwritten C parsers, nom parsers are just as fast, free from
+buffer overflow vulnerabilities, and handle common patterns for you:
+
+- [TLV](https://en.wikipedia.org/wiki/Type-length-value)
+- Bit level parsing
+- Hexadecimal viewer in the debugging macros for easy data analysis
+- Streaming parsers for network formats and huge files
+
+Example projects:
+
+- [FLV parser](https://github.com/rust-av/flavors)
+- [Matroska parser](https://github.com/rust-av/matroska)
+- [tar parser](https://github.com/Keruspe/tar-parser.rs)
+
+### Text format parsers
+
+While nom was made for binary format at first, it soon grew to work just as
+well with text formats. From line based formats like CSV, to more complex, nested
+formats such as JSON, nom can manage it, and provides you with useful tools:
+
+- Fast case insensitive comparison
+- Recognizers for escaped strings
+- Regular expressions can be embedded in nom parsers to represent complex character patterns succinctly
+- Special care has been given to managing non ASCII characters properly
+
+Example projects:
+
+- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser)
+- [TOML parser](https://github.com/joelself/tomllib)
+
+### Programming language parsers
+
+While programming language parsers are usually written manually for more
+flexibility and performance, nom can be (and has been successfully) used
+as a prototyping parser for a language.
+
+nom will get you started quickly with powerful custom error types, that you
+can leverage with [nom_locate](https://github.com/fflorent/nom_locate) to
+pinpoint the exact line and column of the error. No need for separate
+tokenizing, lexing and parsing phases: nom can automatically handle whitespace
+parsing, and construct an AST in place.
+
+Example projects:
+
+- [PHP VM](https://github.com/tagua-vm/parser)
+- eve language prototype
+- [xshade shading language](https://github.com/xshade-lang/xshade/)
+
+### Streaming formats
+
+While a lot of formats (and the code handling them) assume that they can fit
+the complete data in memory, there are formats for which we only get a part
+of the data at once, like network formats, or huge files.
+nom has been designed for a correct behaviour with partial data: If there is
+not enough data to decide, nom will tell you it needs more instead of silently
+returning a wrong result. Whether your data comes entirely or in chunks, the
+result should be the same.
+
+It allows you to build powerful, deterministic state machines for your protocols.
+
+Example projects:
+
+- [HTTP proxy](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http/parser)
+- [Using nom with generators](https://github.com/Geal/generator_nom)
+
+## Parser combinators
+
+Parser combinators are an approach to parsers that is very different from
+software like [lex](https://en.wikipedia.org/wiki/Lex_(software)) and
+[yacc](https://en.wikipedia.org/wiki/Yacc). Instead of writing the grammar
+in a separate file and generating the corresponding code, you use very
+small functions with very specific purpose, like "take 5 bytes", or
+"recognize the word 'HTTP'", and assemble them in meaningful patterns
+like "recognize 'HTTP', then a space, then a version".
+The resulting code is small, and looks like the grammar you would have
+written with other parser approaches.
+
+This has a few advantages:
+
+- The parsers are small and easy to write
+- The parsers components are easy to reuse (if they're general enough, please add them to nom!)
+- The parsers components are easy to test separately (unit tests and property-based tests)
+- The parser combination code looks close to the grammar you would have written
+- You can build partial parsers, specific to the data you need at the moment, and ignore the rest
+
+## Technical features
+
+nom parsers are for:
+- [x] **byte-oriented**: The basic type is `&[u8]` and parsers will work as much as possible on byte array slices (but are not limited to them)
+- [x] **bit-oriented**: nom can address a byte slice as a bit stream
+- [x] **string-oriented**: The same kind of combinators can apply on UTF-8 strings as well
+- [x] **zero-copy**: If a parser returns a subset of its input data, it will return a slice of that input, without copying
+- [x] **streaming**: nom can work on partial data and detect when it needs more data to produce a correct result
+- [x] **descriptive errors**: The parsers can aggregate a list of error codes with pointers to the incriminated input slice. Those error lists can be pattern matched to provide useful messages.
+- [x] **custom error types**: You can provide a specific type to improve errors returned by parsers
+- [x] **safe parsing**: nom leverages Rust's safe memory handling and powerful types, and parsers are routinely fuzzed and tested with real world data. So far, the only flaws found by fuzzing were in code written outside of nom
+- [x] **speed**: Benchmarks have shown that nom parsers often outperform many parser combinators library like Parsec and attoparsec, some regular expression engines and even handwritten C parsers
+
+Some benchmarks are available on [Github](https://github.com/Geal/nom_benchmarks).
+
+## Rust version requirements (MSRV)
+
+The 7.0 series of nom has **a minimum-supported Rust version (MSRV) of 1.51.0**. It is known to work properly on Rust 1.41.1 but there is no guarantee it will stay the case through this major release.
+
+The current policy is that this will only be updated in the next major nom release.
+
+## Installation
+
+nom is available on [crates.io](https://crates.io/crates/nom) and can be included in your Cargo enabled project like this:
+
+```toml
+[dependencies]
+nom = "7"
+```
+
+There are a few compilation features:
+
+* `alloc`: (activated by default) if disabled, nom can work in `no_std` builds without memory allocators. If enabled, combinators that allocate (like `many0`) will be available
+* `std`: (activated by default, activates `alloc` too) if disabled, nom can work in `no_std` builds
+
+You can configure those features like this:
+
+```toml
+[dependencies.nom]
+version = "7"
+default-features = false
+features = ["alloc"]
+```
+
+# Related projects
+
+- [Get line and column info in nom's input type](https://github.com/fflorent/nom_locate)
+- [Using nom as lexer and parser](https://github.com/Rydgel/monkey-rust)
+
+# Parsers written with nom
+
+Here is a (non exhaustive) list of known projects using nom:
+
+- Text file formats: [Ceph Crush](https://github.com/cholcombe973/crushtool),
+[Cronenberg](https://github.com/ayrat555/cronenberg),
+[XFS Runtime Stats](https://github.com/ChrisMacNaughton/xfs-rs),
+[CSV](https://github.com/GuillaumeGomez/csv-parser),
+[FASTA](https://github.com/TianyiShi2001/nom-fasta),
+[FASTQ](https://github.com/elij/fastq.rs),
+[INI](https://github.com/Geal/nom/blob/main/tests/ini.rs),
+[ISO 8601 dates](https://github.com/badboy/iso8601),
+[libconfig-like configuration file format](https://github.com/filipegoncalves/rust-config),
+[Web archive](https://github.com/sbeckeriv/warc_nom_parser),
+[PDB](https://github.com/TianyiShi2001/nom-pdb),
+[proto files](https://github.com/tafia/protobuf-parser),
+[Fountain screenplay markup](https://github.com/adamchalmers/fountain-rs),
+[vimwiki](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki) & [vimwiki_macros](https://github.com/chipsenkbeil/vimwiki-server/tree/master/vimwiki_macros)
+- Programming languages:
+[PHP](https://github.com/tagua-vm/parser),
+[Basic Calculator](https://github.com/balajisivaraman/basic_calculator_rs),
+[GLSL](https://github.com/phaazon/glsl),
+[Lua](https://github.com/doomrobo/nom-lua53),
+[Python](https://github.com/ProgVal/rust-python-parser),
+[SQL](https://github.com/ms705/nom-sql),
+[Elm](https://github.com/cout970/Elm-interpreter),
+[SystemVerilog](https://github.com/dalance/sv-parser),
+[Turtle](https://github.com/vandenoever/rome/tree/master/src/io/turtle),
+[CSML](https://github.com/CSML-by-Clevy/csml-interpreter),
+[Wasm](https://github.com/Strytyp/wasm-nom),
+[Pseudocode](https://github.com/Gungy2/pseudocode)
+[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch)
+- Interface definition formats: [Thrift](https://github.com/thehydroimpulse/thrust)
+- Audio, video and image formats:
+[GIF](https://github.com/Geal/gif.rs),
+[MagicaVoxel .vox](https://github.com/davidedmonds/dot_vox),
+[midi](https://github.com/derekdreery/nom-midi-rs),
+[SWF](https://github.com/open-flash/swf-parser),
+[WAVE](http://github.com/noise-Labs/wave),
+[Matroska (MKV)](https://github.com/rust-av/matroska)
+- Document formats:
+[TAR](https://github.com/Keruspe/tar-parser.rs),
+[GZ](https://github.com/nharward/nom-gzip),
+[GDSII](https://github.com/erihsu/gds2-io)
+- Cryptographic formats:
+[X.509](https://github.com/rusticata/x509-parser)
+- Network protocol formats:
+[Bencode](https://github.com/jbaum98/bencode.rs),
+[D-Bus](https://github.com/toshokan/misato),
+[DHCP](https://github.com/rusticata/dhcp-parser),
+[HTTP](https://github.com/sozu-proxy/sozu/tree/main/lib/src/protocol/http),
+[URI](https://github.com/santifa/rrp/blob/master/src/uri.rs),
+[IMAP](https://github.com/djc/tokio-imap),
+[IRC](https://github.com/Detegr/RBot-parser),
+[Pcap-NG](https://github.com/richo/pcapng-rs),
+[Pcap](https://github.com/ithinuel/pcap-rs),
+[Pcap + PcapNG](https://github.com/rusticata/pcap-parser),
+[IKEv2](https://github.com/rusticata/ipsec-parser),
+[NTP](https://github.com/rusticata/ntp-parser),
+[SNMP](https://github.com/rusticata/snmp-parser),
+[Kerberos v5](https://github.com/rusticata/kerberos-parser),
+[DER](https://github.com/rusticata/der-parser),
+[TLS](https://github.com/rusticata/tls-parser),
+[IPFIX / Netflow v10](https://github.com/dominotree/rs-ipfix),
+[GTP](https://github.com/fuerstenau/gorrosion-gtp),
+[SIP](https://github.com/armatusmiles/sipcore/tree/master/crates/sipmsg),
+[Prometheus](https://github.com/timberio/vector/blob/master/lib/prometheus-parser/src/line.rs)
+- Language specifications:
+[BNF](https://github.com/snewt/bnf)
+- Misc formats:
+[Gameboy ROM](https://github.com/MarkMcCaskey/gameboy-rom-parser),
+[ANT FIT](https://github.com/stadelmanma/fitparse-rs),
+[Version Numbers](https://github.com/fosskers/rs-versions),
+[Telcordia/Bellcore SR-4731 SOR OTDR files](https://github.com/JamesHarrison/otdrs),
+[MySQL binary log](https://github.com/PrivateRookie/boxercrab),
+[URI](https://github.com/Skasselbard/nom-uri),
+[Furigana](https://github.com/sachaarbonel/furigana.rs),
+[Wordle Result](https://github.com/Fyko/wordle-stats/tree/main/parser)
+
+Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/Geal/nom/issues/14).
+
+Want to add your parser here? Create a pull request for it!
+
+# Contributors
+
+nom is the fruit of the work of many contributors over the years, many thanks for your help!
+
+<a href="https://github.com/geal/nom/graphs/contributors">
+ <img src="https://contributors-img.web.app/image?repo=geal/nom" />
+</a>
diff --git a/vendor/nom8/src/_cookbook.rs b/vendor/nom8/src/_cookbook.rs
new file mode 100644
index 000000000..f0dce23e4
--- /dev/null
+++ b/vendor/nom8/src/_cookbook.rs
@@ -0,0 +1,378 @@
+//! # Nom Recipes
+//!
+//! These are short recipes for accomplishing common tasks with nom.
+//!
+//! * [Whitespace](#whitespace)
+//! + [Wrapper combinators that eat whitespace before and after a parser](#wrapper-combinators-that-eat-whitespace-before-and-after-a-parser)
+//! * [Comments](#comments)
+//! + [`// C++/EOL-style comments`](#-ceol-style-comments)
+//! + [`/* C-style comments */`](#-c-style-comments-)
+//! * [Identifiers](#identifiers)
+//! + [`Rust-Style Identifiers`](#rust-style-identifiers)
+//! * [Literal Values](#literal-values)
+//! + [Escaped Strings](#escaped-strings)
+//! + [Integers](#integers)
+//! - [Hexadecimal](#hexadecimal)
+//! - [Octal](#octal)
+//! - [Binary](#binary)
+//! - [Decimal](#decimal)
+//! + [Floating Point Numbers](#floating-point-numbers)
+//!
+//! ## Whitespace
+//!
+//!
+//!
+//! ### Wrapper combinators that eat whitespace before and after a parser
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! error::ParseError,
+//! sequence::delimited,
+//! character::multispace0,
+//! };
+//!
+//! /// A combinator that takes a parser `inner` and produces a parser that also consumes both leading and
+//! /// trailing whitespace, returning the output of `inner`.
+//! fn ws<'a, F: 'a, O, E: ParseError<&'a str>>(inner: F) -> impl FnMut(&'a str) -> IResult<&'a str, O, E>
+//! where
+//! F: Fn(&'a str) -> IResult<&'a str, O, E>,
+//! {
+//! delimited(
+//! multispace0,
+//! inner,
+//! multispace0
+//! )
+//! }
+//! ```
+//!
+//! To eat only trailing whitespace, replace `delimited(...)` with `terminated(&inner, multispace0)`.
+//! Likewise, the eat only leading whitespace, replace `delimited(...)` with `preceded(multispace0,
+//! &inner)`. You can use your own parser instead of `multispace0` if you want to skip a different set
+//! of lexemes.
+//!
+//! ## Comments
+//!
+//! ### `// C++/EOL-style comments`
+//!
+//! This version uses `%` to start a comment, does not consume the newline character, and returns an
+//! output of `()`.
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::{
+//! IResult,
+//! error::ParseError,
+//! sequence::pair,
+//! bytes::take_till1,
+//! character::char,
+//! };
+//!
+//! pub fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E>
+//! {
+//! pair('%', take_till1("\n\r"))
+//! .value(()) // Output is thrown away.
+//! .parse(i)
+//! }
+//! ```
+//!
+//! ### `/* C-style comments */`
+//!
+//! Inline comments surrounded with sentinel tags `(*` and `*)`. This version returns an output of `()`
+//! and does not handle nested comments.
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::{
+//! IResult,
+//! error::ParseError,
+//! bytes::{tag, take_until},
+//! };
+//!
+//! pub fn pinline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
+//! (
+//! "(*",
+//! take_until("*)"),
+//! "*)"
+//! )
+//! .value(()) // Output is thrown away.
+//! .parse(i)
+//! }
+//! ```
+//!
+//! ## Identifiers
+//!
+//! ### `Rust-Style Identifiers`
+//!
+//! Parsing identifiers that may start with a letter (or underscore) and may contain underscores,
+//! letters and numbers may be parsed like this:
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::many0_count,
+//! sequence::pair,
+//! character::{alpha1, alphanumeric1},
+//! bytes::tag,
+//! };
+//!
+//! pub fn identifier(input: &str) -> IResult<&str, &str> {
+//! pair(
+//! alt((alpha1, "_")),
+//! many0_count(alt((alphanumeric1, "_")))
+//! )
+//! .recognize()
+//! .parse(input)
+//! }
+//! ```
+//!
+//! Let's say we apply this to the identifier `hello_world123abc`. The first `alt` parser would
+//! recognize `h`. The `pair` combinator ensures that `ello_world123abc` will be piped to the next
+//! `alphanumeric0` parser, which recognizes every remaining character. However, the `pair` combinator
+//! returns a tuple of the results of its sub-parsers. The `recognize` parser produces a `&str` of the
+//! input text that was parsed, which in this case is the entire `&str` `hello_world123abc`.
+//!
+//! ## Literal Values
+//!
+//! ### Escaped Strings
+//!
+//! This is [one of the examples](https://github.com/Geal/nom/blob/main/examples/string.rs) in the
+//! examples directory.
+//!
+//! ### Integers
+//!
+//! The following recipes all return string slices rather than integer values. How to obtain an
+//! integer value instead is demonstrated for hexadecimal integers. The others are similar.
+//!
+//! The parsers allow the grouping character `_`, which allows one to group the digits by byte, for
+//! example: `0xA4_3F_11_28`. If you prefer to exclude the `_` character, the lambda to convert from a
+//! string slice to an integer value is slightly simpler. You can also strip the `_` from the string
+//! slice that is returned, which is demonstrated in the second hexdecimal number parser.
+//!
+//! If you wish to limit the number of digits in a valid integer literal, replace `many1` with
+//! `many_m_n` in the recipes.
+//!
+//! #### Hexadecimal
+//!
+//! The parser outputs the string slice of the digits without the leading `0x`/`0X`.
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::{many0, many1},
+//! sequence::{preceded, terminated},
+//! character::char,
+//! bytes::one_of,
+//! bytes::tag,
+//! };
+//!
+//! fn hexadecimal(input: &str) -> IResult<&str, &str> { // <'a, E: ParseError<&'a str>>
+//! preceded(
+//! alt(("0x", "0X")),
+//! many1(
+//! terminated(one_of("0123456789abcdefABCDEF"), many0('_'))
+//! ).recognize()
+//! )(input)
+//! }
+//! ```
+//!
+//! If you want it to return the integer value instead, use map:
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::{many0, many1},
+//! sequence::{preceded, terminated},
+//! character::char,
+//! bytes::one_of,
+//! bytes::tag,
+//! };
+//!
+//! fn hexadecimal_value(input: &str) -> IResult<&str, i64> {
+//! preceded(
+//! alt(("0x", "0X")),
+//! many1(
+//! terminated(one_of("0123456789abcdefABCDEF"), many0('_'))
+//! ).recognize()
+//! ).map_res(
+//! |out: &str| i64::from_str_radix(&str::replace(&out, "_", ""), 16)
+//! ).parse(input)
+//! }
+//! ```
+//!
+//! #### Octal
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::{many0, many1},
+//! sequence::{preceded, terminated},
+//! character::char,
+//! bytes::one_of,
+//! bytes::tag,
+//! };
+//!
+//! fn octal(input: &str) -> IResult<&str, &str> {
+//! preceded(
+//! alt(("0o", "0O")),
+//! many1(
+//! terminated(one_of("01234567"), many0('_'))
+//! ).recognize()
+//! )(input)
+//! }
+//! ```
+//!
+//! #### Binary
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::{many0, many1},
+//! sequence::{preceded, terminated},
+//! character::char,
+//! bytes::one_of,
+//! bytes::tag,
+//! };
+//!
+//! fn binary(input: &str) -> IResult<&str, &str> {
+//! preceded(
+//! alt(("0b", "0B")),
+//! many1(
+//! terminated(one_of("01"), many0('_'))
+//! ).recognize()
+//! )(input)
+//! }
+//! ```
+//!
+//! #### Decimal
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::{
+//! IResult,
+//! multi::{many0, many1},
+//! sequence::terminated,
+//! character::char,
+//! bytes::one_of,
+//! };
+//!
+//! fn decimal(input: &str) -> IResult<&str, &str> {
+//! many1(
+//! terminated(one_of("0123456789"), many0('_'))
+//! )
+//! .recognize()
+//! .parse(input)
+//! }
+//! ```
+//!
+//! ### Floating Point Numbers
+//!
+//! The following is adapted from [the Python parser by Valentin Lorentz (ProgVal)](https://github.com/ProgVal/rust-python-parser/blob/master/src/numbers.rs).
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! branch::alt,
+//! multi::{many0, many1},
+//! combinator::opt,
+//! sequence::{preceded, terminated},
+//! character::char,
+//! bytes::one_of,
+//! };
+//!
+//! fn float(input: &str) -> IResult<&str, &str> {
+//! alt((
+//! // Case one: .42
+//! (
+//! '.',
+//! decimal,
+//! opt((
+//! one_of("eE"),
+//! opt(one_of("+-")),
+//! decimal
+//! ))
+//! ).recognize()
+//! , // Case two: 42e42 and 42.42e42
+//! (
+//! decimal,
+//! opt(preceded(
+//! '.',
+//! decimal,
+//! )),
+//! one_of("eE"),
+//! opt(one_of("+-")),
+//! decimal
+//! ).recognize()
+//! , // Case three: 42. and 42.42
+//! (
+//! decimal,
+//! '.',
+//! opt(decimal)
+//! ).recognize()
+//! ))(input)
+//! }
+//!
+//! fn decimal(input: &str) -> IResult<&str, &str> {
+//! many1(
+//! terminated(one_of("0123456789"), many0('_'))
+//! )
+//! .recognize()
+//! .parse(input)
+//! }
+//! ```
+//!
+//! # implementing FromStr
+//!
+//! The [FromStr trait](https://doc.rust-lang.org/std/str/trait.FromStr.html) provides
+//! a common interface to parse from a string.
+//!
+//! ```rust
+//! use nom8::{
+//! IResult, Finish, error::Error,
+//! bytes::{tag, take_while},
+//! };
+//! use std::str::FromStr;
+//!
+//! // will recognize the name in "Hello, name!"
+//! fn parse_name(input: &str) -> IResult<&str, &str> {
+//! let (i, _) = tag("Hello, ")(input)?;
+//! let (i, name) = take_while(|c:char| c.is_alphabetic())(i)?;
+//! let (i, _) = tag("!")(i)?;
+//!
+//! Ok((i, name))
+//! }
+//!
+//! // with FromStr, the result cannot be a reference to the input, it must be owned
+//! #[derive(Debug)]
+//! pub struct Name(pub String);
+//!
+//! impl FromStr for Name {
+//! // the error must be owned as well
+//! type Err = Error<String>;
+//!
+//! fn from_str(s: &str) -> Result<Self, Self::Err> {
+//! match parse_name(s).finish() {
+//! Ok(name) => Ok(Name(name.to_string())),
+//! Err(Error { input, code }) => Err(Error {
+//! input: input.to_string(),
+//! code,
+//! })
+//! }
+//! }
+//! }
+//!
+//! fn main() {
+//! // parsed: Ok(Name("nom"))
+//! println!("parsed: {:?}", "Hello, nom!".parse::<Name>());
+//!
+//! // parsed: Err(Error { input: "123!", code: Tag })
+//! println!("parsed: {:?}", "Hello, 123!".parse::<Name>());
+//! }
+//! ```
diff --git a/vendor/nom8/src/_tutorial.rs b/vendor/nom8/src/_tutorial.rs
new file mode 100644
index 000000000..53cd724dc
--- /dev/null
+++ b/vendor/nom8/src/_tutorial.rs
@@ -0,0 +1,217 @@
+//! # Making a new parser from scratch
+//!
+//! Writing a parser is a very fun, interactive process, but sometimes a daunting
+//! task. How do you test it? How to see ambiguities in specifications?
+//!
+//! nom is designed to abstract data manipulation (counting array offsets,
+//! converting to structures, etc) while providing a safe, composable API. It also
+//! takes care of making the code easy to test and read, but it can be confusing at
+//! first, if you are not familiar with parser combinators, or if you are not used
+//! to Rust generic functions.
+//!
+//! This document is here to help you in getting started with nom. You can also find
+//! [nom recipes for common short parsing tasks here](crate::_cookbook). If you need
+//! more specific help, please ping `geal` on IRC (libera, geeknode,
+//! oftc), go to `#nom-parsers` on Libera IRC, or on the
+//! [Gitter chat room](https://gitter.im/Geal/nom).
+//!
+//! # First step: the initial research
+//!
+//! A big part of the initial work lies in accumulating enough documentation and
+//! samples to understand the format. The specification is useful, but specifications
+//! represent an "official" point of view, that may not be the real world usage. Any
+//! blog post or open source code is useful, because it shows how people understand
+//! the format, and how they work around each other's bugs (if you think a
+//! specification ensures every implementation is consistent with the others, think again).
+//!
+//! You should get a lot of samples (file or network traces) to test your code. The
+//! easy way is to use a small number of samples coming from the same source and
+//! develop everything around them, to realize later that they share a very specific
+//! bug.
+//!
+//! # Code organization
+//!
+//! While it is tempting to insert the parsing code right inside the rest of the
+//! logic, it usually results in unmaintainable code, and makes testing challenging.
+//! Parser combinators, the parsing technique used in nom, assemble a lot of small
+//! functions to make powerful parsers. This means that those functions only depend
+//! on their input, not on an external state. This makes it easy to parse the input
+//! partially, and to test those functions independently.
+//!
+//! Usually, you can separate the parsing functions in their own module, so you
+//! could have a `src/lib.rs` file containing this:
+//!
+//! ```rust,ignore
+//! pub mod parser;
+//! ```
+//!
+//! And the `src/parser.rs` file:
+//!
+//! ```rust
+//! use nom8::IResult;
+//! use nom8::number::complete::be_u16;
+//! use nom8::bytes::complete::take;
+//!
+//! pub fn length_value(input: &[u8]) -> IResult<&[u8],&[u8]> {
+//! let (input, length) = be_u16(input)?;
+//! take(length)(input)
+//! }
+//! ```
+//!
+//! # Writing a first parser
+//!
+//! Let's parse a simple expression like `(12345)`. nom parsers are functions that
+//! use the `nom8::IResult` type everywhere. As an example, a parser taking a byte
+//! slice `&[u8]` and returning a 32 bits unsigned integer `u32` would have this
+//! signature: `fn parse_u32(input: &[u8]) -> IResult<&[u8], u32>`.
+//!
+//! The `IResult` type depends on the input and output types, and an optional custom
+//! error type. This enum can either be `Ok((i,o))` containing the remaining input
+//! and the output value, or, on the `Err` side, an error or an indication that more
+//! data is needed.
+//!
+//! ```rust
+//! # use nom8::error::ErrorKind;
+//! pub type IResult<I, O, E=(I,ErrorKind)> = Result<(I, O), Err<E>>;
+//!
+//! #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+//! pub enum Needed {
+//! Unknown,
+//! Size(u32)
+//! }
+//!
+//! #[derive(Debug, Clone, PartialEq)]
+//! pub enum Err<E> {
+//! Incomplete(Needed),
+//! Error(E),
+//! Failure(E),
+//! }
+//! ```
+//!
+//! nom uses this type everywhere. Every combination of parsers will pattern match
+//! on this to know if it must return a value, an error, consume more data, etc.
+//! But this is done behind the scenes most of the time.
+//!
+//! Parsers are usually built from the bottom up, by first writing parsers for the
+//! smallest elements, then assembling them in more complex parsers by using
+//! combinators.
+//!
+//! As an example, here is how we could build a (non spec compliant) HTTP request
+//! line parser:
+//!
+//! ```rust
+//! # use nom8::prelude::*;
+//! # use nom8::bytes::complete::take_while1;
+//! # use nom8::bytes::complete::tag;
+//! # use nom8::sequence::preceded;
+//! # use nom8::AsChar;
+//! struct Request<'s> {
+//! method: &'s [u8],
+//! url: &'s [u8],
+//! version: &'s [u8],
+//! }
+//!
+//! // combine all previous parsers in one function
+//! fn request_line(i: &[u8]) -> IResult<&[u8], Request> {
+//! // first implement the basic parsers
+//! let method = take_while1(AsChar::is_alpha);
+//! let space = take_while1(|c| c == b' ');
+//! let url = take_while1(|c| c != b' ');
+//! let is_version = |c| c >= b'0' && c <= b'9' || c == b'.';
+//! let version = take_while1(is_version);
+//! let line_ending = tag("\r\n");
+//!
+//! // combine http and version to extract the version string
+//! // preceded will return the result of the second parser
+//! // if both succeed
+//! let http_version = preceded("HTTP/", version);
+//!
+//! // tuples takes as argument a tuple of parsers and will return
+//! // a tuple of their results
+//! let (input, (method, _, url, _, version, _)) =
+//! (method, &space, url, &space, http_version, line_ending).parse(i)?;
+//!
+//! Ok((input, Request { method, url, version }))
+//! }
+//! ```
+//!
+//! Since it is easy to combine small parsers, I encourage you to write small
+//! functions corresponding to specific parts of the format, test them
+//! independently, then combine them in more general parsers.
+//!
+//! # Finding the right combinator
+//!
+//! nom has a lot of different combinators, depending on the use case. They are all
+//! described in the [reference](https://docs.rs/nom).
+//!
+//! [Basic functions](https://docs.rs/nom/#functions) are available. They deal mostly
+//! in recognizing character types, like `alphanumeric` or `digit`. They also parse
+//! big endian and little endian integers and floats of multiple sizes.
+//!
+//! Most of the functions are there to combine parsers, and they are generic over
+//! the input type.
+//!
+//! # Testing the parsers
+//!
+//! Once you have a parser function, a good trick is to test it on a lot of the
+//! samples you gathered, and integrate this to your unit tests. To that end, put
+//! all of the test files in a folder like `assets` and refer to test files like
+//! this:
+//!
+//! ```rust
+//! #[test]
+//! fn header_test() {
+//! let data = include_bytes!("../assets/axolotl-piano.gif");
+//! println!("bytes:\n{}", &data[0..100].to_hex(8));
+//! let res = header(data);
+//! // ...
+//! }
+//! ```
+//!
+//! The `include_bytes!` macro (provided by Rust's standard library) will integrate
+//! the file as a byte slice in your code. You can then just refer to the part of
+//! the input the parser has to handle via its offset. Here, we take the first 100
+//! bytes of a GIF file to parse its header
+//! (complete code [here](https://github.com/Geal/gif.rs/blob/master/src/parser.rs#L305-L309)).
+//!
+//! If your parser handles textual data, you can just use a lot of strings directly
+//! in the test, like this:
+//!
+//! ```rust
+//! #[test]
+//! fn factor_test() {
+//! assert_eq!(factor("3"), Ok(("", 3)));
+//! assert_eq!(factor(" 12"), Ok(("", 12)));
+//! assert_eq!(factor("537 "), Ok(("", 537)));
+//! assert_eq!(factor(" 24 "), Ok(("", 24)));
+//! }
+//! ```
+//!
+//! The more samples and test cases you get, the more you can experiment with your
+//! parser design.
+//!
+//! # Debugging the parsers
+//!
+//! There are a few tools you can use to debug how code is generated.
+//!
+//! ## dbg_err
+//!
+//! This function wraps a parser that accepts byte-like input (bytes, str) and
+//! prints its hexdump if the child parser encountered an error:
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::bytes::complete::tag;
+//!
+//! fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+//! tag("abcd").dbg_err("tag").parse(i)
+//! }
+//!
+//! let a = &b"efghijkl"[..];
+//!
+//! // Will print the following message:
+//! // tag: Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])):
+//! // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
+//! f(a);
+//! ```
+//!
diff --git a/vendor/nom8/src/bits/complete.rs b/vendor/nom8/src/bits/complete.rs
new file mode 100644
index 000000000..e91e47d41
--- /dev/null
+++ b/vendor/nom8/src/bits/complete.rs
@@ -0,0 +1,177 @@
+//! Bit level parsers
+//!
+
+#![allow(deprecated)]
+
+use crate::error::{ErrorKind, ParseError};
+use crate::input::{InputIter, InputLength, Slice, ToUsize};
+use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
+use crate::{Err, IResult};
+
+/// Generates a parser taking `count` bits
+///
+/// # Example
+/// ```rust
+/// # use nom8::bits::complete::take;
+/// # use nom8::IResult;
+/// # use nom8::error::{Error, ErrorKind};
+/// // Input is a tuple of (input: I, bit_offset: usize)
+/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
+/// take(count)(input)
+/// }
+///
+/// // Consumes 0 bits, returns 0
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
+///
+/// // Consumes 4 bits, returns their values and increase offset to 4
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
+///
+/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
+/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
+///
+/// // Tries to consume 12 bits but only 8 are available
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom8::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bits::take`][crate::bits::take]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bits::take`")]
+pub fn take<I, O, C, E: ParseError<(I, usize)>>(
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| take_internal(input, count)
+}
+
+pub(crate) fn take_internal<I, O, E: ParseError<(I, usize)>>(
+ (input, bit_offset): (I, usize),
+ count: usize,
+) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
+{
+ if count == 0 {
+ Ok(((input, bit_offset), 0u8.into()))
+ } else {
+ let cnt = (count + bit_offset).div(8);
+ if input.input_len() * 8 < count + bit_offset {
+ Err(Err::Error(E::from_error_kind(
+ (input, bit_offset),
+ ErrorKind::Eof,
+ )))
+ } else {
+ let mut acc: O = 0_u8.into();
+ let mut offset: usize = bit_offset;
+ let mut remaining: usize = count;
+ let mut end_offset: usize = 0;
+
+ for byte in input.iter_elements().take(cnt + 1) {
+ if remaining == 0 {
+ break;
+ }
+ let val: O = if offset == 0 {
+ byte.into()
+ } else {
+ ((byte << offset) as u8 >> offset).into()
+ };
+
+ if remaining < 8 - offset {
+ acc += val >> (8 - offset - remaining);
+ end_offset = remaining + offset;
+ break;
+ } else {
+ acc += val << (remaining - (8 - offset));
+ remaining -= 8 - offset;
+ offset = 0;
+ }
+ }
+ Ok(((input.slice(cnt..), end_offset), acc))
+ }
+ }
+}
+
+/// Generates a parser taking `count` bits and comparing them to `pattern`
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bits::tag`][crate::bits::tag]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bits::tag`")]
+pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
+ pattern: O,
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| tag_internal(input, &pattern, count)
+}
+
+pub(crate) fn tag_internal<I, O, E: ParseError<(I, usize)>>(
+ input: (I, usize),
+ pattern: &O,
+ count: usize,
+) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
+{
+ let inp = input.clone();
+
+ take_internal(input, count).and_then(|(i, o)| {
+ if *pattern == o {
+ Ok((i, o))
+ } else {
+ Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
+ }
+ })
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_take_0() {
+ let input = [0b00010010].as_ref();
+ let count = 0usize;
+ assert_eq!(count, 0usize);
+ let offset = 0usize;
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
+
+ assert_eq!(result, Ok(((input, offset), 0)));
+ }
+
+ #[test]
+ fn test_take_eof() {
+ let input = [0b00010010].as_ref();
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
+
+ assert_eq!(
+ result,
+ Err(crate::Err::Error(crate::error::Error {
+ input: (input, 8),
+ code: ErrorKind::Eof
+ }))
+ )
+ }
+
+ #[test]
+ fn test_take_span_over_multiple_bytes() {
+ let input = [0b00010010, 0b00110100, 0b11111111, 0b11111111].as_ref();
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
+
+ assert_eq!(
+ result,
+ Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
+ );
+ }
+}
diff --git a/vendor/nom8/src/bits/mod.rs b/vendor/nom8/src/bits/mod.rs
new file mode 100644
index 000000000..d3ce61480
--- /dev/null
+++ b/vendor/nom8/src/bits/mod.rs
@@ -0,0 +1,179 @@
+//! Bit level parsers
+//!
+
+pub mod complete;
+pub mod streaming;
+#[cfg(test)]
+mod tests;
+
+use crate::error::{ErrorKind, ParseError};
+use crate::input::{ErrorConvert, InputIsStreaming, InputIter, InputLength, Slice, ToUsize};
+use crate::lib::std::ops::{AddAssign, RangeFrom, Shl, Shr};
+use crate::{Err, IResult, Needed, Parser};
+
+/// Converts a byte-level input to a bit-level input, for consumption by a parser that uses bits.
+///
+/// Afterwards, the input is converted back to a byte-level parser, with any remaining bits thrown
+/// away.
+///
+/// # Example
+/// ```
+/// use nom8::bits::{bits, take};
+/// use nom8::error::Error;
+/// use nom8::IResult;
+///
+/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
+/// bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input)
+/// }
+///
+/// let input = &[0x12, 0x34, 0xff, 0xff];
+///
+/// let output = parse(input).expect("We take 1.5 bytes and the input is longer than 2 bytes");
+///
+/// // The first byte is consumed, the second byte is partially consumed and dropped.
+/// let remaining = output.0;
+/// assert_eq!(remaining, [0xff, 0xff]);
+///
+/// let parsed = output.1;
+/// assert_eq!(parsed.0, 0x01);
+/// assert_eq!(parsed.1, 0x23);
+/// ```
+pub fn bits<I, O, E1, E2, P>(mut parser: P) -> impl FnMut(I) -> IResult<I, O, E2>
+where
+ E1: ParseError<(I, usize)> + ErrorConvert<E2>,
+ E2: ParseError<I>,
+ I: Slice<RangeFrom<usize>>,
+ P: Parser<(I, usize), O, E1>,
+{
+ move |input: I| match parser.parse((input, 0)) {
+ Ok(((rest, offset), result)) => {
+ // If the next byte has been partially read, it will be sliced away as well.
+ // The parser functions might already slice away all fully read bytes.
+ // That's why `offset / 8` isn't necessarily needed at all times.
+ let remaining_bytes_index = offset / 8 + if offset % 8 == 0 { 0 } else { 1 };
+ Ok((rest.slice(remaining_bytes_index..), result))
+ }
+ Err(Err::Incomplete(n)) => Err(Err::Incomplete(n.map(|u| u.get() / 8 + 1))),
+ Err(Err::Error(e)) => Err(Err::Error(e.convert())),
+ Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
+ }
+}
+
+/// Counterpart to `bits`, `bytes` transforms its bit stream input into a byte slice for the underlying
+/// parser, allowing byte-slice parsers to work on bit streams.
+///
+/// A partial byte remaining in the input will be ignored and the given parser will start parsing
+/// at the next full byte.
+///
+/// ```
+/// use nom8::bits::{bits, bytes, take};
+/// use nom8::combinator::rest;
+/// use nom8::error::Error;
+/// use nom8::IResult;
+///
+/// fn parse(input: &[u8]) -> IResult<&[u8], (u8, u8, &[u8])> {
+/// bits::<_, _, Error<(&[u8], usize)>, _, _>((
+/// take(4usize),
+/// take(8usize),
+/// bytes::<_, _, Error<&[u8]>, _, _>(rest)
+/// ))(input)
+/// }
+///
+/// let input = &[0x12, 0x34, 0xff, 0xff];
+///
+/// assert_eq!(parse( input ), Ok(( &[][..], (0x01, 0x23, &[0xff, 0xff][..]) )));
+/// ```
+pub fn bytes<I, O, E1, E2, P>(mut parser: P) -> impl FnMut((I, usize)) -> IResult<(I, usize), O, E2>
+where
+ E1: ParseError<I> + ErrorConvert<E2>,
+ E2: ParseError<(I, usize)>,
+ I: Slice<RangeFrom<usize>> + Clone,
+ P: Parser<I, O, E1>,
+{
+ move |(input, offset): (I, usize)| {
+ let inner = if offset % 8 != 0 {
+ input.slice((1 + offset / 8)..)
+ } else {
+ input.slice((offset / 8)..)
+ };
+ let i = (input, offset);
+ match parser.parse(inner) {
+ Ok((rest, res)) => Ok(((rest, 0), res)),
+ Err(Err::Incomplete(Needed::Unknown)) => Err(Err::Incomplete(Needed::Unknown)),
+ Err(Err::Incomplete(Needed::Size(sz))) => Err(match sz.get().checked_mul(8) {
+ Some(v) => Err::Incomplete(Needed::new(v)),
+ None => Err::Failure(E2::from_error_kind(i, ErrorKind::TooLarge)),
+ }),
+ Err(Err::Error(e)) => Err(Err::Error(e.convert())),
+ Err(Err::Failure(e)) => Err(Err::Failure(e.convert())),
+ }
+ }
+}
+
+/// Generates a parser taking `count` bits
+///
+/// # Example
+/// ```rust
+/// # use nom8::bits::take;
+/// # use nom8::IResult;
+/// # use nom8::error::{Error, ErrorKind};
+/// // Input is a tuple of (input: I, bit_offset: usize)
+/// fn parser(input: (&[u8], usize), count: usize)-> IResult<(&[u8], usize), u8> {
+/// take(count)(input)
+/// }
+///
+/// // Consumes 0 bits, returns 0
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 0), Ok((([0b00010010].as_ref(), 0), 0)));
+///
+/// // Consumes 4 bits, returns their values and increase offset to 4
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 4), Ok((([0b00010010].as_ref(), 4), 0b00000001)));
+///
+/// // Consumes 4 bits, offset is 4, returns their values and increase offset to 0 of next byte
+/// assert_eq!(parser(([0b00010010].as_ref(), 4), 4), Ok((([].as_ref(), 0), 0b00000010)));
+///
+/// // Tries to consume 12 bits but only 8 are available
+/// assert_eq!(parser(([0b00010010].as_ref(), 0), 12), Err(nom8::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
+/// ```
+#[inline(always)]
+pub fn take<I, O, C, E: ParseError<(I, usize)>, const STREAMING: bool>(
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| {
+ if STREAMING {
+ streaming::take_internal(input, count)
+ } else {
+ complete::take_internal(input, count)
+ }
+ }
+}
+
+/// Generates a parser taking `count` bits and comparing them to `pattern`
+#[inline(always)]
+pub fn tag<I, O, C, E: ParseError<(I, usize)>, const STREAMING: bool>(
+ pattern: O,
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>>
+ + InputIter<Item = u8>
+ + InputLength
+ + InputIsStreaming<STREAMING>
+ + Clone,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| {
+ if STREAMING {
+ streaming::tag_internal(input, &pattern, count)
+ } else {
+ complete::tag_internal(input, &pattern, count)
+ }
+ }
+}
diff --git a/vendor/nom8/src/bits/streaming.rs b/vendor/nom8/src/bits/streaming.rs
new file mode 100644
index 000000000..4c15be1ce
--- /dev/null
+++ b/vendor/nom8/src/bits/streaming.rs
@@ -0,0 +1,162 @@
+//! Bit level parsers
+//!
+
+#![allow(deprecated)]
+
+use crate::error::{ErrorKind, ParseError};
+use crate::input::{InputIter, InputLength, Slice, ToUsize};
+use crate::lib::std::ops::{AddAssign, Div, RangeFrom, Shl, Shr};
+use crate::{Err, IResult, Needed};
+
+/// Generates a parser taking `count` bits
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bits::take`][crate::bits::take] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bits::take` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take<I, O, C, E: ParseError<(I, usize)>>(
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| take_internal(input, count)
+}
+
+pub(crate) fn take_internal<I, O, E: ParseError<(I, usize)>>(
+ (input, bit_offset): (I, usize),
+ count: usize,
+) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
+{
+ if count == 0 {
+ Ok(((input, bit_offset), 0u8.into()))
+ } else {
+ let cnt = (count + bit_offset).div(8);
+ if input.input_len() * 8 < count + bit_offset {
+ Err(Err::Incomplete(Needed::new(count as usize)))
+ } else {
+ let mut acc: O = 0_u8.into();
+ let mut offset: usize = bit_offset;
+ let mut remaining: usize = count;
+ let mut end_offset: usize = 0;
+
+ for byte in input.iter_elements().take(cnt + 1) {
+ if remaining == 0 {
+ break;
+ }
+ let val: O = if offset == 0 {
+ byte.into()
+ } else {
+ ((byte << offset) as u8 >> offset).into()
+ };
+
+ if remaining < 8 - offset {
+ acc += val >> (8 - offset - remaining);
+ end_offset = remaining + offset;
+ break;
+ } else {
+ acc += val << (remaining - (8 - offset));
+ remaining -= 8 - offset;
+ offset = 0;
+ }
+ }
+ Ok(((input.slice(cnt..), end_offset), acc))
+ }
+ }
+}
+
+/// Generates a parser taking `count` bits and comparing them to `pattern`
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bits::tag`][crate::bits::tag] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bits::tag` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn tag<I, O, C, E: ParseError<(I, usize)>>(
+ pattern: O,
+ count: C,
+) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
+ C: ToUsize,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
+{
+ let count = count.to_usize();
+ move |input: (I, usize)| tag_internal(input, &pattern, count)
+}
+
+pub(crate) fn tag_internal<I, O, E: ParseError<(I, usize)>>(
+ input: (I, usize),
+ pattern: &O,
+ count: usize,
+) -> IResult<(I, usize), O, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + Clone,
+ O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O> + PartialEq,
+{
+ let inp = input.clone();
+
+ take(count)(input).and_then(|(i, o)| {
+ if *pattern == o {
+ Ok((i, o))
+ } else {
+ Err(Err::Error(error_position!(inp, ErrorKind::TagBits)))
+ }
+ })
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_take_0() {
+ let input = [].as_ref();
+ let count = 0usize;
+ assert_eq!(count, 0usize);
+ let offset = 0usize;
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
+
+ assert_eq!(result, Ok(((input, offset), 0)));
+ }
+
+ #[test]
+ fn test_tag_ok() {
+ let input = [0b00011111].as_ref();
+ let offset = 0usize;
+ let bits_to_take = 4usize;
+ let value_to_tag = 0b0001;
+
+ let result: crate::IResult<(&[u8], usize), usize> =
+ tag(value_to_tag, bits_to_take)((input, offset));
+
+ assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
+ }
+
+ #[test]
+ fn test_tag_err() {
+ let input = [0b00011111].as_ref();
+ let offset = 0usize;
+ let bits_to_take = 4usize;
+ let value_to_tag = 0b1111;
+
+ let result: crate::IResult<(&[u8], usize), usize> =
+ tag(value_to_tag, bits_to_take)((input, offset));
+
+ assert_eq!(
+ result,
+ Err(crate::Err::Error(crate::error::Error {
+ input: (input, offset),
+ code: ErrorKind::TagBits
+ }))
+ );
+ }
+}
diff --git a/vendor/nom8/src/bits/tests.rs b/vendor/nom8/src/bits/tests.rs
new file mode 100644
index 000000000..a760fefa2
--- /dev/null
+++ b/vendor/nom8/src/bits/tests.rs
@@ -0,0 +1,142 @@
+use super::*;
+use crate::error::Error;
+use crate::input::Streaming;
+
+#[test]
+/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
+/// previous bytes are fully consumed
+fn test_complete_byte_consumption_bits() {
+ let input = &[0x12, 0x34, 0x56, 0x78][..];
+
+ // Take 3 bit slices with sizes [4, 8, 4].
+ let result: IResult<&[u8], (u8, u8, u8)> =
+ bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize), take(4usize)))(input);
+
+ let output = result.expect("We take 2 bytes and the input is longer than 2 bytes");
+
+ let remaining = output.0;
+ assert_eq!(remaining, [0x56, 0x78]);
+
+ let parsed = output.1;
+ assert_eq!(parsed.0, 0x01);
+ assert_eq!(parsed.1, 0x23);
+ assert_eq!(parsed.2, 0x04);
+}
+
+#[test]
+/// Take the `bits` function and assert that remaining bytes are correctly returned, if the
+/// previous bytes are NOT fully consumed. Partially consumed bytes are supposed to be dropped.
+/// I.e. if we consume 1.5 bytes of 4 bytes, 2 bytes will be returned, bits 13-16 will be
+/// dropped.
+fn test_partial_byte_consumption_bits() {
+ let input = &[0x12, 0x34, 0x56, 0x78][..];
+
+ // Take bit slices with sizes [4, 8].
+ let result: IResult<&[u8], (u8, u8)> =
+ bits::<_, _, Error<(&[u8], usize)>, _, _>((take(4usize), take(8usize)))(input);
+
+ let output = result.expect("We take 1.5 bytes and the input is longer than 2 bytes");
+
+ let remaining = output.0;
+ assert_eq!(remaining, [0x56, 0x78]);
+
+ let parsed = output.1;
+ assert_eq!(parsed.0, 0x01);
+ assert_eq!(parsed.1, 0x23);
+}
+
+#[test]
+#[cfg(feature = "std")]
+/// Ensure that in Incomplete error is thrown, if too few bytes are passed for a given parser.
+fn test_incomplete_bits() {
+ let input = Streaming(&[0x12][..]);
+
+ // Take bit slices with sizes [4, 8].
+ let result: IResult<_, (u8, u8)> =
+ bits::<_, _, Error<(_, usize)>, _, _>((take(4usize), take(8usize)))(input);
+
+ assert!(result.is_err());
+ let error = result.err().unwrap();
+ assert_eq!("Parsing requires 2 bytes/chars", error.to_string());
+}
+
+#[test]
+fn test_take_complete_0() {
+ let input = &[0b00010010][..];
+ let count = 0usize;
+ assert_eq!(count, 0usize);
+ let offset = 0usize;
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(count)((input, offset));
+
+ assert_eq!(result, Ok(((input, offset), 0)));
+}
+
+#[test]
+fn test_take_complete_eof() {
+ let input = &[0b00010010][..];
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(1usize)((input, 8));
+
+ assert_eq!(
+ result,
+ Err(crate::Err::Error(crate::error::Error {
+ input: (input, 8),
+ code: ErrorKind::Eof
+ }))
+ )
+}
+
+#[test]
+fn test_take_complete_span_over_multiple_bytes() {
+ let input = &[0b00010010, 0b00110100, 0b11111111, 0b11111111][..];
+
+ let result: crate::IResult<(&[u8], usize), usize> = take(24usize)((input, 4));
+
+ assert_eq!(
+ result,
+ Ok((([0b11111111].as_ref(), 4), 0b1000110100111111111111))
+ );
+}
+
+#[test]
+fn test_take_streaming_0() {
+ let input = Streaming(&[][..]);
+ let count = 0usize;
+ assert_eq!(count, 0usize);
+ let offset = 0usize;
+
+ let result: crate::IResult<(_, usize), usize> = take(count)((input, offset));
+
+ assert_eq!(result, Ok(((input, offset), 0)));
+}
+
+#[test]
+fn test_tag_streaming_ok() {
+ let input = Streaming(&[0b00011111][..]);
+ let offset = 0usize;
+ let bits_to_take = 4usize;
+ let value_to_tag = 0b0001;
+
+ let result: crate::IResult<(_, usize), usize> = tag(value_to_tag, bits_to_take)((input, offset));
+
+ assert_eq!(result, Ok(((input, bits_to_take), value_to_tag)));
+}
+
+#[test]
+fn test_tag_streaming_err() {
+ let input = Streaming(&[0b00011111][..]);
+ let offset = 0usize;
+ let bits_to_take = 4usize;
+ let value_to_tag = 0b1111;
+
+ let result: crate::IResult<(_, usize), usize> = tag(value_to_tag, bits_to_take)((input, offset));
+
+ assert_eq!(
+ result,
+ Err(crate::Err::Error(crate::error::Error {
+ input: (input, offset),
+ code: ErrorKind::TagBits
+ }))
+ );
+}
diff --git a/vendor/nom8/src/branch/mod.rs b/vendor/nom8/src/branch/mod.rs
new file mode 100644
index 000000000..9598b0151
--- /dev/null
+++ b/vendor/nom8/src/branch/mod.rs
@@ -0,0 +1,267 @@
+//! Choice combinators
+
+#[cfg(test)]
+mod tests;
+
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::{Err, IResult, Parser};
+
+/// Helper trait for the [alt()] combinator.
+///
+/// This trait is implemented for tuples of up to 21 elements
+pub trait Alt<I, O, E> {
+ /// Tests each parser in the tuple and returns the result of the first one that succeeds
+ fn choice(&mut self, input: I) -> IResult<I, O, E>;
+}
+
+/// Tests a list of parsers one by one until one succeeds.
+///
+/// It takes as argument a tuple of parsers. There is a maximum of 21
+/// parsers. If you need more, it is possible to nest them in other `alt` calls,
+/// like this: `alt(parser_a, alt(parser_b, parser_c))`
+///
+/// ```rust
+/// # use nom8::error_position;
+/// # use nom8::{Err,error::ErrorKind, Needed, IResult};
+/// use nom8::character::{alpha1, digit1};
+/// use nom8::branch::alt;
+/// # fn main() {
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alt((alpha1, digit1))(input)
+/// };
+///
+/// // the first parser, alpha1, recognizes the input
+/// assert_eq!(parser("abc"), Ok(("", "abc")));
+///
+/// // the first parser returns an error, so alt tries the second one
+/// assert_eq!(parser("123456"), Ok(("", "123456")));
+///
+/// // both parsers failed, and with the default error type, alt will return the last error
+/// assert_eq!(parser(" "), Err(Err::Error(error_position!(" ", ErrorKind::Digit))));
+/// # }
+/// ```
+///
+/// With a custom error type, it is possible to have alt return the error of the parser
+/// that went the farthest in the input data
+pub fn alt<I: Clone, O, E: ParseError<I>, List: Alt<I, O, E>>(
+ mut l: List,
+) -> impl FnMut(I) -> IResult<I, O, E> {
+ move |i: I| l.choice(i)
+}
+
+/// Helper trait for the [permutation()] combinator.
+///
+/// This trait is implemented for tuples of up to 21 elements
+pub trait Permutation<I, O, E> {
+ /// Tries to apply all parsers in the tuple in various orders until all of them succeed
+ fn permutation(&mut self, input: I) -> IResult<I, O, E>;
+}
+
+/// Applies a list of parsers in any order.
+///
+/// Permutation will succeed if all of the child parsers succeeded.
+/// It takes as argument a tuple of parsers, and returns a
+/// tuple of the parser results.
+///
+/// ```rust
+/// # use nom8::{Err,error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::character::{alpha1, digit1};
+/// use nom8::branch::permutation;
+/// # fn main() {
+/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
+/// permutation((alpha1, digit1))(input)
+/// }
+///
+/// // permutation recognizes alphabetic characters then digit
+/// assert_eq!(parser("abc123"), Ok(("", ("abc", "123"))));
+///
+/// // but also in inverse order
+/// assert_eq!(parser("123abc"), Ok(("", ("abc", "123"))));
+///
+/// // it will fail if one of the parsers failed
+/// assert_eq!(parser("abc;"), Err(Err::Error(Error::new(";", ErrorKind::Digit))));
+/// # }
+/// ```
+///
+/// The parsers are applied greedily: if there are multiple unapplied parsers
+/// that could parse the next slice of input, the first one is used.
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult};
+/// use nom8::branch::permutation;
+/// use nom8::bytes::any;
+///
+/// fn parser(input: &str) -> IResult<&str, (char, char)> {
+/// permutation((any, 'a'))(input)
+/// }
+///
+/// // any parses 'b', then char('a') parses 'a'
+/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
+///
+/// // any parses 'a', then char('a') fails on 'b',
+/// // even though char('a') followed by any would succeed
+/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::OneOf))));
+/// ```
+///
+pub fn permutation<I: Clone, O, E: ParseError<I>, List: Permutation<I, O, E>>(
+ mut l: List,
+) -> impl FnMut(I) -> IResult<I, O, E> {
+ move |i: I| l.permutation(i)
+}
+
+macro_rules! alt_trait(
+ ($first:ident $second:ident $($id: ident)+) => (
+ alt_trait!(__impl $first $second; $($id)+);
+ );
+ (__impl $($current:ident)*; $head:ident $($id: ident)+) => (
+ alt_trait_impl!($($current)*);
+
+ alt_trait!(__impl $($current)* $head; $($id)+);
+ );
+ (__impl $($current:ident)*; $head:ident) => (
+ alt_trait_impl!($($current)*);
+ alt_trait_impl!($($current)* $head);
+ );
+);
+
+macro_rules! alt_trait_impl(
+ ($($id:ident)+) => (
+ impl<
+ Input: Clone, Output, Error: ParseError<Input>,
+ $($id: Parser<Input, Output, Error>),+
+ > Alt<Input, Output, Error> for ( $($id),+ ) {
+
+ fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
+ match self.0.parse(input.clone()) {
+ Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
+ res => res,
+ }
+ }
+ }
+ );
+);
+
+macro_rules! alt_trait_inner(
+ ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
+ match $self.$it.parse($input.clone()) {
+ Err(Err::Error(e)) => {
+ let err = $err.or(e);
+ succ!($it, alt_trait_inner!($self, $input, err, $($id)+))
+ }
+ res => res,
+ }
+ );
+ ($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
+ Err(Err::Error(Error::append($input, ErrorKind::Alt, $err)))
+ );
+);
+
+alt_trait!(A B C D E F G H I J K L M N O P Q R S T U);
+
+// Manually implement Alt for (A,), the 1-tuple type
+impl<Input, Output, Error: ParseError<Input>, A: Parser<Input, Output, Error>>
+ Alt<Input, Output, Error> for (A,)
+{
+ fn choice(&mut self, input: Input) -> IResult<Input, Output, Error> {
+ self.0.parse(input)
+ }
+}
+
+macro_rules! permutation_trait(
+ (
+ $name1:ident $ty1:ident $item1:ident
+ $name2:ident $ty2:ident $item2:ident
+ $($name3:ident $ty3:ident $item3:ident)*
+ ) => (
+ permutation_trait!(__impl $name1 $ty1 $item1, $name2 $ty2 $item2; $($name3 $ty3 $item3)*);
+ );
+ (
+ __impl $($name:ident $ty:ident $item:ident),+;
+ $name1:ident $ty1:ident $item1:ident $($name2:ident $ty2:ident $item2:ident)*
+ ) => (
+ permutation_trait_impl!($($name $ty $item),+);
+ permutation_trait!(__impl $($name $ty $item),+ , $name1 $ty1 $item1; $($name2 $ty2 $item2)*);
+ );
+ (__impl $($name:ident $ty:ident $item:ident),+;) => (
+ permutation_trait_impl!($($name $ty $item),+);
+ );
+);
+
+macro_rules! permutation_trait_impl(
+ ($($name:ident $ty:ident $item:ident),+) => (
+ impl<
+ Input: Clone, $($ty),+ , Error: ParseError<Input>,
+ $($name: Parser<Input, $ty, Error>),+
+ > Permutation<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
+
+ fn permutation(&mut self, mut input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
+ let mut res = ($(Option::<$ty>::None),+);
+
+ loop {
+ let mut err: Option<Error> = None;
+ permutation_trait_inner!(0, self, input, res, err, $($name)+);
+
+ // If we reach here, every iterator has either been applied before,
+ // or errored on the remaining input
+ if let Some(err) = err {
+ // There are remaining parsers, and all errored on the remaining input
+ return Err(Err::Error(Error::append(input, ErrorKind::Permutation, err)));
+ }
+
+ // All parsers were applied
+ match res {
+ ($(Some($item)),+) => return Ok((input, ($($item),+))),
+ _ => unreachable!(),
+ }
+ }
+ }
+ }
+ );
+);
+
+macro_rules! permutation_trait_inner(
+ ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($id:ident)*) => (
+ if $res.$it.is_none() {
+ match $self.$it.parse($input.clone()) {
+ Ok((i, o)) => {
+ $input = i;
+ $res.$it = Some(o);
+ continue;
+ }
+ Err(Err::Error(e)) => {
+ $err = Some(match $err {
+ Some(err) => err.or(e),
+ None => e,
+ });
+ }
+ Err(e) => return Err(e),
+ };
+ }
+ succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($id)*));
+ );
+ ($it:tt, $self:expr, $input:ident, $res:expr, $err:expr,) => ();
+);
+
+permutation_trait!(
+ FnA A a
+ FnB B b
+ FnC C c
+ FnD D d
+ FnE E e
+ FnF F f
+ FnG G g
+ FnH H h
+ FnI I i
+ FnJ J j
+ FnK K k
+ FnL L l
+ FnM M m
+ FnN N n
+ FnO O o
+ FnP P p
+ FnQ Q q
+ FnR R r
+ FnS S s
+ FnT T t
+ FnU U u
+);
diff --git a/vendor/nom8/src/branch/tests.rs b/vendor/nom8/src/branch/tests.rs
new file mode 100644
index 000000000..492f705ab
--- /dev/null
+++ b/vendor/nom8/src/branch/tests.rs
@@ -0,0 +1,146 @@
+use crate::branch::{alt, permutation};
+use crate::bytes::tag;
+use crate::error::ErrorKind;
+use crate::input::Streaming;
+#[cfg(feature = "alloc")]
+use crate::{
+ error::ParseError,
+ lib::std::{
+ fmt::Debug,
+ string::{String, ToString},
+ },
+};
+use crate::{Err, IResult, Needed};
+
+#[cfg(feature = "alloc")]
+#[derive(Debug, Clone, PartialEq)]
+pub struct ErrorStr(String);
+
+#[cfg(feature = "alloc")]
+impl From<u32> for ErrorStr {
+ fn from(i: u32) -> Self {
+ ErrorStr(format!("custom error code: {}", i))
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<'a> From<&'a str> for ErrorStr {
+ fn from(i: &'a str) -> Self {
+ ErrorStr(format!("custom error message: {}", i))
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I: Debug> ParseError<I> for ErrorStr {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ ErrorStr(format!("custom error message: ({:?}, {:?})", input, kind))
+ }
+
+ fn append(input: I, kind: ErrorKind, other: Self) -> Self {
+ ErrorStr(format!(
+ "custom error message: ({:?}, {:?}) - {:?}",
+ input, kind, other
+ ))
+ }
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn alt_test() {
+ fn work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((&b""[..], input))
+ }
+
+ #[allow(unused_variables)]
+ fn dont_work(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Err(Err::Error(ErrorStr("abcd".to_string())))
+ }
+
+ fn work2(input: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ Ok((input, &b""[..]))
+ }
+
+ fn alt1(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, dont_work))(i)
+ }
+ fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, work))(i)
+ }
+ fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
+ alt((dont_work, dont_work, work2, dont_work))(i)
+ }
+ //named!(alt1, alt!(dont_work | dont_work));
+ //named!(alt2, alt!(dont_work | work));
+ //named!(alt3, alt!(dont_work | dont_work | work2 | dont_work));
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ alt1(a),
+ Err(Err::Error(error_node_position!(
+ a,
+ ErrorKind::Alt,
+ ErrorStr("abcd".to_string())
+ )))
+ );
+ assert_eq!(alt2(a), Ok((&b""[..], a)));
+ assert_eq!(alt3(a), Ok((a, &b""[..])));
+
+ fn alt4(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ alt((tag("abcd"), tag("efgh")))(i)
+ }
+ let b = &b"efgh"[..];
+ assert_eq!(alt4(a), Ok((&b""[..], a)));
+ assert_eq!(alt4(b), Ok((&b""[..], b)));
+}
+
+#[test]
+fn alt_incomplete() {
+ fn alt1(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ alt((tag("a"), tag("bc"), tag("def")))(i)
+ }
+
+ let a = &b""[..];
+ assert_eq!(alt1(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"b"[..];
+ assert_eq!(alt1(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"bcd"[..];
+ assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"d"[..]), &b"bc"[..])));
+ let a = &b"cde"[..];
+ assert_eq!(
+ alt1(Streaming(a)),
+ Err(Err::Error(error_position!(Streaming(a), ErrorKind::Tag)))
+ );
+ let a = &b"de"[..];
+ assert_eq!(alt1(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ let a = &b"defg"[..];
+ assert_eq!(alt1(Streaming(a)), Ok((Streaming(&b"g"[..]), &b"def"[..])));
+}
+
+#[test]
+fn permutation_test() {
+ fn perm(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8], &[u8])> {
+ permutation((tag("abcd"), tag("efg"), tag("hi")))(i)
+ }
+
+ let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
+
+ let a = &b"abcdefghijk"[..];
+ assert_eq!(perm(Streaming(a)), Ok((Streaming(&b"jk"[..]), expected)));
+ let b = &b"efgabcdhijk"[..];
+ assert_eq!(perm(Streaming(b)), Ok((Streaming(&b"jk"[..]), expected)));
+ let c = &b"hiefgabcdjk"[..];
+ assert_eq!(perm(Streaming(c)), Ok((Streaming(&b"jk"[..]), expected)));
+
+ let d = &b"efgxyzabcdefghi"[..];
+ assert_eq!(
+ perm(Streaming(d)),
+ Err(Err::Error(error_node_position!(
+ Streaming(&b"efgxyzabcdefghi"[..]),
+ ErrorKind::Permutation,
+ error_position!(Streaming(&b"xyzabcdefghi"[..]), ErrorKind::Tag)
+ )))
+ );
+
+ let e = &b"efgabc"[..];
+ assert_eq!(perm(Streaming(e)), Err(Err::Incomplete(Needed::new(1))));
+}
diff --git a/vendor/nom8/src/bytes/complete.rs b/vendor/nom8/src/bytes/complete.rs
new file mode 100644
index 000000000..ee4860c0b
--- /dev/null
+++ b/vendor/nom8/src/bytes/complete.rs
@@ -0,0 +1,1258 @@
+//! Parsers recognizing bytes streams, complete input version
+
+#![allow(deprecated)]
+
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::{
+ Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake,
+ InputTakeAtPosition, IntoOutput, Slice, ToUsize,
+};
+use crate::lib::std::ops::RangeFrom;
+use crate::lib::std::result::Result::*;
+use crate::IntoOutputIResult;
+use crate::{Err, IResult, Parser};
+
+pub(crate) fn any<I, E: ParseError<I>>(input: I) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: InputIter + InputLength + Slice<RangeFrom<usize>>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))),
+ Some((_, c)) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ }
+}
+
+/// Recognizes a pattern
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument
+///
+/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag("Hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag`][crate::bytes::tag]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::tag`")]
+pub fn tag<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| tag_internal(i, tag.clone())
+}
+
+pub(crate) fn tag_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let tag_len = t.input_len();
+ let res: IResult<_, _, Error> = match i.compare(t) {
+ CompareResult::Ok => Ok(i.take_split(tag_len)),
+ _ => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(Error::from_error_kind(i, e)))
+ }
+ };
+ res.into_output()
+}
+
+/// Recognizes a case insensitive pattern.
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument with no regard to case.
+///
+/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::tag_no_case;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag_no_case("hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag_no_case`][crate::bytes::tag_no_case]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::tag_no_case`")]
+pub fn tag_no_case<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| tag_no_case_internal(i, tag.clone())
+}
+
+pub(crate) fn tag_no_case_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let tag_len = t.input_len();
+
+ let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
+ CompareResult::Ok => Ok(i.take_split(tag_len)),
+ _ => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(Error::from_error_kind(i, e)))
+ }
+ };
+ res.into_output()
+}
+
+pub(crate) fn one_of_internal<I, T, E: ParseError<I>>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ Some((_, c)) if list.find_token(c) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::OneOf))),
+ None => Err(Err::Error(E::from_error_kind(input, ErrorKind::OneOf))),
+ }
+}
+
+pub(crate) fn none_of_internal<I, T, E: ParseError<I>>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ Some((_, c)) if !list.find_token(c) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::NoneOf))),
+ None => Err(Err::Error(E::from_error_kind(input, ErrorKind::NoneOf))),
+ }
+}
+
+/// Parse till certain characters are met.
+///
+/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
+///
+/// It doesn't consume the matched character.
+///
+/// It will return a `Err::Error(("", ErrorKind::IsNot))` if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::is_not;
+///
+/// fn not_space(s: &str) -> IResult<&str, &str> {
+/// is_not(" \t\r\n")(s)
+/// }
+///
+/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
+/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
+/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
+/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::IsNot))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till1`")]
+pub fn is_not<T, Input, Error: ParseError<Input>>(
+ arr: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| is_not_internal(i, &arr)
+}
+
+pub(crate) fn is_not_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ arr: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::IsNot;
+ i.split_at_position1_complete(|c| arr.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest slice of the matches the pattern.
+///
+/// The parser will return the longest slice consisting of the characters in provided in the
+/// combinator's argument.
+///
+/// It will return a `Err(Err::Error((_, ErrorKind::IsA)))` if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::is_a;
+///
+/// fn hex(s: &str) -> IResult<&str, &str> {
+/// is_a("1234567890ABCDEF")(s)
+/// }
+///
+/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
+/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
+/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
+/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
+/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::IsA))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1`]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while1`")]
+pub fn is_a<T, Input, Error: ParseError<Input>>(
+ arr: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| is_a_internal(i, &arr)
+}
+
+pub(crate) fn is_a_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ arr: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::IsA;
+ i.split_at_position1_complete(|c| !arr.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest input slice (if any) that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::complete::take_while;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while`][crate::bytes::take_while]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while`")]
+pub fn take_while<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_while_internal(i, &list)
+}
+
+pub(crate) fn take_while_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ i.split_at_position_complete(|c| !list.find_token(c))
+ .into_output()
+}
+
+/// Returns the longest (at least 1) input slice that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take_while1;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while1(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while1`")]
+pub fn take_while1<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_while1_internal(i, &list)
+}
+
+pub(crate) fn take_while1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::TakeWhile1;
+ i.split_at_position1_complete(|c| !list.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest (m <= len <= n) input slice that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out
+/// of range (m <= len <= n).
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take_while_m_n;
+/// use nom8::input::AsChar;
+///
+/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while_m_n(3, 6, AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
+/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN))));
+/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while_m_n`][crate::bytes::take_while_m_n]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_while_m_n`")]
+pub fn take_while_m_n<T, Input, Error: ParseError<Input>>(
+ m: usize,
+ n: usize,
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputIter>::Item>,
+{
+ move |i: Input| take_while_m_n_internal(i, m, n, &list)
+}
+
+pub(crate) fn take_while_m_n_internal<T, Input, Error: ParseError<Input>>(
+ input: Input,
+ m: usize,
+ n: usize,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputIter>::Item>,
+{
+ match input.position(|c| !list.find_token(c)) {
+ Some(idx) => {
+ if idx >= m {
+ if idx <= n {
+ let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) {
+ Ok(input.take_split(index)).into_output()
+ } else {
+ Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ )))
+ };
+ res
+ } else {
+ let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) {
+ Ok(input.take_split(index)).into_output()
+ } else {
+ Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ )))
+ };
+ res
+ }
+ } else {
+ let e = ErrorKind::TakeWhileMN;
+ Err(Err::Error(Error::from_error_kind(input, e)))
+ }
+ }
+ None => {
+ let len = input.input_len();
+ if len >= n {
+ match input.slice_index(n) {
+ Ok(index) => Ok(input.take_split(index)).into_output(),
+ Err(_needed) => Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ ))),
+ }
+ } else if len >= m && len <= n {
+ let res: IResult<_, _, Error> = Ok((input.slice(len..), input));
+ res.into_output()
+ } else {
+ let e = ErrorKind::TakeWhileMN;
+ Err(Err::Error(Error::from_error_kind(input, e)))
+ }
+ }
+ }
+}
+
+/// Returns the longest input slice (if any) till a predicate is met.
+///
+/// The parser will return the longest slice till the given predicate *(a function that
+/// takes the input and returns a bool)*.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::complete::take_till;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till`][crate::bytes::take_till]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till`")]
+pub fn take_till<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_till_internal(i, &list)
+}
+
+pub(crate) fn take_till_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ i.split_at_position_complete(|c| list.find_token(c))
+ .into_output()
+}
+
+/// Returns the longest (at least 1) input slice till a predicate is met.
+///
+/// The parser will return the longest slice till the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the
+/// predicate matches the first input.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take_till1;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till1(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_till1`")]
+pub fn take_till1<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_till1_internal(i, &list)
+}
+
+pub(crate) fn take_till1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::TakeTill1;
+ i.split_at_position1_complete(|c| list.find_token(c), e)
+ .into_output()
+}
+
+/// Returns an input slice containing the first N input elements (Input[..N]).
+///
+/// It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take;
+///
+/// fn take6(s: &str) -> IResult<&str, &str> {
+/// take(6usize)(s)
+/// }
+///
+/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
+/// assert_eq!(take6("things"), Ok(("", "things")));
+/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
+/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
+/// ```
+///
+/// The units that are taken will depend on the input type. For example, for a
+/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
+/// take that many `u8`'s:
+///
+/// ```rust
+/// use nom8::error::Error;
+/// use nom8::bytes::complete::take;
+///
+/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙"), Ok(("", "💙")));
+/// assert_eq!(take::<_, _, Error<_>>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take`][crate::bytes::take]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take`")]
+pub fn take<C, Input, Error: ParseError<Input>>(
+ count: C,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputIter + InputTake,
+ Input: IntoOutput,
+ C: ToUsize,
+{
+ let c = count.to_usize();
+ move |i: Input| take_internal(i, c)
+}
+
+pub(crate) fn take_internal<Input, Error: ParseError<Input>>(
+ i: Input,
+ c: usize,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputIter + InputTake,
+ Input: IntoOutput,
+{
+ match i.slice_index(c) {
+ Err(_needed) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Eof))),
+ Ok(index) => Ok(i.take_split(index)).into_output(),
+ }
+}
+
+/// Returns the input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
+/// if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take_until;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until`][crate::bytes::take_until]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_until`")]
+pub fn take_until<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + FindSubstring<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| take_until_internal(i, tag.clone())
+}
+
+pub(crate) fn take_until_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + FindSubstring<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let res: IResult<_, _, Error> = match i.find_substring(t) {
+ None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
+ Some(index) => Ok(i.take_split(index)),
+ };
+ res.into_output()
+}
+
+/// Returns the non empty input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern. It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
+/// if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::complete::take_until1;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until1("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until1`][crate::bytes::take_until1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::take_until1`")]
+pub fn take_until1<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + FindSubstring<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| take_until1_internal(i, tag.clone())
+}
+
+pub(crate) fn take_until1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + FindSubstring<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let res: IResult<_, _, Error> = match i.find_substring(t) {
+ None => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
+ Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
+ Some(index) => Ok(i.take_split(index)),
+ };
+ res.into_output()
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not accept the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters
+/// # Example
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::character::complete::digit1;
+/// use nom8::bytes::complete::escaped;
+/// use nom8::character::complete::one_of;
+///
+/// fn esc(s: &str) -> IResult<&str, &str> {
+/// escaped(digit1, '\\', one_of(r#""n\"#))(s)
+/// }
+///
+/// assert_eq!(esc("123;"), Ok((";", "123")));
+/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#)));
+/// ```
+///
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped`][crate::bytes::escaped]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::escaped`")]
+pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2>(
+ mut normal: F,
+ control_char: char,
+ mut escapable: G,
+) -> impl FnMut(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: IntoOutput,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| escaped_internal(input, &mut normal, control_char, &mut escapable)
+}
+
+pub(crate) fn escaped_internal<'a, Input: 'a, Error, F, G, O1, O2>(
+ input: Input,
+ normal: &mut F,
+ control_char: char,
+ escapable: &mut G,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: IntoOutput,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ use crate::input::AsChar;
+
+ let mut i = input.clone();
+
+ while i.input_len() > 0 {
+ let current_len = i.input_len();
+
+ match normal.parse(i.clone()) {
+ Ok((i2, _)) => {
+ // return if we consumed everything or if the normal parser
+ // does not consume anything
+ if i2.input_len() == 0 {
+ return Ok((input.slice(input.input_len()..), input)).into_output();
+ } else if i2.input_len() == current_len {
+ let index = input.offset(&i2);
+ return Ok(input.take_split(index)).into_output();
+ } else {
+ i = i2;
+ }
+ }
+ Err(Err::Error(_)) => {
+ // unwrap() should be safe here since index < $i.input_len()
+ if i.iter_elements().next().unwrap().as_char() == control_char {
+ let next = control_char.len_utf8();
+ if next >= i.input_len() {
+ return Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::Escaped,
+ )));
+ } else {
+ match escapable.parse(i.slice(next..)) {
+ Ok((i2, _)) => {
+ if i2.input_len() == 0 {
+ return Ok((input.slice(input.input_len()..), input)).into_output();
+ } else {
+ i = i2;
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ } else {
+ let index = input.offset(&i);
+ if index == 0 {
+ return Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::Escaped,
+ )));
+ }
+ return Ok(input.take_split(index)).into_output();
+ }
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok((input.slice(input.input_len()..), input)).into_output()
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not match the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters and transforms them
+///
+/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use std::str::from_utf8;
+/// use nom8::bytes::complete::{escaped_transform, tag};
+/// use nom8::character::complete::alpha1;
+/// use nom8::branch::alt;
+/// use nom8::combinator::value;
+///
+/// fn parser(input: &str) -> IResult<&str, String> {
+/// escaped_transform(
+/// alpha1,
+/// '\\',
+/// alt((
+/// value("\\", tag("\\")),
+/// value("\"", tag("\"")),
+/// value("\n", tag("n")),
+/// ))
+/// )(input)
+/// }
+///
+/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd"))));
+/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd"))));
+/// ```
+#[cfg(feature = "alloc")]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped_transform`][crate::bytes::escaped_transform]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::escaped_transform`"
+)]
+pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
+ mut normal: F,
+ control_char: char,
+ mut transform: G,
+) -> impl FnMut(Input) -> IResult<Input, Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| escaped_transform_internal(input, &mut normal, control_char, &mut transform)
+}
+
+#[cfg(feature = "alloc")]
+pub(crate) fn escaped_transform_internal<Input, Error, F, G, O1, O2, ExtendItem, Output>(
+ input: Input,
+ normal: &mut F,
+ control_char: char,
+ transform: &mut G,
+) -> IResult<Input, Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ use crate::input::AsChar;
+
+ let mut index = 0;
+ let mut res = input.new_builder();
+
+ let i = input.clone();
+
+ while index < i.input_len() {
+ let current_len = i.input_len();
+ let remainder = i.slice(index..);
+ match normal.parse(remainder.clone()) {
+ Ok((i2, o)) => {
+ o.extend_into(&mut res);
+ if i2.input_len() == 0 {
+ return Ok((i.slice(i.input_len()..), res));
+ } else if i2.input_len() == current_len {
+ return Ok((remainder, res));
+ } else {
+ index = input.offset(&i2);
+ }
+ }
+ Err(Err::Error(_)) => {
+ // unwrap() should be safe here since index < $i.input_len()
+ if remainder.iter_elements().next().unwrap().as_char() == control_char {
+ let next = index + control_char.len_utf8();
+ let input_len = input.input_len();
+
+ if next >= input_len {
+ return Err(Err::Error(Error::from_error_kind(
+ remainder,
+ ErrorKind::EscapedTransform,
+ )));
+ } else {
+ match transform.parse(i.slice(next..)) {
+ Ok((i2, o)) => {
+ o.extend_into(&mut res);
+ if i2.input_len() == 0 {
+ return Ok((i.slice(i.input_len()..), res));
+ } else {
+ index = input.offset(&i2);
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ } else {
+ if index == 0 {
+ return Err(Err::Error(Error::from_error_kind(
+ remainder,
+ ErrorKind::EscapedTransform,
+ )));
+ }
+ return Ok((remainder, res));
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ Ok((input.slice(index..), res))
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::character::complete::{alpha1 as alpha, digit1 as digit};
+ #[cfg(feature = "alloc")]
+ use crate::{
+ branch::alt,
+ combinator::{map, value},
+ lib::std::string::String,
+ lib::std::vec::Vec,
+ };
+
+ #[test]
+ fn complete_take_while_m_n_utf8_all_matching() {
+ let result: IResult<&str, &str> =
+ super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn");
+ assert_eq!(result, Ok(("", "øn")));
+ }
+
+ #[test]
+ fn complete_take_while_m_n_utf8_all_matching_substring() {
+ let result: IResult<&str, &str> =
+ super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn");
+ assert_eq!(result, Ok(("n", "ø")));
+ }
+
+ // issue #1336 "escaped hangs if normal parser accepts empty"
+ fn escaped_string(input: &str) -> IResult<&str, &str> {
+ use crate::character::complete::{alpha0, one_of};
+ escaped(alpha0, '\\', one_of("n"))(input)
+ }
+
+ // issue #1336 "escaped hangs if normal parser accepts empty"
+ #[test]
+ fn escaped_hang() {
+ escaped_string("7").unwrap();
+ escaped_string("a7").unwrap();
+ }
+
+ // issue ##1118 escaped does not work with empty string
+ fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> {
+ use crate::bytes::complete::*;
+ use crate::character::complete::*;
+ use crate::combinator::opt;
+ use crate::sequence::delimited;
+
+ delimited(
+ char('"'),
+ escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
+ char('"'),
+ )(input)
+ }
+
+ #[test]
+ fn escaped_hang_1118() {
+ assert_eq!(unquote(r#""""#), Ok(("", "")));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[allow(unused_variables)]
+ #[test]
+ fn escaping() {
+ use crate::character::complete::one_of;
+
+ fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(alpha, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
+ assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
+ assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
+ assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(Err::Error(error_position!(
+ &b"AB\\"[..],
+ ErrorKind::Escaped
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(Err::Error(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::Escaped,
+ error_position!(&b"A"[..], ErrorKind::OneOf)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(digit, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn escaping_str() {
+ use crate::character::complete::one_of;
+
+ fn esc(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc("abcd;"), Ok((";", "abcd")));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
+ assert_eq!(esc("\\n;"), Ok((";", "\\n")));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
+ assert_eq!(
+ esc("AB\\"),
+ Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped)))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(Err::Error(error_node_position!(
+ "AB\\A",
+ ErrorKind::Escaped,
+ error_position!("A", ErrorKind::OneOf)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, &str> {
+ escaped(digit, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));
+
+ fn esc3(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\u{241b}', one_of("\"n"))(i)
+ }
+ assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
+ }
+
+ #[cfg(feature = "alloc")]
+ fn to_s(i: Vec<u8>) -> String {
+ String::from_utf8_lossy(&i).into_owned()
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn escape_transform() {
+ fn esc(i: &[u8]) -> IResult<&[u8], String> {
+ map(
+ escaped_transform(
+ alpha,
+ '\\',
+ alt((
+ value(&b"\\"[..], tag("\\")),
+ value(&b"\""[..], tag("\"")),
+ value(&b"\n"[..], tag("n")),
+ )),
+ ),
+ to_s,
+ )(i)
+ }
+
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
+ assert_eq!(
+ esc(&b"ab\\\"cd;"[..]),
+ Ok((&b";"[..], String::from("ab\"cd")))
+ );
+ assert_eq!(
+ esc(&b"\\\"abcd;"[..]),
+ Ok((&b";"[..], String::from("\"abcd")))
+ );
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
+ assert_eq!(
+ esc(&b"ab\\\"12"[..]),
+ Ok((&b"12"[..], String::from("ab\"")))
+ );
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(Err::Error(error_position!(
+ &b"\\"[..],
+ ErrorKind::EscapedTransform
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(Err::Error(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::EscapedTransform,
+ error_position!(&b"A"[..], ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], String> {
+ map(
+ escaped_transform(
+ alpha,
+ '&',
+ alt((
+ value("è".as_bytes(), tag("egrave;")),
+ value("à".as_bytes(), tag("agrave;")),
+ )),
+ ),
+ to_s,
+ )(i)
+ }
+ assert_eq!(
+ esc2(&b"ab&egrave;DEF;"[..]),
+ Ok((&b";"[..], String::from("abèDEF")))
+ );
+ assert_eq!(
+ esc2(&b"ab&egrave;D&agrave;EF;"[..]),
+ Ok((&b";"[..], String::from("abèDàEF")))
+ );
+ }
+
+ #[cfg(feature = "std")]
+ #[test]
+ fn escape_transform_str() {
+ fn esc(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '\\',
+ alt((
+ value("\\", tag("\\")),
+ value("\"", tag("\"")),
+ value("\n", tag("n")),
+ )),
+ )(i)
+ }
+
+ assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
+ assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
+ assert_eq!(
+ esc("AB\\"),
+ Err(Err::Error(error_position!(
+ "\\",
+ ErrorKind::EscapedTransform
+ )))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(Err::Error(error_node_position!(
+ "AB\\A",
+ ErrorKind::EscapedTransform,
+ error_position!("A", ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '&',
+ alt((value("è", tag("egrave;")), value("à", tag("agrave;")))),
+ )(i)
+ }
+ assert_eq!(esc2("ab&egrave;DEF;"), Ok((";", String::from("abèDEF"))));
+ assert_eq!(
+ esc2("ab&egrave;D&agrave;EF;"),
+ Ok((";", String::from("abèDàEF")))
+ );
+
+ fn esc3(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '␛',
+ alt((value("\0", tag("0")), value("\n", tag("n")))),
+ )(i)
+ }
+ assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
+ }
+}
diff --git a/vendor/nom8/src/bytes/mod.rs b/vendor/nom8/src/bytes/mod.rs
new file mode 100644
index 000000000..12e420410
--- /dev/null
+++ b/vendor/nom8/src/bytes/mod.rs
@@ -0,0 +1,924 @@
+//! Parsers recognizing bytes streams
+
+pub mod complete;
+pub mod streaming;
+#[cfg(test)]
+mod tests;
+
+use crate::error::ParseError;
+use crate::input::{
+ Compare, FindSubstring, FindToken, InputIsStreaming, InputIter, InputLength, InputTake,
+ InputTakeAtPosition, IntoOutput, Slice, ToUsize,
+};
+use crate::lib::std::ops::RangeFrom;
+use crate::{IResult, Parser};
+
+/// Matches one token
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{bytes::any, Err, error::{Error, ErrorKind}, IResult};
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// any(input)
+/// }
+///
+/// assert_eq!(parser("abc"), Ok(("bc",'a')));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
+/// ```
+///
+/// ```
+/// # use nom8::{bytes::any, Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// assert_eq!(any::<_, (_, ErrorKind), true>(Streaming("abc")), Ok((Streaming("bc"),'a')));
+/// assert_eq!(any::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn any<I, E: ParseError<I>, const STREAMING: bool>(
+ input: I,
+) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: InputIter + InputLength + Slice<RangeFrom<usize>> + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::any(input)
+ } else {
+ complete::any(input)
+ }
+}
+
+/// Recognizes a pattern
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument
+///
+/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern
+///
+/// **Note:** [`Parser`] is implemented for strings and byte strings as a convenience (complete
+/// only)
+///
+/// # Example
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed};
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag("Hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// tag("Hello")(s)
+/// }
+///
+/// assert_eq!(parser(Streaming("Hello, World!")), Ok((Streaming(", World!"), "Hello")));
+/// assert_eq!(parser(Streaming("Something")), Err(Err::Error(Error::new(Streaming("Something"), ErrorKind::Tag))));
+/// assert_eq!(parser(Streaming("S")), Err(Err::Error(Error::new(Streaming("S"), ErrorKind::Tag))));
+/// assert_eq!(parser(Streaming("H")), Err(Err::Incomplete(Needed::new(4))));
+/// ```
+#[inline(always)]
+pub fn tag<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T> + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| {
+ let t = tag.clone();
+ if STREAMING {
+ streaming::tag_internal(i, t)
+ } else {
+ complete::tag_internal(i, t)
+ }
+ }
+}
+
+/// Recognizes a case insensitive pattern.
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument with no regard to case.
+///
+/// It will return `Err(Err::Error((_, ErrorKind::Tag)))` if the input doesn't match the pattern.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::tag_no_case;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag_no_case("hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::tag_no_case;
+///
+/// fn parser(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// tag_no_case("hello")(s)
+/// }
+///
+/// assert_eq!(parser(Streaming("Hello, World!")), Ok((Streaming(", World!"), "Hello")));
+/// assert_eq!(parser(Streaming("hello, World!")), Ok((Streaming(", World!"), "hello")));
+/// assert_eq!(parser(Streaming("HeLlO, World!")), Ok((Streaming(", World!"), "HeLlO")));
+/// assert_eq!(parser(Streaming("Something")), Err(Err::Error(Error::new(Streaming("Something"), ErrorKind::Tag))));
+/// assert_eq!(parser(Streaming("")), Err(Err::Incomplete(Needed::new(5))));
+/// ```
+#[inline(always)]
+pub fn tag_no_case<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T> + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| {
+ let t = tag.clone();
+ if STREAMING {
+ streaming::tag_no_case_internal(i, t)
+ } else {
+ complete::tag_no_case_internal(i, t)
+ }
+ }
+}
+
+/// Returns a token that matches the [pattern][FindToken]
+///
+/// **Note:** [`Parser`] is implemented as a convenience (complete
+/// only) for
+/// - `u8`
+/// - `char`
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::*;
+/// # use nom8::{Err, error::ErrorKind, error::Error};
+/// # use nom8::bytes::one_of;
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind), false>("abc")("b"), Ok(("", 'b')));
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind), false>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf))));
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind), false>("a")(""), Err(Err::Error(("", ErrorKind::OneOf))));
+///
+/// fn parser_fn(i: &str) -> IResult<&str, char> {
+/// one_of(|c| c == 'a' || c == 'b')(i)
+/// }
+/// assert_eq!(parser_fn("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser_fn("cd"), Err(Err::Error(Error::new("cd", ErrorKind::OneOf))));
+/// assert_eq!(parser_fn(""), Err(Err::Error(Error::new("", ErrorKind::OneOf))));
+/// ```
+///
+/// ```
+/// # use nom8::*;
+/// # use nom8::{Err, error::ErrorKind, error::Error, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::bytes::one_of;
+/// assert_eq!(one_of::<_, _, (_, ErrorKind), true>("abc")(Streaming("b")), Ok((Streaming(""), 'b')));
+/// assert_eq!(one_of::<_, _, (_, ErrorKind), true>("a")(Streaming("bc")), Err(Err::Error((Streaming("bc"), ErrorKind::OneOf))));
+/// assert_eq!(one_of::<_, _, (_, ErrorKind), true>("a")(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+///
+/// fn parser_fn(i: Streaming<&str>) -> IResult<Streaming<&str>, char> {
+/// one_of(|c| c == 'a' || c == 'b')(i)
+/// }
+/// assert_eq!(parser_fn(Streaming("abc")), Ok((Streaming("bc"), 'a')));
+/// assert_eq!(parser_fn(Streaming("cd")), Err(Err::Error(Error::new(Streaming("cd"), ErrorKind::OneOf))));
+/// assert_eq!(parser_fn(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn one_of<I, T, Error: ParseError<I>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(I) -> IResult<I, <I as InputIter>::Item, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| {
+ if STREAMING {
+ streaming::one_of_internal(i, &list)
+ } else {
+ complete::one_of_internal(i, &list)
+ }
+ }
+}
+
+/// Returns a token that does not match the [pattern][FindToken]
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind};
+/// # use nom8::bytes::none_of;
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind), false>("abc")("z"), Ok(("", 'z')));
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind), false>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf))));
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind), false>("a")(""), Err(Err::Error(("", ErrorKind::NoneOf))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::bytes::none_of;
+/// assert_eq!(none_of::<_, _, (_, ErrorKind), true>("abc")(Streaming("z")), Ok((Streaming(""), 'z')));
+/// assert_eq!(none_of::<_, _, (_, ErrorKind), true>("ab")(Streaming("a")), Err(Err::Error((Streaming("a"), ErrorKind::NoneOf))));
+/// assert_eq!(none_of::<_, _, (_, ErrorKind), true>("a")(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn none_of<I, T, Error: ParseError<I>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(I) -> IResult<I, <I as InputIter>::Item, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| {
+ if STREAMING {
+ streaming::none_of_internal(i, &list)
+ } else {
+ complete::none_of_internal(i, &list)
+ }
+ }
+}
+
+/// Returns the longest input slice (if any) that matches the [pattern][FindToken]
+///
+/// *Streaming version*: will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::take_while;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b""), Ok((&b""[..], &b""[..])));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_while;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// take_while(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(Streaming(b"latin123")), Ok((Streaming(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(alpha(Streaming(b"12345")), Ok((Streaming(&b"12345"[..]), &b""[..])));
+/// assert_eq!(alpha(Streaming(b"latin")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(Streaming(b"")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn take_while<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+ Input: InputTakeAtPosition,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_while_internal(i, &list)
+ } else {
+ complete::take_while_internal(i, &list)
+ }
+ }
+}
+
+/// Returns the longest (at least 1) input slice that matches the [pattern][FindToken]
+///
+/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
+///
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take_while1;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while1(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
+///
+/// fn hex(s: &str) -> IResult<&str, &str> {
+/// take_while1("1234567890ABCDEF")(s)
+/// }
+///
+/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
+/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
+/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
+/// assert_eq!(hex("D15EA5E"), Ok(("", "D15EA5E")));
+/// assert_eq!(hex(""), Err(Err::Error(Error::new("", ErrorKind::TakeWhile1))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_while1;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// take_while1(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(Streaming(b"latin123")), Ok((Streaming(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(alpha(Streaming(b"latin")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(Streaming(b"12345")), Err(Err::Error(Error::new(Streaming(&b"12345"[..]), ErrorKind::TakeWhile1))));
+///
+/// fn hex(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_while1("1234567890ABCDEF")(s)
+/// }
+///
+/// assert_eq!(hex(Streaming("123 and voila")), Ok((Streaming(" and voila"), "123")));
+/// assert_eq!(hex(Streaming("DEADBEEF and others")), Ok((Streaming(" and others"), "DEADBEEF")));
+/// assert_eq!(hex(Streaming("BADBABEsomething")), Ok((Streaming("something"), "BADBABE")));
+/// assert_eq!(hex(Streaming("D15EA5E")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(hex(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn take_while1<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_while1_internal(i, &list)
+ } else {
+ complete::take_while1_internal(i, &list)
+ }
+ }
+}
+
+/// Returns the longest (m <= len <= n) input slice that matches the [pattern][FindToken]
+///
+/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met or is out
+/// of range (m <= len <= n).
+///
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take_while_m_n;
+/// use nom8::input::AsChar;
+///
+/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while_m_n(3, 6, AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
+/// assert_eq!(short_alpha(b"latin"), Ok((&b""[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"ed"), Err(Err::Error(Error::new(&b"ed"[..], ErrorKind::TakeWhileMN))));
+/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_while_m_n;
+/// use nom8::input::AsChar;
+///
+/// fn short_alpha(s: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// take_while_m_n(3, 6, AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(short_alpha(Streaming(b"latin123")), Ok((Streaming(&b"123"[..]), &b"latin"[..])));
+/// assert_eq!(short_alpha(Streaming(b"lengthy")), Ok((Streaming(&b"y"[..]), &b"length"[..])));
+/// assert_eq!(short_alpha(Streaming(b"latin")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(Streaming(b"ed")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(Streaming(b"12345")), Err(Err::Error(Error::new(Streaming(&b"12345"[..]), ErrorKind::TakeWhileMN))));
+/// ```
+#[inline(always)]
+pub fn take_while_m_n<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ m: usize,
+ n: usize,
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input:
+ InputTake + InputIter + InputLength + Slice<RangeFrom<usize>> + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputIter>::Item>,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_while_m_n_internal(i, m, n, &list)
+ } else {
+ complete::take_while_m_n_internal(i, m, n, &list)
+ }
+ }
+}
+
+/// Returns the longest input slice (if any) till a [pattern][FindToken] is met.
+///
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::take_till;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Ok(("", "")));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_till;
+///
+/// fn till_colon(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_till(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon(Streaming("latin:123")), Ok((Streaming(":123"), "latin")));
+/// assert_eq!(till_colon(Streaming(":empty matched")), Ok((Streaming(":empty matched"), ""))); //allowed
+/// assert_eq!(till_colon(Streaming("12345")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn take_till<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_till_internal(i, &list)
+ } else {
+ complete::take_till_internal(i, &list)
+ }
+ }
+}
+
+/// Returns the longest (at least 1) input slice till a [pattern][FindToken] is met.
+///
+/// It will return `Err(Err::Error((_, ErrorKind::TakeTill1)))` if the input is empty or the
+/// predicate matches the first input.
+///
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take_till1;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till1(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
+///
+/// fn not_space(s: &str) -> IResult<&str, &str> {
+/// take_till1(" \t\r\n")(s)
+/// }
+///
+/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
+/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
+/// assert_eq!(not_space("Nospace"), Ok(("", "Nospace")));
+/// assert_eq!(not_space(""), Err(Err::Error(Error::new("", ErrorKind::TakeTill1))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_till1;
+///
+/// fn till_colon(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_till1(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon(Streaming("latin:123")), Ok((Streaming(":123"), "latin")));
+/// assert_eq!(till_colon(Streaming(":empty matched")), Err(Err::Error(Error::new(Streaming(":empty matched"), ErrorKind::TakeTill1))));
+/// assert_eq!(till_colon(Streaming("12345")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+///
+/// fn not_space(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_till1(" \t\r\n")(s)
+/// }
+///
+/// assert_eq!(not_space(Streaming("Hello, World!")), Ok((Streaming(" World!"), "Hello,")));
+/// assert_eq!(not_space(Streaming("Sometimes\t")), Ok((Streaming("\t"), "Sometimes")));
+/// assert_eq!(not_space(Streaming("Nospace")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(not_space(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn take_till1<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_till1_internal(i, &list)
+ } else {
+ complete::take_till1_internal(i, &list)
+ }
+ }
+}
+
+/// Returns an input slice containing the first N input elements (Input[..N]).
+///
+/// *Complete version*: It will return `Err(Err::Error((_, ErrorKind::Eof)))` if the input is shorter than the argument.
+///
+/// *Streaming version*: if the input has less than N elements, `take` will
+/// return a `Err::Incomplete(Needed::new(M))` where M is the number of
+/// additional bytes the parser would need to succeed.
+/// It is well defined for `&[u8]` as the number of elements is the byte size,
+/// but for types like `&str`, we cannot know how many bytes correspond for
+/// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)`
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take;
+///
+/// fn take6(s: &str) -> IResult<&str, &str> {
+/// take(6usize)(s)
+/// }
+///
+/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
+/// assert_eq!(take6("things"), Ok(("", "things")));
+/// assert_eq!(take6("short"), Err(Err::Error(Error::new("short", ErrorKind::Eof))));
+/// assert_eq!(take6(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
+/// ```
+///
+/// The units that are taken will depend on the input type. For example, for a
+/// `&str` it will take a number of `char`'s, whereas for a `&[u8]` it will
+/// take that many `u8`'s:
+///
+/// ```rust
+/// use nom8::error::Error;
+/// use nom8::bytes::take;
+///
+/// assert_eq!(take::<_, _, Error<_>, false>(1usize)("💙"), Ok(("", "💙")));
+/// assert_eq!(take::<_, _, Error<_>, false>(1usize)("💙".as_bytes()), Ok((b"\x9F\x92\x99".as_ref(), b"\xF0".as_ref())));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take;
+///
+/// fn take6(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take(6usize)(s)
+/// }
+///
+/// assert_eq!(take6(Streaming("1234567")), Ok((Streaming("7"), "123456")));
+/// assert_eq!(take6(Streaming("things")), Ok((Streaming(""), "things")));
+/// // `Unknown` as we don't know the number of bytes that `count` corresponds to
+/// assert_eq!(take6(Streaming("short")), Err(Err::Incomplete(Needed::Unknown)));
+/// ```
+#[inline(always)]
+pub fn take<C, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ count: C,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputIter + InputLength + InputTake + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ C: ToUsize,
+{
+ let c = count.to_usize();
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_internal(i, c)
+ } else {
+ complete::take_internal(i, c)
+ }
+ }
+}
+
+/// Returns the input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern.
+///
+/// *Complete version*: It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
+/// if the pattern wasn't met.
+///
+/// *Streaming version*: will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take_until;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_until;
+///
+/// fn until_eof(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_until("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof(Streaming("hello, worldeof")), Ok((Streaming("eof"), "hello, world")));
+/// assert_eq!(until_eof(Streaming("hello, world")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Streaming("hello, worldeo")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Streaming("1eof2eof")), Ok((Streaming("eof2eof"), "1")));
+/// ```
+#[inline(always)]
+pub fn take_until<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T> + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_until_internal(i, tag.clone())
+ } else {
+ complete::take_until_internal(i, tag.clone())
+ }
+ }
+}
+
+/// Returns the non empty input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern.
+///
+/// *Complete version*: It will return `Err(Err::Error((_, ErrorKind::TakeUntil)))`
+/// if the pattern wasn't met.
+///
+/// *Streaming version*: will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::take_until1;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until1("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Error(Error::new("hello, world", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof(""), Err(Err::Error(Error::new("", ErrorKind::TakeUntil))));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::take_until1;
+///
+/// fn until_eof(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// take_until1("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof(Streaming("hello, worldeof")), Ok((Streaming("eof"), "hello, world")));
+/// assert_eq!(until_eof(Streaming("hello, world")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Streaming("hello, worldeo")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof(Streaming("1eof2eof")), Ok((Streaming("eof2eof"), "1")));
+/// assert_eq!(until_eof(Streaming("eof")), Err(Err::Error(Error::new(Streaming("eof"), ErrorKind::TakeUntil))));
+/// ```
+#[inline(always)]
+pub fn take_until1<T, Input, Error: ParseError<Input>, const STREAMING: bool>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T> + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| {
+ if STREAMING {
+ streaming::take_until1_internal(i, tag.clone())
+ } else {
+ complete::take_until1_internal(i, tag.clone())
+ }
+ }
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not accept the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters
+/// # Example
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::character::digit1;
+/// use nom8::bytes::escaped;
+/// use nom8::bytes::one_of;
+///
+/// fn esc(s: &str) -> IResult<&str, &str> {
+/// escaped(digit1, '\\', one_of(r#""n\"#))(s)
+/// }
+///
+/// assert_eq!(esc("123;"), Ok((";", "123")));
+/// assert_eq!(esc(r#"12\"34;"#), Ok((";", r#"12\"34"#)));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::character::digit1;
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::escaped;
+/// use nom8::bytes::one_of;
+///
+/// fn esc(s: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// escaped(digit1, '\\', one_of("\"n\\"))(s)
+/// }
+///
+/// assert_eq!(esc(Streaming("123;")), Ok((Streaming(";"), "123")));
+/// assert_eq!(esc(Streaming("12\\\"34;")), Ok((Streaming(";"), "12\\\"34")));
+/// ```
+#[inline(always)]
+pub fn escaped<'a, Input: 'a, Error, F, G, O1, O2, const STREAMING: bool>(
+ mut normal: F,
+ control_char: char,
+ mut escapable: G,
+) -> impl FnMut(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter
+ + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| {
+ if STREAMING {
+ streaming::escaped_internal(input, &mut normal, control_char, &mut escapable)
+ } else {
+ complete::escaped_internal(input, &mut normal, control_char, &mut escapable)
+ }
+ }
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not match the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters and transforms them
+///
+/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
+///
+/// ```
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use std::str::from_utf8;
+/// use nom8::bytes::{escaped_transform, tag};
+/// use nom8::character::alpha1;
+/// use nom8::branch::alt;
+/// use nom8::combinator::value;
+///
+/// fn parser(input: &str) -> IResult<&str, String> {
+/// escaped_transform(
+/// alpha1,
+/// '\\',
+/// alt((
+/// tag("\\").value("\\"),
+/// tag("\"").value("\""),
+/// tag("n").value("\n"),
+/// ))
+/// )(input)
+/// }
+///
+/// assert_eq!(parser("ab\\\"cd"), Ok(("", String::from("ab\"cd"))));
+/// assert_eq!(parser("ab\\ncd"), Ok(("", String::from("ab\ncd"))));
+/// ```
+///
+/// ```
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use std::str::from_utf8;
+/// # use nom8::input::Streaming;
+/// use nom8::bytes::{escaped_transform, tag};
+/// use nom8::character::alpha1;
+/// use nom8::branch::alt;
+/// use nom8::combinator::value;
+///
+/// fn parser(input: Streaming<&str>) -> IResult<Streaming<&str>, String> {
+/// escaped_transform(
+/// alpha1,
+/// '\\',
+/// alt((
+/// tag("\\").value("\\"),
+/// tag("\"").value("\""),
+/// tag("n").value("\n"),
+/// ))
+/// )(input)
+/// }
+///
+/// assert_eq!(parser(Streaming("ab\\\"cd\"")), Ok((Streaming("\""), String::from("ab\"cd"))));
+/// ```
+#[cfg(feature = "alloc")]
+#[inline(always)]
+pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output, const STREAMING: bool>(
+ mut normal: F,
+ control_char: char,
+ mut transform: G,
+) -> impl FnMut(Input) -> IResult<Input, Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter
+ + InputIsStreaming<STREAMING>,
+ Input: IntoOutput,
+ Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| {
+ if STREAMING {
+ streaming::escaped_transform_internal(input, &mut normal, control_char, &mut transform)
+ } else {
+ complete::escaped_transform_internal(input, &mut normal, control_char, &mut transform)
+ }
+ }
+}
diff --git a/vendor/nom8/src/bytes/streaming.rs b/vendor/nom8/src/bytes/streaming.rs
new file mode 100644
index 000000000..40c1e04c8
--- /dev/null
+++ b/vendor/nom8/src/bytes/streaming.rs
@@ -0,0 +1,1465 @@
+//! Parsers recognizing bytes streams, streaming version
+
+#![allow(deprecated)]
+
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::{
+ Compare, CompareResult, FindSubstring, FindToken, InputIter, InputLength, InputTake,
+ InputTakeAtPosition, IntoOutput, Slice, ToUsize,
+};
+use crate::lib::std::ops::RangeFrom;
+use crate::lib::std::result::Result::*;
+use crate::IntoOutputIResult;
+use crate::{Err, IResult, Needed, Parser};
+
+pub(crate) fn any<I, E: ParseError<I>>(input: I) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: InputIter + InputLength + Slice<RangeFrom<usize>>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ None => Err(Err::Incomplete(Needed::new(1))),
+ Some((_, c)) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ }
+}
+
+/// Recognizes a pattern.
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag("Hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser("S"), Err(Err::Error(Error::new("S", ErrorKind::Tag))));
+/// assert_eq!(parser("H"), Err(Err::Incomplete(Needed::new(4))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag`][crate::bytes::tag] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::tag` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn tag<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| tag_internal(i, tag.clone())
+}
+
+pub(crate) fn tag_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let tag_len = t.input_len();
+
+ let res: IResult<_, _, Error> = match i.compare(t) {
+ CompareResult::Ok => Ok(i.take_split(tag_len)),
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))),
+ CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(Error::from_error_kind(i, e)))
+ }
+ };
+ res.into_output()
+}
+
+/// Recognizes a case insensitive pattern.
+///
+/// The input data will be compared to the tag combinator's argument and will return the part of
+/// the input that matches the argument with no regard to case.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::tag_no_case;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag_no_case("hello")(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser("HeLlO, World!"), Ok((", World!", "HeLlO")));
+/// assert_eq!(parser("Something"), Err(Err::Error(Error::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(5))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::tag_no_case`][crate::bytes::tag_no_case] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::tag_no_case` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn tag_no_case<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength + Clone,
+{
+ move |i: Input| tag_no_case_internal(i, tag.clone())
+}
+
+pub(crate) fn tag_no_case_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + Compare<T>,
+ Input: IntoOutput,
+ T: InputLength,
+{
+ let tag_len = t.input_len();
+
+ let res: IResult<_, _, Error> = match (i).compare_no_case(t) {
+ CompareResult::Ok => Ok(i.take_split(tag_len)),
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(tag_len - i.input_len()))),
+ CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(Error::from_error_kind(i, e)))
+ }
+ };
+ res.into_output()
+}
+
+pub(crate) fn one_of_internal<I, T, E: ParseError<I>>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ Some((_, c)) if list.find_token(c) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::OneOf))),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+}
+
+pub(crate) fn none_of_internal<I, T, E: ParseError<I>>(
+ input: I,
+ list: &T,
+) -> IResult<I, <I as InputIter>::Item, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ let mut it = input.iter_indices();
+ match it.next() {
+ Some((_, c)) if !list.find_token(c) => match it.next() {
+ None => Ok((input.slice(input.input_len()..), c)),
+ Some((idx, _)) => Ok((input.slice(idx..), c)),
+ },
+ Some(_) => Err(Err::Error(E::from_error_kind(input, ErrorKind::NoneOf))),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+}
+
+/// Parse till certain characters are met.
+///
+/// The parser will return the longest slice till one of the characters of the combinator's argument are met.
+///
+/// It doesn't consume the matched character.
+///
+/// It will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::is_not;
+///
+/// fn not_space(s: &str) -> IResult<&str, &str> {
+/// is_not(" \t\r\n")(s)
+/// }
+///
+/// assert_eq!(not_space("Hello, World!"), Ok((" World!", "Hello,")));
+/// assert_eq!(not_space("Sometimes\t"), Ok(("\t", "Sometimes")));
+/// assert_eq!(not_space("Nospace"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(not_space(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_till1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn is_not<T, Input, Error: ParseError<Input>>(
+ arr: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| is_not_internal(i, &arr)
+}
+
+pub(crate) fn is_not_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ arr: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::IsNot;
+ i.split_at_position1_streaming(|c| arr.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest slice of the matches the pattern.
+///
+/// The parser will return the longest slice consisting of the characters in provided in the
+/// combinator's argument.
+///
+/// # Streaming specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern wasn't met
+/// or if the pattern reaches the end of the input.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::is_a;
+///
+/// fn hex(s: &str) -> IResult<&str, &str> {
+/// is_a("1234567890ABCDEF")(s)
+/// }
+///
+/// assert_eq!(hex("123 and voila"), Ok((" and voila", "123")));
+/// assert_eq!(hex("DEADBEEF and others"), Ok((" and others", "DEADBEEF")));
+/// assert_eq!(hex("BADBABEsomething"), Ok(("something", "BADBABE")));
+/// assert_eq!(hex("D15EA5E"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(hex(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_while1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn is_a<T, Input, Error: ParseError<Input>>(
+ arr: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| is_a_internal(i, &arr)
+}
+
+pub(crate) fn is_a_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ arr: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::IsA;
+ i.split_at_position1_streaming(|c| !arr.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest input slice (if any) that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::take_while;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"12345"), Ok((&b"12345"[..], &b""[..])));
+/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(b""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while`][crate::bytes::take_while] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_while` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_while<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_while_internal(i, &list)
+}
+
+pub(crate) fn take_while_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ i.split_at_position_streaming(|c| !list.find_token(c))
+ .into_output()
+}
+
+/// Returns the longest (at least 1) input slice that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// It will return an `Err(Err::Error((_, ErrorKind::TakeWhile1)))` if the pattern wasn't met.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` or if the pattern reaches the end of the input.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::take_while1;
+/// use nom8::input::AsChar;
+///
+/// fn alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while1(AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhile1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while1`][crate::bytes::take_while1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_while1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_while1<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_while1_internal(i, &list)
+}
+
+pub(crate) fn take_while1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::TakeWhile1;
+ i.split_at_position1_streaming(|c| !list.find_token(c), e)
+ .into_output()
+}
+
+/// Returns the longest (m <= len <= n) input slice that matches the predicate.
+///
+/// The parser will return the longest slice that matches the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// It will return an `Err::Error((_, ErrorKind::TakeWhileMN))` if the pattern wasn't met.
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::take_while_m_n;
+/// use nom8::input::AsChar;
+///
+/// fn short_alpha(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// take_while_m_n(3, 6, AsChar::is_alpha)(s)
+/// }
+///
+/// assert_eq!(short_alpha(b"latin123"), Ok((&b"123"[..], &b"latin"[..])));
+/// assert_eq!(short_alpha(b"lengthy"), Ok((&b"y"[..], &b"length"[..])));
+/// assert_eq!(short_alpha(b"latin"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(b"ed"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(short_alpha(b"12345"), Err(Err::Error(Error::new(&b"12345"[..], ErrorKind::TakeWhileMN))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_while_m_n`][crate::bytes::take_while_m_n] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_while_m_n` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_while_m_n<T, Input, Error: ParseError<Input>>(
+ m: usize,
+ n: usize,
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputIter + InputLength,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputIter>::Item>,
+{
+ move |i: Input| take_while_m_n_internal(i, m, n, &list)
+}
+
+pub(crate) fn take_while_m_n_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ m: usize,
+ n: usize,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputIter + InputLength,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputIter>::Item>,
+{
+ let input = i;
+
+ match input.position(|c| !list.find_token(c)) {
+ Some(idx) => {
+ if idx >= m {
+ if idx <= n {
+ let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(idx) {
+ Ok(input.take_split(index)).into_output()
+ } else {
+ Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ )))
+ };
+ res
+ } else {
+ let res: IResult<_, _, Error> = if let Ok(index) = input.slice_index(n) {
+ Ok(input.take_split(index)).into_output()
+ } else {
+ Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ )))
+ };
+ res
+ }
+ } else {
+ let e = ErrorKind::TakeWhileMN;
+ Err(Err::Error(Error::from_error_kind(input, e)))
+ }
+ }
+ None => {
+ let len = input.input_len();
+ if len >= n {
+ match input.slice_index(n) {
+ Ok(index) => Ok(input.take_split(index)).into_output(),
+ Err(_needed) => Err(Err::Error(Error::from_error_kind(
+ input,
+ ErrorKind::TakeWhileMN,
+ ))),
+ }
+ } else {
+ let needed = if m > len { m - len } else { 1 };
+ Err(Err::Incomplete(Needed::new(needed)))
+ }
+ }
+ }
+}
+
+/// Returns the longest input slice (if any) till a predicate is met.
+///
+/// The parser will return the longest slice till the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::take_till;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
+/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till`][crate::bytes::take_till] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_till` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_till<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_till_internal(i, &list)
+}
+
+pub(crate) fn take_till_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ i.split_at_position_streaming(|c| list.find_token(c))
+ .into_output()
+}
+
+/// Returns the longest (at least 1) input slice till a predicate is met.
+///
+/// The parser will return the longest slice till the given predicate *(a function that
+/// takes the input and returns a bool)*.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::take_till1;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till1(|c| c == ':')(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Err(Err::Error(Error::new(":empty matched", ErrorKind::TakeTill1))));
+/// assert_eq!(till_colon("12345"), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_till1`][crate::bytes::take_till1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_till1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_till1<T, Input, Error: ParseError<Input>>(
+ list: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ move |i: Input| take_till1_internal(i, &list)
+}
+
+pub(crate) fn take_till1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ list: &T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTakeAtPosition,
+ Input: IntoOutput,
+ T: FindToken<<Input as InputTakeAtPosition>::Item>,
+{
+ let e: ErrorKind = ErrorKind::TakeTill1;
+ i.split_at_position1_streaming(|c| list.find_token(c), e)
+ .into_output()
+}
+
+/// Returns an input slice containing the first N input elements (Input[..N]).
+///
+/// # Streaming Specific
+/// *Streaming version* if the input has less than N elements, `take` will
+/// return a `Err::Incomplete(Needed::new(M))` where M is the number of
+/// additional bytes the parser would need to succeed.
+/// It is well defined for `&[u8]` as the number of elements is the byte size,
+/// but for types like `&str`, we cannot know how many bytes correspond for
+/// the next few chars, so the result will be `Err::Incomplete(Needed::Unknown)`
+///
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::take;
+///
+/// fn take6(s: &str) -> IResult<&str, &str> {
+/// take(6usize)(s)
+/// }
+///
+/// assert_eq!(take6("1234567"), Ok(("7", "123456")));
+/// assert_eq!(take6("things"), Ok(("", "things")));
+/// assert_eq!(take6("short"), Err(Err::Incomplete(Needed::Unknown)));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take`][crate::bytes::take] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take<C, Input, Error: ParseError<Input>>(
+ count: C,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputIter + InputTake + InputLength,
+ Input: IntoOutput,
+ C: ToUsize,
+{
+ let c = count.to_usize();
+ move |i: Input| take_internal(i, c)
+}
+
+pub(crate) fn take_internal<Input, Error: ParseError<Input>>(
+ i: Input,
+ c: usize,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputIter + InputTake + InputLength,
+ Input: IntoOutput,
+{
+ match i.slice_index(c) {
+ Err(i) => Err(Err::Incomplete(i)),
+ Ok(index) => Ok(i.take_split(index)).into_output(),
+ }
+}
+
+/// Returns the input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::bytes::streaming::take_until;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until`][crate::bytes::take_until] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_until` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_until<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T>,
+ Input: IntoOutput,
+ T: Clone,
+{
+ move |i: Input| take_until_internal(i, tag.clone())
+}
+
+pub(crate) fn take_until_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T>,
+ Input: IntoOutput,
+{
+ let res: IResult<_, _, Error> = match i.find_substring(t) {
+ None => Err(Err::Incomplete(Needed::Unknown)),
+ Some(index) => Ok(i.take_split(index)),
+ };
+ res.into_output()
+}
+
+/// Returns the non empty input slice up to the first occurrence of the pattern.
+///
+/// It doesn't consume the pattern.
+///
+/// # Streaming Specific
+/// *Streaming version* will return a `Err::Incomplete(Needed::new(N))` if the input doesn't
+/// contain the pattern or if the input is smaller than the pattern.
+/// # Example
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::bytes::streaming::take_until1;
+///
+/// fn until_eof(s: &str) -> IResult<&str, &str> {
+/// take_until1("eof")(s)
+/// }
+///
+/// assert_eq!(until_eof("hello, worldeof"), Ok(("eof", "hello, world")));
+/// assert_eq!(until_eof("hello, world"), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof("hello, worldeo"), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(until_eof("1eof2eof"), Ok(("eof2eof", "1")));
+/// assert_eq!(until_eof("eof"), Err(Err::Error(Error::new("eof", ErrorKind::TakeUntil))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::take_until1`][crate::bytes::take_until1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::take_until1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn take_until1<T, Input, Error: ParseError<Input>>(
+ tag: T,
+) -> impl Fn(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T>,
+ Input: IntoOutput,
+ T: Clone,
+{
+ move |i: Input| take_until1_internal(i, tag.clone())
+}
+
+pub(crate) fn take_until1_internal<T, Input, Error: ParseError<Input>>(
+ i: Input,
+ t: T,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: InputTake + InputLength + FindSubstring<T>,
+ Input: IntoOutput,
+{
+ let res: IResult<_, _, Error> = match i.find_substring(t) {
+ None => Err(Err::Incomplete(Needed::Unknown)),
+ Some(0) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::TakeUntil))),
+ Some(index) => Ok(i.take_split(index)),
+ };
+ res.into_output()
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not accept the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters
+/// # Example
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use nom8::character::streaming::digit1;
+/// use nom8::bytes::streaming::escaped;
+/// use nom8::character::streaming::one_of;
+///
+/// fn esc(s: &str) -> IResult<&str, &str> {
+/// escaped(digit1, '\\', one_of("\"n\\"))(s)
+/// }
+///
+/// assert_eq!(esc("123;"), Ok((";", "123")));
+/// assert_eq!(esc("12\\\"34;"), Ok((";", "12\\\"34")));
+/// ```
+///
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped`][crate::bytes::escaped] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::escaped` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn escaped<Input, Error, F, G, O1, O2>(
+ mut normal: F,
+ control_char: char,
+ mut escapable: G,
+) -> impl FnMut(Input) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: IntoOutput,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| escaped_internal(input, &mut normal, control_char, &mut escapable)
+}
+
+pub(crate) fn escaped_internal<Input, Error, F, G, O1, O2>(
+ input: Input,
+ normal: &mut F,
+ control_char: char,
+ escapable: &mut G,
+) -> IResult<Input, <Input as IntoOutput>::Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: IntoOutput,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ use crate::input::AsChar;
+
+ let mut i = input.clone();
+
+ while i.input_len() > 0 {
+ let current_len = i.input_len();
+
+ match normal.parse(i.clone()) {
+ Ok((i2, _)) => {
+ if i2.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::Unknown));
+ } else if i2.input_len() == current_len {
+ let index = input.offset(&i2);
+ return Ok(input.take_split(index)).into_output();
+ } else {
+ i = i2;
+ }
+ }
+ Err(Err::Error(_)) => {
+ // unwrap() should be safe here since index < $i.input_len()
+ if i.iter_elements().next().unwrap().as_char() == control_char {
+ let next = control_char.len_utf8();
+ if next >= i.input_len() {
+ return Err(Err::Incomplete(Needed::new(1)));
+ } else {
+ match escapable.parse(i.slice(next..)) {
+ Ok((i2, _)) => {
+ if i2.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::Unknown));
+ } else {
+ i = i2;
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ } else {
+ let index = input.offset(&i);
+ return Ok(input.take_split(index)).into_output();
+ }
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Err(Err::Incomplete(Needed::Unknown))
+}
+
+/// Matches a byte string with escaped characters.
+///
+/// * The first argument matches the normal characters (it must not match the control character)
+/// * The second argument is the control character (like `\` in most languages)
+/// * The third argument matches the escaped characters and transforms them
+///
+/// As an example, the chain `abc\tdef` could be `abc def` (it also consumes the control character)
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// # use std::str::from_utf8;
+/// use nom8::bytes::streaming::{escaped_transform, tag};
+/// use nom8::character::streaming::alpha1;
+/// use nom8::branch::alt;
+/// use nom8::combinator::value;
+///
+/// fn parser(input: &str) -> IResult<&str, String> {
+/// escaped_transform(
+/// alpha1,
+/// '\\',
+/// alt((
+/// value("\\", tag("\\")),
+/// value("\"", tag("\"")),
+/// value("\n", tag("n")),
+/// ))
+/// )(input)
+/// }
+///
+/// assert_eq!(parser("ab\\\"cd\""), Ok(("\"", String::from("ab\"cd"))));
+/// ```
+#[cfg(feature = "alloc")]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::escaped_transform`][crate::bytes::escaped_transform] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::escaped_transform` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn escaped_transform<Input, Error, F, G, O1, O2, ExtendItem, Output>(
+ mut normal: F,
+ control_char: char,
+ mut transform: G,
+) -> impl FnMut(Input) -> IResult<Input, Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ move |input: Input| escaped_transform_internal(input, &mut normal, control_char, &mut transform)
+}
+
+#[cfg(feature = "alloc")]
+pub(crate) fn escaped_transform_internal<Input, Error, F, G, O1, O2, ExtendItem, Output>(
+ input: Input,
+ normal: &mut F,
+ control_char: char,
+ transform: &mut G,
+) -> IResult<Input, Output, Error>
+where
+ Input: Clone
+ + crate::input::Offset
+ + InputLength
+ + InputTake
+ + InputTakeAtPosition
+ + Slice<RangeFrom<usize>>
+ + InputIter,
+ Input: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O1: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ O2: crate::input::ExtendInto<Item = ExtendItem, Extender = Output>,
+ <Input as InputIter>::Item: crate::input::AsChar,
+ F: Parser<Input, O1, Error>,
+ G: Parser<Input, O2, Error>,
+ Error: ParseError<Input>,
+{
+ use crate::input::AsChar;
+
+ let mut index = 0;
+ let mut res = input.new_builder();
+
+ let i = input.clone();
+
+ while index < i.input_len() {
+ let current_len = i.input_len();
+ let remainder = i.slice(index..);
+ match normal.parse(remainder.clone()) {
+ Ok((i2, o)) => {
+ o.extend_into(&mut res);
+ if i2.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::Unknown));
+ } else if i2.input_len() == current_len {
+ return Ok((remainder, res));
+ } else {
+ index = input.offset(&i2);
+ }
+ }
+ Err(Err::Error(_)) => {
+ // unwrap() should be safe here since index < $i.input_len()
+ if remainder.iter_elements().next().unwrap().as_char() == control_char {
+ let next = index + control_char.len_utf8();
+ let input_len = input.input_len();
+
+ if next >= input_len {
+ return Err(Err::Incomplete(Needed::Unknown));
+ } else {
+ match transform.parse(i.slice(next..)) {
+ Ok((i2, o)) => {
+ o.extend_into(&mut res);
+ if i2.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::Unknown));
+ } else {
+ index = input.offset(&i2);
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ } else {
+ return Ok((remainder, res));
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ Err(Err::Incomplete(Needed::Unknown))
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::character::streaming::{
+ alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
+ multispace1 as multispace, oct_digit1 as oct_digit, space1 as space,
+ };
+ use crate::error::ErrorKind;
+ use crate::input::AsChar;
+ use crate::{Err, IResult, Needed};
+
+ #[test]
+ fn is_a() {
+ use crate::bytes::streaming::is_a;
+
+ fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ is_a("ab")(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(a_or_b(a), Ok((&b"cd"[..], &b"ab"[..])));
+
+ let b = &b"bcde"[..];
+ assert_eq!(a_or_b(b), Ok((&b"cde"[..], &b"b"[..])));
+
+ let c = &b"cdef"[..];
+ assert_eq!(
+ a_or_b(c),
+ Err(Err::Error(error_position!(c, ErrorKind::IsA)))
+ );
+
+ let d = &b"bacdef"[..];
+ assert_eq!(a_or_b(d), Ok((&b"cdef"[..], &b"ba"[..])));
+ }
+
+ #[test]
+ fn is_not() {
+ use crate::bytes::streaming::is_not;
+
+ fn a_or_b(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ is_not("ab")(i)
+ }
+
+ let a = &b"cdab"[..];
+ assert_eq!(a_or_b(a), Ok((&b"ab"[..], &b"cd"[..])));
+
+ let b = &b"cbde"[..];
+ assert_eq!(a_or_b(b), Ok((&b"bde"[..], &b"c"[..])));
+
+ let c = &b"abab"[..];
+ assert_eq!(
+ a_or_b(c),
+ Err(Err::Error(error_position!(c, ErrorKind::IsNot)))
+ );
+
+ let d = &b"cdefba"[..];
+ assert_eq!(a_or_b(d), Ok((&b"ba"[..], &b"cdef"[..])));
+
+ let e = &b"e"[..];
+ assert_eq!(a_or_b(e), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ fn take_until_incomplete() {
+ use crate::bytes::streaming::take_until;
+ fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_until("end")(i)
+ }
+ assert_eq!(y(&b"nd"[..]), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(y(&b"123"[..]), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(y(&b"123en"[..]), Err(Err::Incomplete(Needed::Unknown)));
+ }
+
+ #[test]
+ fn take_until_incomplete_s() {
+ use crate::bytes::streaming::take_until;
+ fn ys(i: &str) -> IResult<&str, &str> {
+ take_until("end")(i)
+ }
+ assert_eq!(ys("123en"), Err(Err::Incomplete(Needed::Unknown)));
+ }
+
+ #[test]
+ fn recognize() {
+ use crate::bytes::streaming::{tag, take};
+ use crate::combinator::recognize;
+ use crate::sequence::delimited;
+
+ fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(delimited(tag("<!--"), take(5_usize), tag("-->")))(i)
+ }
+ let r = x(&b"<!-- abc --> aaa"[..]);
+ assert_eq!(r, Ok((&b" aaa"[..], &b"<!-- abc -->"[..])));
+
+ let semicolon = &b";"[..];
+
+ fn ya(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(alpha)(i)
+ }
+ let ra = ya(&b"abc;"[..]);
+ assert_eq!(ra, Ok((semicolon, &b"abc"[..])));
+
+ fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(digit)(i)
+ }
+ let rd = yd(&b"123;"[..]);
+ assert_eq!(rd, Ok((semicolon, &b"123"[..])));
+
+ fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(hex_digit)(i)
+ }
+ let rhd = yhd(&b"123abcDEF;"[..]);
+ assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..])));
+
+ fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(oct_digit)(i)
+ }
+ let rod = yod(&b"1234567;"[..]);
+ assert_eq!(rod, Ok((semicolon, &b"1234567"[..])));
+
+ fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(alphanumeric)(i)
+ }
+ let ran = yan(&b"123abc;"[..]);
+ assert_eq!(ran, Ok((semicolon, &b"123abc"[..])));
+
+ fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(space)(i)
+ }
+ let rs = ys(&b" \t;"[..]);
+ assert_eq!(rs, Ok((semicolon, &b" \t"[..])));
+
+ fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(multispace)(i)
+ }
+ let rms = yms(&b" \t\r\n;"[..]);
+ assert_eq!(rms, Ok((semicolon, &b" \t\r\n"[..])));
+ }
+
+ #[test]
+ fn take_while() {
+ use crate::bytes::streaming::take_while;
+
+ fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_while(AsChar::is_alpha)(i)
+ }
+ let a = b"";
+ let b = b"abcd";
+ let c = b"abcd123";
+ let d = b"123";
+
+ assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(&c[..]), Ok((&d[..], &b[..])));
+ assert_eq!(f(&d[..]), Ok((&d[..], &a[..])));
+ }
+
+ #[test]
+ fn take_while1() {
+ use crate::bytes::streaming::take_while1;
+
+ fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_while1(AsChar::is_alpha)(i)
+ }
+ let a = b"";
+ let b = b"abcd";
+ let c = b"abcd123";
+ let d = b"123";
+
+ assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(&b[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(&c[..]), Ok((&b"123"[..], &b[..])));
+ assert_eq!(
+ f(&d[..]),
+ Err(Err::Error(error_position!(&d[..], ErrorKind::TakeWhile1)))
+ );
+ }
+
+ #[test]
+ fn take_while_m_n() {
+ use crate::bytes::streaming::take_while_m_n;
+
+ fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_while_m_n(2, 4, AsChar::is_alpha)(i)
+ }
+ let a = b"";
+ let b = b"a";
+ let c = b"abc";
+ let d = b"abc123";
+ let e = b"abcde";
+ let f = b"123";
+
+ assert_eq!(x(&a[..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(x(&b[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(&c[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(&d[..]), Ok((&b"123"[..], &c[..])));
+ assert_eq!(x(&e[..]), Ok((&b"e"[..], &b"abcd"[..])));
+ assert_eq!(
+ x(&f[..]),
+ Err(Err::Error(error_position!(&f[..], ErrorKind::TakeWhileMN)))
+ );
+ }
+
+ #[test]
+ fn take_till() {
+ use crate::bytes::streaming::take_till;
+
+ fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_till(AsChar::is_alpha)(i)
+ }
+ let a = b"";
+ let b = b"abcd";
+ let c = b"123abcd";
+ let d = b"123";
+
+ assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(&b[..]), Ok((&b"abcd"[..], &b""[..])));
+ assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
+ assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ fn take_till1() {
+ use crate::bytes::streaming::take_till1;
+
+ fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_till1(AsChar::is_alpha)(i)
+ }
+ let a = b"";
+ let b = b"abcd";
+ let c = b"123abcd";
+ let d = b"123";
+
+ assert_eq!(f(&a[..]), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(
+ f(&b[..]),
+ Err(Err::Error(error_position!(&b[..], ErrorKind::TakeTill1)))
+ );
+ assert_eq!(f(&c[..]), Ok((&b"abcd"[..], &b"123"[..])));
+ assert_eq!(f(&d[..]), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ fn take_while_utf8() {
+ use crate::bytes::streaming::take_while;
+
+ fn f(i: &str) -> IResult<&str, &str> {
+ take_while(|c| c != '點')(i)
+ }
+
+ assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f("abcd點"), Ok(("點", "abcd")));
+ assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));
+
+ fn g(i: &str) -> IResult<&str, &str> {
+ take_while(|c| c == '點')(i)
+ }
+
+ assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g("點abcd"), Ok(("abcd", "點")));
+ assert_eq!(g("點點點a"), Ok(("a", "點點點")));
+ }
+
+ #[test]
+ fn take_till_utf8() {
+ use crate::bytes::streaming::take_till;
+
+ fn f(i: &str) -> IResult<&str, &str> {
+ take_till(|c| c == '點')(i)
+ }
+
+ assert_eq!(f(""), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f("abcd"), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f("abcd點"), Ok(("點", "abcd")));
+ assert_eq!(f("abcd點a"), Ok(("點a", "abcd")));
+
+ fn g(i: &str) -> IResult<&str, &str> {
+ take_till(|c| c != '點')(i)
+ }
+
+ assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g("點abcd"), Ok(("abcd", "點")));
+ assert_eq!(g("點點點a"), Ok(("a", "點點點")));
+ }
+
+ #[test]
+ fn take_utf8() {
+ use crate::bytes::streaming::{take, take_while};
+
+ fn f(i: &str) -> IResult<&str, &str> {
+ take(3_usize)(i)
+ }
+
+ assert_eq!(f(""), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f("ab"), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f("點"), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f("ab點cd"), Ok(("cd", "ab點")));
+ assert_eq!(f("a點bcd"), Ok(("cd", "a點b")));
+ assert_eq!(f("a點b"), Ok(("", "a點b")));
+
+ fn g(i: &str) -> IResult<&str, &str> {
+ take_while(|c| c == '點')(i)
+ }
+
+ assert_eq!(g(""), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g("點abcd"), Ok(("abcd", "點")));
+ assert_eq!(g("點點點a"), Ok(("a", "點點點")));
+ }
+
+ #[test]
+ fn take_while_m_n_utf8() {
+ use crate::bytes::streaming::take_while_m_n;
+
+ fn parser(i: &str) -> IResult<&str, &str> {
+ take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i)
+ }
+ assert_eq!(parser("A!"), Ok(("!", "A")));
+ assert_eq!(parser("😃!"), Ok(("!", "😃")));
+ }
+
+ #[test]
+ fn take_while_m_n_utf8_full_match() {
+ use crate::bytes::streaming::take_while_m_n;
+
+ fn parser(i: &str) -> IResult<&str, &str> {
+ take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i)
+ }
+ assert_eq!(parser("øn"), Ok(("n", "ø")));
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn recognize_take_while() {
+ use crate::bytes::streaming::take_while;
+ use crate::combinator::recognize;
+
+ fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ take_while(AsChar::is_alphanum)(i)
+ }
+ fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ recognize(x)(i)
+ }
+ assert_eq!(x(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
+ println!("X: {:?}", x(&b"ab"[..]));
+ assert_eq!(y(&b"ab."[..]), Ok((&b"."[..], &b"ab"[..])));
+ }
+
+ #[test]
+ fn length_bytes() {
+ use crate::input::Streaming;
+ use crate::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8};
+
+ fn x(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ length_data(le_u8)(i)
+ }
+ assert_eq!(
+ x(Streaming(b"\x02..>>")),
+ Ok((Streaming(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ x(Streaming(b"\x02..")),
+ Ok((Streaming(&[][..]), &b".."[..]))
+ );
+ assert_eq!(x(Streaming(b"\x02.")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(Streaming(b"\x02")), Err(Err::Incomplete(Needed::new(2))));
+
+ fn y(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ let (i, _) = tag("magic")(i)?;
+ length_data(le_u8)(i)
+ }
+ assert_eq!(
+ y(Streaming(b"magic\x02..>>")),
+ Ok((Streaming(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02..")),
+ Ok((Streaming(&[][..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02.")),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02")),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn case_insensitive() {
+ use crate::bytes::streaming::tag_no_case;
+
+ fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ tag_no_case("ABcd")(i)
+ }
+ assert_eq!(test(&b"aBCdefgh"[..]), Ok((&b"efgh"[..], &b"aBCd"[..])));
+ assert_eq!(test(&b"abcdefgh"[..]), Ok((&b"efgh"[..], &b"abcd"[..])));
+ assert_eq!(test(&b"ABCDefgh"[..]), Ok((&b"efgh"[..], &b"ABCD"[..])));
+ assert_eq!(test(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(
+ test(&b"Hello"[..]),
+ Err(Err::Error(error_position!(&b"Hello"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ test(&b"Hel"[..]),
+ Err(Err::Error(error_position!(&b"Hel"[..], ErrorKind::Tag)))
+ );
+
+ fn test2(i: &str) -> IResult<&str, &str> {
+ tag_no_case("ABcd")(i)
+ }
+ assert_eq!(test2("aBCdefgh"), Ok(("efgh", "aBCd")));
+ assert_eq!(test2("abcdefgh"), Ok(("efgh", "abcd")));
+ assert_eq!(test2("ABCDefgh"), Ok(("efgh", "ABCD")));
+ assert_eq!(test2("ab"), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(
+ test2("Hello"),
+ Err(Err::Error(error_position!(&"Hello"[..], ErrorKind::Tag)))
+ );
+ assert_eq!(
+ test2("Hel"),
+ Err(Err::Error(error_position!(&"Hel"[..], ErrorKind::Tag)))
+ );
+ }
+
+ #[test]
+ fn tag_fixed_size_array() {
+ use crate::bytes::streaming::tag;
+
+ fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ tag([0x42])(i)
+ }
+ fn test2(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ tag(&[0x42])(i)
+ }
+ let input = [0x42, 0x00];
+ assert_eq!(test(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
+ assert_eq!(test2(&input), Ok((&b"\x00"[..], &b"\x42"[..])));
+ }
+}
diff --git a/vendor/nom8/src/bytes/tests.rs b/vendor/nom8/src/bytes/tests.rs
new file mode 100644
index 000000000..08562dcc0
--- /dev/null
+++ b/vendor/nom8/src/bytes/tests.rs
@@ -0,0 +1,807 @@
+use super::*;
+
+use crate::error::ErrorKind;
+use crate::input::AsChar;
+use crate::input::Streaming;
+use crate::multi::length_data;
+use crate::sequence::delimited;
+use crate::Err;
+use crate::IResult;
+use crate::Needed;
+#[cfg(feature = "alloc")]
+use crate::{branch::alt, lib::std::string::String, lib::std::vec::Vec};
+
+#[test]
+fn complete_take_while_m_n_utf8_all_matching() {
+ let result: IResult<&str, &str> = super::take_while_m_n(1, 4, |c: char| c.is_alphabetic())("øn");
+ assert_eq!(result, Ok(("", "øn")));
+}
+
+#[test]
+fn complete_take_while_m_n_utf8_all_matching_substring() {
+ let result: IResult<&str, &str> = super::take_while_m_n(1, 1, |c: char| c.is_alphabetic())("øn");
+ assert_eq!(result, Ok(("n", "ø")));
+}
+
+// issue #1336 "escaped hangs if normal parser accepts empty"
+#[test]
+fn complete_escaped_hang() {
+ // issue #1336 "escaped hangs if normal parser accepts empty"
+ fn escaped_string(input: &str) -> IResult<&str, &str> {
+ use crate::bytes::one_of;
+ use crate::character::alpha0;
+ escaped(alpha0, '\\', one_of("n"))(input)
+ }
+
+ escaped_string("7").unwrap();
+ escaped_string("a7").unwrap();
+}
+
+#[test]
+fn complete_escaped_hang_1118() {
+ // issue ##1118 escaped does not work with empty string
+ fn unquote<'a>(input: &'a str) -> IResult<&'a str, &'a str> {
+ use crate::bytes::one_of;
+ use crate::combinator::opt;
+ use crate::sequence::delimited;
+
+ delimited(
+ '"',
+ escaped(opt(none_of(r#"\""#)), '\\', one_of(r#"\"rnt"#)),
+ '"',
+ )(input)
+ }
+
+ assert_eq!(unquote(r#""""#), Ok(("", "")));
+}
+
+#[cfg(feature = "alloc")]
+#[allow(unused_variables)]
+#[test]
+fn complete_escaping() {
+ use crate::bytes::one_of;
+ use crate::character::{alpha1 as alpha, digit1 as digit};
+
+ fn esc(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(alpha, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], &b"abcd"[..])));
+ assert_eq!(esc(&b"ab\\\"cd;"[..]), Ok((&b";"[..], &b"ab\\\"cd"[..])));
+ assert_eq!(esc(&b"\\\"abcd;"[..]), Ok((&b";"[..], &b"\\\"abcd"[..])));
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], &b"\\n"[..])));
+ assert_eq!(esc(&b"ab\\\"12"[..]), Ok((&b"12"[..], &b"ab\\\""[..])));
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(Err::Error(error_position!(
+ &b"AB\\"[..],
+ ErrorKind::Escaped
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(Err::Error(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::Escaped,
+ error_position!(&b"A"[..], ErrorKind::OneOf)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ escaped(digit, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc2(&b"12\\nnn34"[..]), Ok((&b"nn34"[..], &b"12\\n"[..])));
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn complete_escaping_str() {
+ use crate::bytes::one_of;
+ use crate::character::{alpha1 as alpha, digit1 as digit};
+
+ fn esc(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc("abcd;"), Ok((";", "abcd")));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", "ab\\\"cd")));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", "\\\"abcd")));
+ assert_eq!(esc("\\n;"), Ok((";", "\\n")));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", "ab\\\"")));
+ assert_eq!(
+ esc("AB\\"),
+ Err(Err::Error(error_position!("AB\\", ErrorKind::Escaped)))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(Err::Error(error_node_position!(
+ "AB\\A",
+ ErrorKind::Escaped,
+ error_position!("A", ErrorKind::OneOf)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, &str> {
+ escaped(digit, '\\', one_of("\"n\\"))(i)
+ }
+ assert_eq!(esc2("12\\nnn34"), Ok(("nn34", "12\\n")));
+
+ fn esc3(i: &str) -> IResult<&str, &str> {
+ escaped(alpha, '\u{241b}', one_of("\"n"))(i)
+ }
+ assert_eq!(esc3("ab␛ncd;"), Ok((";", "ab␛ncd")));
+}
+
+#[cfg(feature = "alloc")]
+fn to_s(i: Vec<u8>) -> String {
+ String::from_utf8_lossy(&i).into_owned()
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn complete_escape_transform() {
+ use crate::character::alpha1 as alpha;
+
+ fn esc(i: &[u8]) -> IResult<&[u8], String> {
+ escaped_transform(
+ alpha,
+ '\\',
+ alt((
+ tag("\\").value(&b"\\"[..]),
+ tag("\"").value(&b"\""[..]),
+ tag("n").value(&b"\n"[..]),
+ )),
+ )
+ .map(to_s)
+ .parse(i)
+ }
+
+ assert_eq!(esc(&b"abcd;"[..]), Ok((&b";"[..], String::from("abcd"))));
+ assert_eq!(
+ esc(&b"ab\\\"cd;"[..]),
+ Ok((&b";"[..], String::from("ab\"cd")))
+ );
+ assert_eq!(
+ esc(&b"\\\"abcd;"[..]),
+ Ok((&b";"[..], String::from("\"abcd")))
+ );
+ assert_eq!(esc(&b"\\n;"[..]), Ok((&b";"[..], String::from("\n"))));
+ assert_eq!(
+ esc(&b"ab\\\"12"[..]),
+ Ok((&b"12"[..], String::from("ab\"")))
+ );
+ assert_eq!(
+ esc(&b"AB\\"[..]),
+ Err(Err::Error(error_position!(
+ &b"\\"[..],
+ ErrorKind::EscapedTransform
+ )))
+ );
+ assert_eq!(
+ esc(&b"AB\\A"[..]),
+ Err(Err::Error(error_node_position!(
+ &b"AB\\A"[..],
+ ErrorKind::EscapedTransform,
+ error_position!(&b"A"[..], ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &[u8]) -> IResult<&[u8], String> {
+ escaped_transform(
+ alpha,
+ '&',
+ alt((
+ tag("egrave;").value("è".as_bytes()),
+ tag("agrave;").value("à".as_bytes()),
+ )),
+ )
+ .map(to_s)
+ .parse(i)
+ }
+ assert_eq!(
+ esc2(&b"ab&egrave;DEF;"[..]),
+ Ok((&b";"[..], String::from("abèDEF")))
+ );
+ assert_eq!(
+ esc2(&b"ab&egrave;D&agrave;EF;"[..]),
+ Ok((&b";"[..], String::from("abèDàEF")))
+ );
+}
+
+#[cfg(feature = "std")]
+#[test]
+fn complete_escape_transform_str() {
+ use crate::character::alpha1 as alpha;
+
+ fn esc(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '\\',
+ alt((
+ tag("\\").value("\\"),
+ tag("\"").value("\""),
+ tag("n").value("\n"),
+ )),
+ )(i)
+ }
+
+ assert_eq!(esc("abcd;"), Ok((";", String::from("abcd"))));
+ assert_eq!(esc("ab\\\"cd;"), Ok((";", String::from("ab\"cd"))));
+ assert_eq!(esc("\\\"abcd;"), Ok((";", String::from("\"abcd"))));
+ assert_eq!(esc("\\n;"), Ok((";", String::from("\n"))));
+ assert_eq!(esc("ab\\\"12"), Ok(("12", String::from("ab\""))));
+ assert_eq!(
+ esc("AB\\"),
+ Err(Err::Error(error_position!(
+ "\\",
+ ErrorKind::EscapedTransform
+ )))
+ );
+ assert_eq!(
+ esc("AB\\A"),
+ Err(Err::Error(error_node_position!(
+ "AB\\A",
+ ErrorKind::EscapedTransform,
+ error_position!("A", ErrorKind::Tag)
+ )))
+ );
+
+ fn esc2(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '&',
+ alt((tag("egrave;").value("è"), tag("agrave;").value("à"))),
+ )(i)
+ }
+ assert_eq!(esc2("ab&egrave;DEF;"), Ok((";", String::from("abèDEF"))));
+ assert_eq!(
+ esc2("ab&egrave;D&agrave;EF;"),
+ Ok((";", String::from("abèDàEF")))
+ );
+
+ fn esc3(i: &str) -> IResult<&str, String> {
+ escaped_transform(
+ alpha,
+ '␛',
+ alt((tag("0").value("\0"), tag("n").value("\n"))),
+ )(i)
+ }
+ assert_eq!(esc3("a␛0bc␛n"), Ok(("", String::from("a\0bc\n"))));
+}
+
+#[test]
+fn streaming_any_str() {
+ use super::any;
+ assert_eq!(
+ any::<_, (Streaming<&str>, ErrorKind), true>(Streaming("Ә")),
+ Ok((Streaming(""), 'Ә'))
+ );
+}
+
+#[test]
+fn streaming_one_of_test() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u8> {
+ one_of("ab")(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(f(Streaming(a)), Ok((Streaming(&b"bcd"[..]), b'a')));
+
+ let b = &b"cde"[..];
+ assert_eq!(
+ f(Streaming(b)),
+ Err(Err::Error(error_position!(Streaming(b), ErrorKind::OneOf)))
+ );
+
+ fn utf8(i: Streaming<&str>) -> IResult<Streaming<&str>, char> {
+ one_of("+\u{FF0B}")(i)
+ }
+
+ assert!(utf8(Streaming("+")).is_ok());
+ assert!(utf8(Streaming("\u{FF0B}")).is_ok());
+}
+
+#[test]
+fn char_byteslice() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u8> {
+ one_of('c')(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ f(Streaming(a)),
+ Err(Err::Error(error_position!(Streaming(a), ErrorKind::OneOf)))
+ );
+
+ let b = &b"cde"[..];
+ assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c')));
+}
+
+#[test]
+fn char_str() {
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, char> {
+ one_of('c')(i)
+ }
+
+ let a = &"abcd"[..];
+ assert_eq!(
+ f(Streaming(a)),
+ Err(Err::Error(error_position!(Streaming(a), ErrorKind::OneOf)))
+ );
+
+ let b = &"cde"[..];
+ assert_eq!(f(Streaming(b)), Ok((Streaming(&"de"[..]), 'c')));
+}
+
+#[test]
+fn streaming_none_of_test() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u8> {
+ none_of("ab")(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(
+ f(Streaming(a)),
+ Err(Err::Error(error_position!(Streaming(a), ErrorKind::NoneOf)))
+ );
+
+ let b = &b"cde"[..];
+ assert_eq!(f(Streaming(b)), Ok((Streaming(&b"de"[..]), b'c')));
+}
+
+#[test]
+fn streaming_is_a() {
+ fn a_or_b(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_while1("ab")(i)
+ }
+
+ let a = Streaming(&b"abcd"[..]);
+ assert_eq!(a_or_b(a), Ok((Streaming(&b"cd"[..]), &b"ab"[..])));
+
+ let b = Streaming(&b"bcde"[..]);
+ assert_eq!(a_or_b(b), Ok((Streaming(&b"cde"[..]), &b"b"[..])));
+
+ let c = Streaming(&b"cdef"[..]);
+ assert_eq!(
+ a_or_b(c),
+ Err(Err::Error(error_position!(c, ErrorKind::TakeWhile1)))
+ );
+
+ let d = Streaming(&b"bacdef"[..]);
+ assert_eq!(a_or_b(d), Ok((Streaming(&b"cdef"[..]), &b"ba"[..])));
+}
+
+#[test]
+fn streaming_is_not() {
+ fn a_or_b(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_till1("ab")(i)
+ }
+
+ let a = Streaming(&b"cdab"[..]);
+ assert_eq!(a_or_b(a), Ok((Streaming(&b"ab"[..]), &b"cd"[..])));
+
+ let b = Streaming(&b"cbde"[..]);
+ assert_eq!(a_or_b(b), Ok((Streaming(&b"bde"[..]), &b"c"[..])));
+
+ let c = Streaming(&b"abab"[..]);
+ assert_eq!(
+ a_or_b(c),
+ Err(Err::Error(error_position!(c, ErrorKind::TakeTill1)))
+ );
+
+ let d = Streaming(&b"cdefba"[..]);
+ assert_eq!(a_or_b(d), Ok((Streaming(&b"ba"[..]), &b"cdef"[..])));
+
+ let e = Streaming(&b"e"[..]);
+ assert_eq!(a_or_b(e), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn streaming_take_until_incomplete() {
+ fn y(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_until("end")(i)
+ }
+ assert_eq!(
+ y(Streaming(&b"nd"[..])),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ y(Streaming(&b"123"[..])),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ assert_eq!(
+ y(Streaming(&b"123en"[..])),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+}
+
+#[test]
+fn streaming_take_until_incomplete_s() {
+ fn ys(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_until("end")(i)
+ }
+ assert_eq!(
+ ys(Streaming("123en")),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+}
+
+#[test]
+fn streaming_recognize() {
+ use crate::character::{
+ alpha1 as alpha, alphanumeric1 as alphanumeric, digit1 as digit, hex_digit1 as hex_digit,
+ multispace1 as multispace, oct_digit1 as oct_digit, space1 as space,
+ };
+
+ fn x(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ delimited(tag("<!--"), take(5_usize), tag("-->"))
+ .recognize()
+ .parse(i)
+ }
+ let r = x(Streaming(&b"<!-- abc --> aaa"[..]));
+ assert_eq!(r, Ok((Streaming(&b" aaa"[..]), &b"<!-- abc -->"[..])));
+
+ let semicolon = &b";"[..];
+
+ fn ya(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ alpha.recognize().parse(i)
+ }
+ let ra = ya(Streaming(&b"abc;"[..]));
+ assert_eq!(ra, Ok((Streaming(semicolon), &b"abc"[..])));
+
+ fn yd(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ digit.recognize().parse(i)
+ }
+ let rd = yd(Streaming(&b"123;"[..]));
+ assert_eq!(rd, Ok((Streaming(semicolon), &b"123"[..])));
+
+ fn yhd(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ hex_digit.recognize().parse(i)
+ }
+ let rhd = yhd(Streaming(&b"123abcDEF;"[..]));
+ assert_eq!(rhd, Ok((Streaming(semicolon), &b"123abcDEF"[..])));
+
+ fn yod(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ oct_digit.recognize().parse(i)
+ }
+ let rod = yod(Streaming(&b"1234567;"[..]));
+ assert_eq!(rod, Ok((Streaming(semicolon), &b"1234567"[..])));
+
+ fn yan(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ alphanumeric.recognize().parse(i)
+ }
+ let ran = yan(Streaming(&b"123abc;"[..]));
+ assert_eq!(ran, Ok((Streaming(semicolon), &b"123abc"[..])));
+
+ fn ys(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ space.recognize().parse(i)
+ }
+ let rs = ys(Streaming(&b" \t;"[..]));
+ assert_eq!(rs, Ok((Streaming(semicolon), &b" \t"[..])));
+
+ fn yms(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ multispace.recognize().parse(i)
+ }
+ let rms = yms(Streaming(&b" \t\r\n;"[..]));
+ assert_eq!(rms, Ok((Streaming(semicolon), &b" \t\r\n"[..])));
+}
+
+#[test]
+fn streaming_take_while() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_while(AsChar::is_alpha)(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"abcd123"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(b)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(c)), Ok((Streaming(d), b)));
+ assert_eq!(f(Streaming(d)), Ok((Streaming(d), a)));
+}
+
+#[test]
+fn streaming_take_while1() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_while1(AsChar::is_alpha)(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"abcd123"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(b)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(c)), Ok((Streaming(&b"123"[..]), b)));
+ assert_eq!(
+ f(Streaming(d)),
+ Err(Err::Error(error_position!(
+ Streaming(d),
+ ErrorKind::TakeWhile1
+ )))
+ );
+}
+
+#[test]
+fn streaming_take_while_m_n() {
+ fn x(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_while_m_n(2, 4, AsChar::is_alpha)(i)
+ }
+ let a = &b""[..];
+ let b = &b"a"[..];
+ let c = &b"abc"[..];
+ let d = &b"abc123"[..];
+ let e = &b"abcde"[..];
+ let f = &b"123"[..];
+
+ assert_eq!(x(Streaming(a)), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(x(Streaming(b)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(Streaming(c)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(Streaming(d)), Ok((Streaming(&b"123"[..]), c)));
+ assert_eq!(x(Streaming(e)), Ok((Streaming(&b"e"[..]), &b"abcd"[..])));
+ assert_eq!(
+ x(Streaming(f)),
+ Err(Err::Error(error_position!(
+ Streaming(f),
+ ErrorKind::TakeWhileMN
+ )))
+ );
+}
+
+#[test]
+fn streaming_take_till() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_till(AsChar::is_alpha)(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"123abcd"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(b)), Ok((Streaming(&b"abcd"[..]), &b""[..])));
+ assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..])));
+ assert_eq!(f(Streaming(d)), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn streaming_take_till1() {
+ fn f(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_till1(AsChar::is_alpha)(i)
+ }
+ let a = &b""[..];
+ let b = &b"abcd"[..];
+ let c = &b"123abcd"[..];
+ let d = &b"123"[..];
+
+ assert_eq!(f(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(
+ f(Streaming(b)),
+ Err(Err::Error(error_position!(
+ Streaming(b),
+ ErrorKind::TakeTill1
+ )))
+ );
+ assert_eq!(f(Streaming(c)), Ok((Streaming(&b"abcd"[..]), &b"123"[..])));
+ assert_eq!(f(Streaming(d)), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+fn streaming_take_while_utf8() {
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while(|c| c != '點')(i)
+ }
+
+ assert_eq!(f(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming("abcd")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd")));
+ assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd")));
+
+ fn g(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while(|c| c == '點')(i)
+ }
+
+ assert_eq!(g(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點")));
+ assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點")));
+}
+
+#[test]
+fn streaming_take_till_utf8() {
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_till(|c| c == '點')(i)
+ }
+
+ assert_eq!(f(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming("abcd")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming("abcd點")), Ok((Streaming("點"), "abcd")));
+ assert_eq!(f(Streaming("abcd點a")), Ok((Streaming("點a"), "abcd")));
+
+ fn g(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_till(|c| c != '點')(i)
+ }
+
+ assert_eq!(g(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點")));
+ assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點")));
+}
+
+#[test]
+fn streaming_take_utf8() {
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take(3_usize)(i)
+ }
+
+ assert_eq!(f(Streaming("")), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f(Streaming("ab")), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f(Streaming("點")), Err(Err::Incomplete(Needed::Unknown)));
+ assert_eq!(f(Streaming("ab點cd")), Ok((Streaming("cd"), "ab點")));
+ assert_eq!(f(Streaming("a點bcd")), Ok((Streaming("cd"), "a點b")));
+ assert_eq!(f(Streaming("a點b")), Ok((Streaming(""), "a點b")));
+
+ fn g(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while(|c| c == '點')(i)
+ }
+
+ assert_eq!(g(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(g(Streaming("點abcd")), Ok((Streaming("abcd"), "點")));
+ assert_eq!(g(Streaming("點點點a")), Ok((Streaming("a"), "點點點")));
+}
+
+#[test]
+fn streaming_take_while_m_n_utf8() {
+ fn parser(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while_m_n(1, 1, |c| c == 'A' || c == '😃')(i)
+ }
+ assert_eq!(parser(Streaming("A!")), Ok((Streaming("!"), "A")));
+ assert_eq!(parser(Streaming("😃!")), Ok((Streaming("!"), "😃")));
+}
+
+#[test]
+fn streaming_take_while_m_n_utf8_full_match() {
+ fn parser(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while_m_n(1, 1, |c: char| c.is_alphabetic())(i)
+ }
+ assert_eq!(parser(Streaming("øn")), Ok((Streaming("n"), "ø")));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn streaming_recognize_take_while() {
+ fn x(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_while(AsChar::is_alphanum)(i)
+ }
+ fn y(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ x.recognize().parse(i)
+ }
+ assert_eq!(
+ x(Streaming(&b"ab."[..])),
+ Ok((Streaming(&b"."[..]), &b"ab"[..]))
+ );
+ assert_eq!(
+ y(Streaming(&b"ab."[..])),
+ Ok((Streaming(&b"."[..]), &b"ab"[..]))
+ );
+}
+
+#[test]
+fn streaming_length_bytes() {
+ use crate::number::le_u8;
+
+ fn x(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ length_data(le_u8)(i)
+ }
+ assert_eq!(
+ x(Streaming(b"\x02..>>")),
+ Ok((Streaming(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ x(Streaming(b"\x02..")),
+ Ok((Streaming(&[][..]), &b".."[..]))
+ );
+ assert_eq!(x(Streaming(b"\x02.")), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(x(Streaming(b"\x02")), Err(Err::Incomplete(Needed::new(2))));
+
+ fn y(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ let (i, _) = tag("magic")(i)?;
+ length_data(le_u8)(i)
+ }
+ assert_eq!(
+ y(Streaming(b"magic\x02..>>")),
+ Ok((Streaming(&b">>"[..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02..")),
+ Ok((Streaming(&[][..]), &b".."[..]))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02.")),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ y(Streaming(b"magic\x02")),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn streaming_case_insensitive() {
+ fn test(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ tag_no_case("ABcd")(i)
+ }
+ assert_eq!(
+ test(Streaming(&b"aBCdefgh"[..])),
+ Ok((Streaming(&b"efgh"[..]), &b"aBCd"[..]))
+ );
+ assert_eq!(
+ test(Streaming(&b"abcdefgh"[..])),
+ Ok((Streaming(&b"efgh"[..]), &b"abcd"[..]))
+ );
+ assert_eq!(
+ test(Streaming(&b"ABCDefgh"[..])),
+ Ok((Streaming(&b"efgh"[..]), &b"ABCD"[..]))
+ );
+ assert_eq!(
+ test(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ test(Streaming(&b"Hello"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"Hello"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ test(Streaming(&b"Hel"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"Hel"[..]),
+ ErrorKind::Tag
+ )))
+ );
+
+ fn test2(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ tag_no_case("ABcd")(i)
+ }
+ assert_eq!(
+ test2(Streaming("aBCdefgh")),
+ Ok((Streaming("efgh"), "aBCd"))
+ );
+ assert_eq!(
+ test2(Streaming("abcdefgh")),
+ Ok((Streaming("efgh"), "abcd"))
+ );
+ assert_eq!(
+ test2(Streaming("ABCDefgh")),
+ Ok((Streaming("efgh"), "ABCD"))
+ );
+ assert_eq!(test2(Streaming("ab")), Err(Err::Incomplete(Needed::new(2))));
+ assert_eq!(
+ test2(Streaming("Hello")),
+ Err(Err::Error(error_position!(
+ Streaming("Hello"),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ test2(Streaming("Hel")),
+ Err(Err::Error(error_position!(
+ Streaming("Hel"),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn streaming_tag_fixed_size_array() {
+ fn test(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ tag([0x42])(i)
+ }
+ fn test2(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ tag(&[0x42])(i)
+ }
+ let input = Streaming(&[0x42, 0x00][..]);
+ assert_eq!(test(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..])));
+ assert_eq!(test2(input), Ok((Streaming(&b"\x00"[..]), &b"\x42"[..])));
+}
diff --git a/vendor/nom8/src/character/complete.rs b/vendor/nom8/src/character/complete.rs
new file mode 100644
index 000000000..29cfd0079
--- /dev/null
+++ b/vendor/nom8/src/character/complete.rs
@@ -0,0 +1,1366 @@
+//! Character specific parsers and combinators, complete input version.
+//!
+//! Functions recognizing specific characters.
+
+#![allow(deprecated)]
+
+use crate::branch::alt;
+use crate::combinator::opt;
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::{
+ AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, IntoOutput, Slice,
+};
+use crate::input::{Compare, CompareResult};
+use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
+use crate::IntoOutputIResult as _;
+use crate::{Err, IResult};
+
+/// Recognizes one character.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{ErrorKind, Error}, IResult};
+/// # use nom8::character::complete::char;
+/// fn parser(i: &str) -> IResult<&str, char> {
+/// char('a')(i)
+/// }
+/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser(" abc"), Err(Err::Error(Error::new(" abc", ErrorKind::Char))));
+/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::one_of`")]
+pub fn char<I, Error: ParseError<I>>(c: char) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+{
+ move |i: I| char_internal(i, c)
+}
+
+pub(crate) fn char_internal<I, Error: ParseError<I>>(i: I, c: char) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+{
+ match (i).iter_elements().next().map(|t| {
+ let b = t.as_char() == c;
+ (&c, b)
+ }) {
+ Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())),
+ _ => Err(Err::Error(Error::from_char(i, c))),
+ }
+}
+
+/// Recognizes one character and checks that it satisfies a predicate
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{ErrorKind, Error}, Needed, IResult};
+/// # use nom8::character::complete::satisfy;
+/// fn parser(i: &str) -> IResult<&str, char> {
+/// satisfy(|c| c == 'a' || c == 'b')(i)
+/// }
+/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Satisfy))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::one_of`")]
+pub fn satisfy<F, I, Error: ParseError<I>>(cond: F) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+ F: Fn(char) -> bool,
+{
+ move |i: I| satisfy_internal(i, &cond)
+}
+
+pub(crate) fn satisfy_internal<F, I, Error: ParseError<I>>(
+ i: I,
+ cond: &F,
+) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+ F: Fn(char) -> bool,
+{
+ match (i).iter_elements().next().map(|t| {
+ let c = t.as_char();
+ let b = cond(c);
+ (c, b)
+ }) {
+ Some((c, true)) => Ok((i.slice(c.len()..), c)),
+ _ => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))),
+ }
+}
+
+/// Recognizes one of the provided characters.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind};
+/// # use nom8::character::complete::one_of;
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("abc")("b"), Ok(("", 'b')));
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf))));
+/// assert_eq!(one_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::OneOf))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::one_of`")]
+pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar + Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| crate::bytes::complete::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes a character that is not in the provided characters.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind};
+/// # use nom8::character::complete::none_of;
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("abc")("z"), Ok(("", 'z')));
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf))));
+/// assert_eq!(none_of::<_, _, (&str, ErrorKind)>("a")(""), Err(Err::Error(("", ErrorKind::NoneOf))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::none_of`][crate::bytes::none_of]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::none_of`")]
+pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputLength + InputIter,
+ <I as InputIter>::Item: AsChar + Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| crate::bytes::complete::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes the string "\r\n".
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult};
+/// # use nom8::character::complete::crlf;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// crlf(input)
+/// }
+///
+/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::crlf`][crate::character::crlf]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::crlf`")]
+pub fn crlf<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>>,
+ T: InputIter,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ match input.compare("\r\n") {
+ //FIXME: is this the right index?
+ CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
+ _ => {
+ let e: ErrorKind = ErrorKind::CrLf;
+ Err(Err::Error(E::from_error_kind(input, e)))
+ }
+ }
+}
+
+//FIXME: there's still an incomplete
+/// Recognizes a string of any char except '\r\n' or '\n'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::not_line_ending;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// not_line_ending(input)
+/// }
+///
+/// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab")));
+/// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab")));
+/// assert_eq!(parser("abc"), Ok(("", "abc")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag })));
+/// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag })));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::not_line_ending`][crate::character::not_line_ending]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::not_line_ending`"
+)]
+pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+ <T as InputIter>::Item: AsChar,
+ <T as InputIter>::Item: AsChar,
+{
+ match input.position(|item| {
+ let c = item.as_char();
+ c == '\r' || c == '\n'
+ }) {
+ None => Ok((input.slice(input.input_len()..), input)).into_output(),
+ Some(index) => {
+ let mut it = input.slice(index..).iter_elements();
+ let nth = it.next().unwrap().as_char();
+ if nth == '\r' {
+ let sliced = input.slice(index..);
+ let comp = sliced.compare("\r\n");
+ match comp {
+ //FIXME: calculate the right index
+ CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))).into_output(),
+ _ => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(E::from_error_kind(input, e)))
+ }
+ }
+ } else {
+ Ok((input.slice(index..), input.slice(..index))).into_output()
+ }
+ }
+ }
+}
+
+/// Recognizes an end of line (both '\n' and '\r\n').
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::line_ending;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// line_ending(input)
+/// }
+///
+/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::line_ending`][crate::character::line_ending]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::line_ending`")]
+pub fn line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ match input.compare("\n") {
+ CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))).into_output(),
+ CompareResult::Incomplete => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))),
+ CompareResult::Error => {
+ match input.compare("\r\n") {
+ //FIXME: is this the right index?
+ CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
+ _ => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))),
+ }
+ }
+ }
+}
+
+/// Matches a newline character '\n'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::newline;
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// newline(input)
+/// }
+///
+/// assert_eq!(parser("\nc"), Ok(("c", '\n')));
+/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::newline`][crate::character::newline]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::newline`")]
+pub fn newline<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+{
+ char('\n')(input)
+}
+
+/// Matches a tab character '\t'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::tab;
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// tab(input)
+/// }
+///
+/// assert_eq!(parser("\tc"), Ok(("c", '\t')));
+/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::tab`][crate::character::tab]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::tab`")]
+pub fn tab<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+{
+ char('\t')(input)
+}
+
+/// Matches one byte as a character. Note that the input type will
+/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{character::complete::anychar, Err, error::{Error, ErrorKind}, IResult};
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// anychar(input)
+/// }
+///
+/// assert_eq!(parser("abc"), Ok(("bc",'a')));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::any`][crate::bytes::any]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::bytes::any`")]
+pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E>
+where
+ T: InputIter + InputLength + Slice<RangeFrom<usize>>,
+ <T as InputIter>::Item: AsChar,
+{
+ crate::bytes::complete::any(input).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non
+/// alphabetic character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::alpha0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alpha0(input)
+/// }
+///
+/// assert_eq!(parser("ab1c"), Ok(("1c", "ab")));
+/// assert_eq!(parser("1c"), Ok(("1c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha0`][crate::character::alpha0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::alpha0`")]
+pub fn alpha0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_complete(|item| !item.is_alpha())
+ .into_output()
+}
+
+/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non alphabetic character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::alpha1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alpha1(input)
+/// }
+///
+/// assert_eq!(parser("aB1c"), Ok(("1c", "aB")));
+/// assert_eq!(parser("1c"), Err(Err::Error(Error::new("1c", ErrorKind::Alpha))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Alpha))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha1`][crate::character::alpha1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::alpha1`")]
+pub fn alpha1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_complete(|item| !item.is_alpha(), ErrorKind::Alpha)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII numerical characters: 0-9
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// digit0(input)
+/// }
+///
+/// assert_eq!(parser("21c"), Ok(("c", "21")));
+/// assert_eq!(parser("21"), Ok(("", "21")));
+/// assert_eq!(parser("a21c"), Ok(("a21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::digit0`][crate::character::digit0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::digit0`")]
+pub fn digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_complete(|item| !item.is_dec_digit())
+ .into_output()
+}
+
+/// Recognizes one or more ASCII numerical characters: 0-9
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// digit1(input)
+/// }
+///
+/// assert_eq!(parser("21c"), Ok(("c", "21")));
+/// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit))));
+/// ```
+///
+/// ## Parsing an integer
+/// You can use `digit1` in combination with [`map_res`] to parse an integer:
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::combinator::map_res;
+/// # use nom8::character::complete::digit1;
+/// fn parser(input: &str) -> IResult<&str, u32> {
+/// map_res(digit1, str::parse)(input)
+/// }
+///
+/// assert_eq!(parser("416"), Ok(("", 416)));
+/// assert_eq!(parser("12b"), Ok(("b", 12)));
+/// assert!(parser("b").is_err());
+/// ```
+///
+/// [`map_res`]: crate::combinator::map_res
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::digit1`][crate::character::digit1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::digit1`")]
+pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_complete(|item| !item.is_dec_digit(), ErrorKind::Digit)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::hex_digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// hex_digit0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit0`][crate::character::hex_digit0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::hex_digit0`")]
+pub fn hex_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_complete(|item| !item.is_hex_digit())
+ .into_output()
+}
+/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non hexadecimal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::hex_digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// hex_digit1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::HexDigit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::HexDigit))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit1`][crate::character::hex_digit1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::hex_digit1`")]
+pub fn hex_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_complete(|item| !item.is_hex_digit(), ErrorKind::HexDigit)
+ .into_output()
+}
+
+/// Recognizes zero or more octal characters: 0-7
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non octal
+/// digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::oct_digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// oct_digit0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit0`][crate::character::oct_digit0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::oct_digit0`")]
+pub fn oct_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_complete(|item| !item.is_oct_digit())
+ .into_output()
+}
+
+/// Recognizes one or more octal characters: 0-7
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non octal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::oct_digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// oct_digit1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::OctDigit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OctDigit))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit1`][crate::character::oct_digit1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::oct_digit1`")]
+pub fn oct_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_complete(|item| !item.is_oct_digit(), ErrorKind::OctDigit)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non
+/// alphanumerical character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::alphanumeric0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alphanumeric0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(parser("&Z21c"), Ok(("&Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric0`][crate::character::alphanumeric0]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alphanumeric0`"
+)]
+pub fn alphanumeric0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_complete(|item| !item.is_alphanum())
+ .into_output()
+}
+
+/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non alphanumerical character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::alphanumeric1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alphanumeric1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(parser("&H2"), Err(Err::Error(Error::new("&H2", ErrorKind::AlphaNumeric))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::AlphaNumeric))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric1`][crate::character::alphanumeric1]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alphanumeric1`"
+)]
+pub fn alphanumeric1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_complete(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric)
+ .into_output()
+}
+
+/// Recognizes zero or more spaces and tabs.
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non space
+/// character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::space0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// space0(input)
+/// }
+///
+/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::space0`][crate::character::space0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::space0`")]
+pub fn space0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position_complete(|item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t')
+ })
+ .into_output()
+}
+
+/// Recognizes one or more spaces and tabs.
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::space1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// space1(input)
+/// }
+///
+/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::Space))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Space))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::space1`][crate::character::space1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::space1`")]
+pub fn space1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position1_complete(
+ |item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t')
+ },
+ ErrorKind::Space,
+ )
+ .into_output()
+}
+
+/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Complete version*: will return the whole input if no terminating token is found (a non space
+/// character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::complete::multispace0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// multispace0(input)
+/// }
+///
+/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace0`][crate::character::multispace0]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::multispace0`")]
+pub fn multispace0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position_complete(|item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ })
+ .into_output()
+}
+
+/// Recognizes one or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Complete version*: will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::complete::multispace1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// multispace1(input)
+/// }
+///
+/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::MultiSpace))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::MultiSpace))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace1`][crate::character::multispace1]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::multispace1`")]
+pub fn multispace1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position1_complete(
+ |item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ },
+ ErrorKind::MultiSpace,
+ )
+ .into_output()
+}
+
+pub(crate) fn sign<T, E: ParseError<T>>(input: T) -> IResult<T, bool, E>
+where
+ T: Clone + InputTake,
+ T: IntoOutput,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ use crate::bytes::complete::tag;
+ use crate::combinator::value;
+
+ let (i, opt_sign) = opt(alt((
+ value(false, tag(&b"-"[..])),
+ value(true, tag(&b"+"[..])),
+ )))(input)?;
+ let sign = opt_sign.unwrap_or(true);
+
+ Ok((i, sign))
+}
+
+#[doc(hidden)]
+macro_rules! ints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputTake + Clone,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: for <'a> Compare<&'a[u8]>,
+ {
+ let (i, sign) = sign(input.clone())?;
+
+ if i.input_len() == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
+ }
+
+ let mut value: $t = 0;
+ if sign {
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+ } else {
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+ }
+
+ Ok((i.slice(i.input_len()..), value))
+ }
+ )+
+ }
+}
+
+ints! { i8 i16 i32 i64 i128 }
+
+#[doc(hidden)]
+macro_rules! uints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ {
+ let i = input;
+
+ if i.input_len() == 0 {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit)));
+ }
+
+ let mut value: $t = 0;
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+
+ Ok((i.slice(i.input_len()..), value))
+ }
+ )+
+ }
+}
+
+uints! { u8 u16 u32 u64 u128 }
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::input::ParseTo;
+ use crate::Err;
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn character() {
+ let empty: &[u8] = b"";
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::Size(1))));
+ assert_parse!(alpha1(a), Ok((empty, a)));
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..])));
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind)>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c)));
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(d),
+ Ok(("zé12".as_bytes(), &b"a"[..]))
+ );
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e)));
+ assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..])));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let empty = "";
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Ok((empty, a)));
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..])));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..])));
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(c), Ok((empty, c)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..])));
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1::<_, (_, ErrorKind)>(b), Ok((empty, b)));
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(c), Ok((empty, c)));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az")));
+ assert_eq!(space1::<_, (_, ErrorKind)>(e), Ok((empty, e)));
+ }
+
+ use crate::input::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, (_, ErrorKind)>(a) {
+ Ok((i, _)) => {
+ assert_eq!(a.offset(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, (_, ErrorKind)>(b) {
+ Ok((i, _)) => {
+ assert_eq!(b.offset(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, (_, ErrorKind)>(c) {
+ Ok((i, _)) => {
+ assert_eq!(c.offset(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, (_, ErrorKind)>(d) {
+ Ok((i, _)) => {
+ assert_eq!(d.offset(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, (_, ErrorKind)>(e) {
+ Ok((i, _)) => {
+ assert_eq!(e.offset(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, (_, ErrorKind)>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, (_, ErrorKind)>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(a),
+ Ok((&b"\nefgh"[..], &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(b),
+ Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(c),
+ Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(d),
+ Ok((&[][..], &d[..]))
+ );
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ /*
+ let a: &str = "ab12cd\nefgh";
+ assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..])));
+
+ let b: &str = "ab12cd\nefgh\nijkl";
+ assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..])));
+
+ let c: &str = "ab12cd\r\nefgh\nijkl";
+ assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..])));
+
+ let d = "βèƒôřè\nÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
+
+ let e = "βèƒôřè\r\nÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
+ */
+
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag))));
+
+ let g2: &str = "ab12cd";
+ assert_eq!(not_line_ending::<_, (_, ErrorKind)>(g2), Ok(("", g2)));
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::OctDigit)))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ use crate::sequence::pair;
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
+ }
+
+ #[test]
+ fn full_line_unix() {
+ use crate::sequence::pair;
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ crlf(&b"\r"[..]),
+ Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ crlf(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(crlf("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ crlf("\r"),
+ Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ crlf("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..])));
+ assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ line_ending(&b"\r"[..]),
+ Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ line_ending(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(line_ending("\na"), Ok(("a", "\n")));
+ assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ line_ending("\r"),
+ Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ line_ending("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ fn digit_to_i16(input: &str) -> IResult<&str, i16> {
+ let i = input;
+ let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?;
+ let sign = match opt_sign {
+ Some('+') => true,
+ Some('-') => false,
+ _ => true,
+ };
+
+ let (i, s) = match digit1::<_, crate::error::Error<_>>(i) {
+ Ok((i, s)) => (i, s),
+ Err(_) => {
+ return Err(Err::Error(crate::error::Error::from_error_kind(
+ input,
+ ErrorKind::Digit,
+ )))
+ }
+ };
+
+ match s.parse_to() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ fn digit_to_u32(i: &str) -> IResult<&str, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(&s);
+ let res2 = i16(s.as_str());
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(&s);
+ let res2 = u32(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+}
diff --git a/vendor/nom8/src/character/mod.rs b/vendor/nom8/src/character/mod.rs
new file mode 100644
index 000000000..daba1f94e
--- /dev/null
+++ b/vendor/nom8/src/character/mod.rs
@@ -0,0 +1,1217 @@
+//! Character specific parsers and combinators
+//!
+//! Functions recognizing specific characters
+
+#![allow(deprecated)] // will just become `pub(crate)` later
+
+pub mod complete;
+pub mod streaming;
+#[cfg(test)]
+mod tests;
+
+use crate::error::ParseError;
+use crate::input::Compare;
+use crate::input::{
+ AsBytes, AsChar, InputIsStreaming, InputIter, InputLength, InputTake, InputTakeAtPosition,
+ IntoOutput, Offset, ParseTo, Slice,
+};
+use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
+use crate::IResult;
+
+/// Recognizes the string "\r\n".
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult};
+/// # use nom8::character::crlf;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// crlf(input)
+/// }
+///
+/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::crlf;
+/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Ok((Streaming("c"), "\r\n")));
+/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Err(Err::Error((Streaming("ab\r\nc"), ErrorKind::CrLf))));
+/// assert_eq!(crlf::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn crlf<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ if STREAMING {
+ streaming::crlf(input)
+ } else {
+ complete::crlf(input)
+ }
+}
+
+/// Recognizes a string of any char except '\r\n' or '\n'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::not_line_ending;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// not_line_ending(input)
+/// }
+///
+/// assert_eq!(parser("ab\r\nc"), Ok(("\r\nc", "ab")));
+/// assert_eq!(parser("ab\nc"), Ok(("\nc", "ab")));
+/// assert_eq!(parser("abc"), Ok(("", "abc")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// assert_eq!(parser("a\rb\nc"), Err(Err::Error(Error { input: "a\rb\nc", code: ErrorKind::Tag })));
+/// assert_eq!(parser("a\rbc"), Err(Err::Error(Error { input: "a\rbc", code: ErrorKind::Tag })));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::not_line_ending;
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Ok((Streaming("\r\nc"), "ab")));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("abc")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("a\rb\nc")), Err(Err::Error((Streaming("a\rb\nc"), ErrorKind::Tag ))));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind), true>(Streaming("a\rbc")), Err(Err::Error((Streaming("a\rbc"), ErrorKind::Tag ))));
+/// ```
+#[inline(always)]
+pub fn not_line_ending<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+ <T as InputIter>::Item: AsChar,
+ <T as InputIter>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::not_line_ending(input)
+ } else {
+ complete::not_line_ending(input)
+ }
+}
+
+/// Recognizes an end of line (both '\n' and '\r\n').
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::line_ending;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// line_ending(input)
+/// }
+///
+/// assert_eq!(parser("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(parser("ab\r\nc"), Err(Err::Error(Error::new("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::CrLf))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::line_ending;
+/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Ok((Streaming("c"), "\r\n")));
+/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("ab\r\nc")), Err(Err::Error((Streaming("ab\r\nc"), ErrorKind::CrLf))));
+/// assert_eq!(line_ending::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn line_ending<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ if STREAMING {
+ streaming::line_ending(input)
+ } else {
+ complete::line_ending(input)
+ }
+}
+
+/// Matches a newline character '\n'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::newline;
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// newline(input)
+/// }
+///
+/// assert_eq!(parser("\nc"), Ok(("c", '\n')));
+/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::newline;
+/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("\nc")), Ok((Streaming("c"), '\n')));
+/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Err(Err::Error((Streaming("\r\nc"), ErrorKind::Char))));
+/// assert_eq!(newline::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn newline<I, Error: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
+ <I as InputIter>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::newline(input)
+ } else {
+ complete::newline(input)
+ }
+}
+
+/// Matches a tab character '\t'.
+///
+/// *Complete version*: Will return an error if there's not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::tab;
+/// fn parser(input: &str) -> IResult<&str, char> {
+/// tab(input)
+/// }
+///
+/// assert_eq!(parser("\tc"), Ok(("c", '\t')));
+/// assert_eq!(parser("\r\nc"), Err(Err::Error(Error::new("\r\nc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Char))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::tab;
+/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("\tc")), Ok((Streaming("c"), '\t')));
+/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("\r\nc")), Err(Err::Error((Streaming("\r\nc"), ErrorKind::Char))));
+/// assert_eq!(tab::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn tab<I, Error: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<STREAMING>,
+ <I as InputIter>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::tab(input)
+ } else {
+ complete::tab(input)
+ }
+}
+
+/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non
+/// alphabetic character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphabetic character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::alpha0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alpha0(input)
+/// }
+///
+/// assert_eq!(parser("ab1c"), Ok(("1c", "ab")));
+/// assert_eq!(parser("1c"), Ok(("1c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::alpha0;
+/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("ab1c")), Ok((Streaming("1c"), "ab")));
+/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("1c")), Ok((Streaming("1c"), "")));
+/// assert_eq!(alpha0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn alpha0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::alpha0(input)
+ } else {
+ complete::alpha0(input)
+ }
+}
+
+/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non alphabetic character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphabetic character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::alpha1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alpha1(input)
+/// }
+///
+/// assert_eq!(parser("aB1c"), Ok(("1c", "aB")));
+/// assert_eq!(parser("1c"), Err(Err::Error(Error::new("1c", ErrorKind::Alpha))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Alpha))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::alpha1;
+/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("aB1c")), Ok((Streaming("1c"), "aB")));
+/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("1c")), Err(Err::Error((Streaming("1c"), ErrorKind::Alpha))));
+/// assert_eq!(alpha1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn alpha1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::alpha1(input)
+ } else {
+ complete::alpha1(input)
+ }
+}
+
+/// Recognizes zero or more ASCII numerical characters: 0-9
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// digit0(input)
+/// }
+///
+/// assert_eq!(parser("21c"), Ok(("c", "21")));
+/// assert_eq!(parser("21"), Ok(("", "21")));
+/// assert_eq!(parser("a21c"), Ok(("a21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::digit0;
+/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("21c")), Ok((Streaming("c"), "21")));
+/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("a21c")), Ok((Streaming("a21c"), "")));
+/// assert_eq!(digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn digit0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::digit0(input)
+ } else {
+ complete::digit0(input)
+ }
+}
+
+/// Recognizes one or more ASCII numerical characters: 0-9
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// digit1(input)
+/// }
+///
+/// assert_eq!(parser("21c"), Ok(("c", "21")));
+/// assert_eq!(parser("c1"), Err(Err::Error(Error::new("c1", ErrorKind::Digit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Digit))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::digit1;
+/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("21c")), Ok((Streaming("c"), "21")));
+/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("c1")), Err(Err::Error((Streaming("c1"), ErrorKind::Digit))));
+/// assert_eq!(digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// ## Parsing an integer
+///
+/// You can use `digit1` in combination with [`Parser::map_res`][crate::Parser::map_res] to parse an integer:
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed, Parser};
+/// # use nom8::character::digit1;
+/// fn parser(input: &str) -> IResult<&str, u32> {
+/// digit1.map_res(str::parse).parse(input)
+/// }
+///
+/// assert_eq!(parser("416"), Ok(("", 416)));
+/// assert_eq!(parser("12b"), Ok(("b", 12)));
+/// assert!(parser("b").is_err());
+/// ```
+#[inline(always)]
+pub fn digit1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::digit1(input)
+ } else {
+ complete::digit1(input)
+ }
+}
+
+/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non hexadecimal digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non hexadecimal digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::hex_digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// hex_digit0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::hex_digit0;
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("Z"), "21c")));
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn hex_digit0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::hex_digit0(input)
+ } else {
+ complete::hex_digit0(input)
+ }
+}
+
+/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non hexadecimal digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non hexadecimal digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::hex_digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// hex_digit1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::HexDigit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::HexDigit))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::hex_digit1;
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("Z"), "21c")));
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::HexDigit))));
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn hex_digit1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::hex_digit1(input)
+ } else {
+ complete::hex_digit1(input)
+ }
+}
+
+/// Recognizes zero or more octal characters: 0-7
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non octal
+/// digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non octal digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::oct_digit0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// oct_digit0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::oct_digit0;
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("cZ"), "21")));
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn oct_digit0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::oct_digit0(input)
+ } else {
+ complete::oct_digit0(input)
+ }
+}
+
+/// Recognizes one or more octal characters: 0-7
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non octal digit character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non octal digit character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::oct_digit1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// oct_digit1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::OctDigit))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OctDigit))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::oct_digit1;
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("21cZ")), Ok((Streaming("cZ"), "21")));
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::OctDigit))));
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn oct_digit1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::oct_digit1(input)
+ } else {
+ complete::oct_digit1(input)
+ }
+}
+
+/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non
+/// alphanumerical character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphanumerical character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::alphanumeric0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alphanumeric0(input)
+/// }
+///
+/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(parser("&Z21c"), Ok(("&Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::alphanumeric0;
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("21cZ%1")), Ok((Streaming("%1"), "21cZ")));
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("&Z21c")), Ok((Streaming("&Z21c"), "")));
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn alphanumeric0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::alphanumeric0(input)
+ } else {
+ complete::alphanumeric0(input)
+ }
+}
+
+/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non alphanumerical character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphanumerical character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::alphanumeric1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alphanumeric1(input)
+/// }
+///
+/// assert_eq!(parser("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(parser("&H2"), Err(Err::Error(Error::new("&H2", ErrorKind::AlphaNumeric))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::AlphaNumeric))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::alphanumeric1;
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("21cZ%1")), Ok((Streaming("%1"), "21cZ")));
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("&H2")), Err(Err::Error((Streaming("&H2"), ErrorKind::AlphaNumeric))));
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn alphanumeric1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ streaming::alphanumeric1(input)
+ } else {
+ complete::alphanumeric1(input)
+ }
+}
+
+/// Recognizes zero or more spaces and tabs.
+///
+/// *Complete version*: Will return the whole input if no terminating token is found (a non space
+/// character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::space0;
+/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming(" \t21c")), Ok((Streaming("21c"), " \t")));
+/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
+/// assert_eq!(space0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn space0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ if STREAMING {
+ streaming::space0(input)
+ } else {
+ complete::space0(input)
+ }
+}
+
+/// Recognizes one or more spaces and tabs.
+///
+/// *Complete version*: Will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non space character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::space1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// space1(input)
+/// }
+///
+/// assert_eq!(parser(" \t21c"), Ok(("21c", " \t")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::Space))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Space))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::space1;
+/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming(" \t21c")), Ok((Streaming("21c"), " \t")));
+/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::Space))));
+/// assert_eq!(space1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn space1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ if STREAMING {
+ streaming::space1(input)
+ } else {
+ complete::space1(input)
+ }
+}
+
+/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Complete version*: will return the whole input if no terminating token is found (a non space
+/// character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::multispace0;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// multispace0(input)
+/// }
+///
+/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(parser("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::multispace0;
+/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming(" \t\n\r21c")), Ok((Streaming("21c"), " \t\n\r")));
+/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming("Z21c")), Ok((Streaming("Z21c"), "")));
+/// assert_eq!(multispace0::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn multispace0<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ if STREAMING {
+ streaming::multispace0(input)
+ } else {
+ complete::multispace0(input)
+ }
+}
+
+/// Recognizes one or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Complete version*: will return an error if there's not enough input data,
+/// or the whole input if no terminating token is found (a non space character).
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+///
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::multispace1;
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// multispace1(input)
+/// }
+///
+/// assert_eq!(parser(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(parser("H2"), Err(Err::Error(Error::new("H2", ErrorKind::MultiSpace))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::MultiSpace))));
+/// ```
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::input::Streaming;
+/// # use nom8::character::multispace1;
+/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming(" \t\n\r21c")), Ok((Streaming("21c"), " \t\n\r")));
+/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming("H2")), Err(Err::Error((Streaming("H2"), ErrorKind::MultiSpace))));
+/// assert_eq!(multispace1::<_, (_, ErrorKind), true>(Streaming("")), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn multispace1<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ if STREAMING {
+ streaming::multispace1(input)
+ } else {
+ complete::multispace1(input)
+ }
+}
+
+#[doc(hidden)]
+macro_rules! ints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ ///
+ /// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+ #[inline(always)]
+ pub fn $t<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputTake + Clone + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: for <'a> Compare<&'a[u8]>,
+ {
+ if STREAMING {
+ streaming::$t(input)
+ } else {
+ complete::$t(input)
+ }
+ }
+ )+
+ }
+}
+
+ints! { i8 i16 i32 i64 i128 }
+
+#[doc(hidden)]
+macro_rules! uints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ ///
+ /// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+ #[inline(always)]
+ pub fn $t<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ {
+ if STREAMING {
+ streaming::$t(input)
+ } else {
+ complete::$t(input)
+ }
+ }
+ )+
+ }
+}
+
+uints! { u8 u16 u32 u64 u128 }
+
+/// Recognizes floating point number in text format and returns a f32.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::character::f32;
+///
+/// let parser = |s| {
+/// f32(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::character::f32;
+///
+/// let parser = |s| {
+/// f32(s)
+/// };
+///
+/// assert_eq!(parser(Streaming("11e-1 ")), Ok((Streaming(" "), 1.1)));
+/// assert_eq!(parser(Streaming("11e-1")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(Streaming("123E-02")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), 123.0)));
+/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Float))));
+/// ```
+#[inline(always)]
+pub fn f32<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, f32, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset + Compare<&'static str>,
+ T: InputIter + InputLength + InputTake + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: ParseTo<f32>,
+ <T as InputIter>::Item: AsChar + Copy,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ if STREAMING {
+ crate::number::streaming::float(input)
+ } else {
+ crate::number::complete::float(input)
+ }
+}
+
+/// Recognizes floating point number in text format and returns a f64.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::character::f64;
+///
+/// let parser = |s| {
+/// f64(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::character::f64;
+///
+/// let parser = |s| {
+/// f64(s)
+/// };
+///
+/// assert_eq!(parser(Streaming("11e-1 ")), Ok((Streaming(" "), 1.1)));
+/// assert_eq!(parser(Streaming("11e-1")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(Streaming("123E-02")), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), 123.0)));
+/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Float))));
+/// ```
+#[inline(always)]
+pub fn f64<T, E: ParseError<T>, const STREAMING: bool>(input: T) -> IResult<T, f64, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset + Compare<&'static str>,
+ T: InputIter + InputLength + InputTake + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: ParseTo<f64>,
+ <T as InputIter>::Item: AsChar + Copy,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ if STREAMING {
+ crate::number::streaming::double(input)
+ } else {
+ crate::number::complete::double(input)
+ }
+}
+
+/// Recognizes floating point number in a byte string and returns the corresponding slice.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::character::recognize_float;
+///
+/// let parser = |s| {
+/// recognize_float(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", "11e-1")));
+/// assert_eq!(parser("123E-02"), Ok(("", "123E-02")));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", "123")));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::character::recognize_float;
+///
+/// let parser = |s| {
+/// recognize_float(s)
+/// };
+///
+/// assert_eq!(parser(Streaming("11e-1;")), Ok((Streaming(";"), "11e-1")));
+/// assert_eq!(parser(Streaming("123E-02;")), Ok((Streaming(";"), "123E-02")));
+/// assert_eq!(parser(Streaming("123K-01")), Ok((Streaming("K-01"), "123")));
+/// assert_eq!(parser(Streaming("abc")), Err(Err::Error((Streaming("abc"), ErrorKind::Char))));
+/// ```
+#[inline(always)]
+pub fn recognize_float<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputLength + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ if STREAMING {
+ crate::number::streaming::recognize_float(input)
+ } else {
+ crate::number::complete::recognize_float(input)
+ }
+}
+
+/// Recognizes a floating point number in text format
+///
+/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
+/// data.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+#[inline(always)]
+pub fn recognize_float_parts<T, E: ParseError<T>, const STREAMING: bool>(
+ input: T,
+) -> IResult<
+ T,
+ (
+ bool,
+ <T as IntoOutput>::Output,
+ <T as IntoOutput>::Output,
+ i32,
+ ),
+ E,
+>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputTake + InputIsStreaming<STREAMING>,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar + Copy,
+ T: InputTakeAtPosition + InputLength,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: for<'a> Compare<&'a [u8]>,
+ T: AsBytes,
+{
+ if STREAMING {
+ crate::number::streaming::recognize_float_parts(input)
+ } else {
+ crate::number::complete::recognize_float_parts(input)
+ }
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")]
+pub fn is_alphabetic(chr: u8) -> bool {
+ (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A)
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")]
+pub fn is_digit(chr: u8) -> bool {
+ chr >= 0x30 && chr <= 0x39
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")]
+pub fn is_hex_digit(chr: u8) -> bool {
+ (chr >= 0x30 && chr <= 0x39) || (chr >= 0x41 && chr <= 0x46) || (chr >= 0x61 && chr <= 0x66)
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")]
+pub fn is_oct_digit(chr: u8) -> bool {
+ chr >= 0x30 && chr <= 0x37
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")]
+pub fn is_alphanumeric(chr: u8) -> bool {
+ #![allow(deprecated)]
+ is_alphabetic(chr) || is_digit(chr)
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_space`")]
+pub fn is_space(chr: u8) -> bool {
+ chr == b' ' || chr == b'\t'
+}
+
+#[inline]
+#[doc(hidden)]
+#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_newline`")]
+pub fn is_newline(chr: u8) -> bool {
+ chr == b'\n'
+}
diff --git a/vendor/nom8/src/character/streaming.rs b/vendor/nom8/src/character/streaming.rs
new file mode 100644
index 000000000..47e8af11a
--- /dev/null
+++ b/vendor/nom8/src/character/streaming.rs
@@ -0,0 +1,1441 @@
+//! Character specific parsers and combinators, streaming version
+//!
+//! Functions recognizing specific characters
+
+#![allow(deprecated)]
+
+use crate::branch::alt;
+use crate::combinator::opt;
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::{
+ AsChar, FindToken, InputIter, InputLength, InputTake, InputTakeAtPosition, IntoOutput, Slice,
+};
+use crate::input::{Compare, CompareResult};
+use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
+use crate::IntoOutputIResult as _;
+use crate::{Err, IResult, Needed};
+
+/// Recognizes one character.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{ErrorKind, Error}, Needed, IResult};
+/// # use nom8::character::streaming::char;
+/// fn parser(i: &str) -> IResult<&str, char> {
+/// char('a')(i)
+/// }
+/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::Char))));
+/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn char<I, Error: ParseError<I>>(c: char) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar,
+{
+ move |i: I| char_internal(i, c)
+}
+
+pub(crate) fn char_internal<I, Error: ParseError<I>>(i: I, c: char) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar,
+{
+ match (i).iter_elements().next().map(|t| {
+ let b = t.as_char() == c;
+ (&c, b)
+ }) {
+ None => Err(Err::Incomplete(Needed::new(c.len() - i.input_len()))),
+ Some((_, false)) => Err(Err::Error(Error::from_char(i, c))),
+ Some((c, true)) => Ok((i.slice(c.len()..), c.as_char())),
+ }
+}
+
+/// Recognizes one character and checks that it satisfies a predicate
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{ErrorKind, Error}, Needed, IResult};
+/// # use nom8::character::streaming::satisfy;
+/// fn parser(i: &str) -> IResult<&str, char> {
+/// satisfy(|c| c == 'a' || c == 'b')(i)
+/// }
+/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser("cd"), Err(Err::Error(Error::new("cd", ErrorKind::Satisfy))));
+/// assert_eq!(parser(""), Err(Err::Incomplete(Needed::Unknown)));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn satisfy<F, I, Error: ParseError<I>>(cond: F) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+ F: Fn(char) -> bool,
+{
+ move |i: I| satisfy_internal(i, &cond)
+}
+
+pub(crate) fn satisfy_internal<F, I, Error: ParseError<I>>(
+ i: I,
+ cond: &F,
+) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter,
+ <I as InputIter>::Item: AsChar,
+ F: Fn(char) -> bool,
+{
+ match (i).iter_elements().next().map(|t| {
+ let c = t.as_char();
+ let b = cond(c);
+ (c, b)
+ }) {
+ None => Err(Err::Incomplete(Needed::Unknown)),
+ Some((_, false)) => Err(Err::Error(Error::from_error_kind(i, ErrorKind::Satisfy))),
+ Some((c, true)) => Ok((i.slice(c.len()..), c)),
+ }
+}
+
+/// Recognizes one of the provided characters.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::character::streaming::one_of;
+/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("abc")("b"), Ok(("", 'b')));
+/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")("bc"), Err(Err::Error(("bc", ErrorKind::OneOf))));
+/// assert_eq!(one_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::one_of`][crate::bytes::one_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::one_of` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar + Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| crate::bytes::streaming::one_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes a character that is not in the provided characters.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::character::streaming::none_of;
+/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("abc")("z"), Ok(("", 'z')));
+/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("ab")("a"), Err(Err::Error(("a", ErrorKind::NoneOf))));
+/// assert_eq!(none_of::<_, _, (_, ErrorKind)>("a")(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::none_of`][crate::bytes::none_of] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::none_of` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Fn(I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputLength + InputIter,
+ <I as InputIter>::Item: AsChar + Copy,
+ T: FindToken<<I as InputIter>::Item>,
+{
+ move |i: I| crate::bytes::streaming::none_of_internal(i, &list).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes the string "\r\n".
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::crlf;
+/// assert_eq!(crlf::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(crlf::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(crlf::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::crlf`][crate::character::crlf] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::crlf` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn crlf<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ match input.compare("\r\n") {
+ //FIXME: is this the right index?
+ CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))),
+ CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::CrLf;
+ Err(Err::Error(E::from_error_kind(input, e)))
+ }
+ }
+}
+
+/// Recognizes a string of any char except '\r\n' or '\n'.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult, Needed};
+/// # use nom8::character::streaming::not_line_ending;
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Ok(("\r\nc", "ab")));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("abc"), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::Unknown)));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rb\nc"), Err(Err::Error(("a\rb\nc", ErrorKind::Tag ))));
+/// assert_eq!(not_line_ending::<_, (_, ErrorKind)>("a\rbc"), Err(Err::Error(("a\rbc", ErrorKind::Tag ))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::not_line_ending`][crate::character::not_line_ending] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::not_line_ending` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn not_line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+ <T as InputIter>::Item: AsChar,
+ <T as InputIter>::Item: AsChar,
+{
+ match input.position(|item| {
+ let c = item.as_char();
+ c == '\r' || c == '\n'
+ }) {
+ None => Err(Err::Incomplete(Needed::Unknown)),
+ Some(index) => {
+ let mut it = input.slice(index..).iter_elements();
+ let nth = it.next().unwrap().as_char();
+ if nth == '\r' {
+ let sliced = input.slice(index..);
+ let comp = sliced.compare("\r\n");
+ match comp {
+ //FIXME: calculate the right index
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::Unknown)),
+ CompareResult::Error => {
+ let e: ErrorKind = ErrorKind::Tag;
+ Err(Err::Error(E::from_error_kind(input, e)))
+ }
+ CompareResult::Ok => Ok((input.slice(index..), input.slice(..index))).into_output(),
+ }
+ } else {
+ Ok((input.slice(index..), input.slice(..index))).into_output()
+ }
+ }
+ }
+}
+
+/// Recognizes an end of line (both '\n' and '\r\n').
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::line_ending;
+/// assert_eq!(line_ending::<_, (_, ErrorKind)>("\r\nc"), Ok(("c", "\r\n")));
+/// assert_eq!(line_ending::<_, (_, ErrorKind)>("ab\r\nc"), Err(Err::Error(("ab\r\nc", ErrorKind::CrLf))));
+/// assert_eq!(line_ending::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::line_ending`][crate::character::line_ending] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::line_ending` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn line_ending<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<Range<usize>> + Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: InputIter + InputLength,
+ T: IntoOutput,
+ T: Compare<&'static str>,
+{
+ match input.compare("\n") {
+ CompareResult::Ok => Ok((input.slice(1..), input.slice(0..1))).into_output(),
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(1))),
+ CompareResult::Error => {
+ match input.compare("\r\n") {
+ //FIXME: is this the right index?
+ CompareResult::Ok => Ok((input.slice(2..), input.slice(0..2))).into_output(),
+ CompareResult::Incomplete => Err(Err::Incomplete(Needed::new(2))),
+ CompareResult::Error => Err(Err::Error(E::from_error_kind(input, ErrorKind::CrLf))),
+ }
+ }
+ }
+}
+
+/// Matches a newline character '\\n'.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::newline;
+/// assert_eq!(newline::<_, (_, ErrorKind)>("\nc"), Ok(("c", '\n')));
+/// assert_eq!(newline::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char))));
+/// assert_eq!(newline::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::newline`][crate::character::newline] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::newline` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn newline<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar,
+{
+ char('\n')(input)
+}
+
+/// Matches a tab character '\t'.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::tab;
+/// assert_eq!(tab::<_, (_, ErrorKind)>("\tc"), Ok(("c", '\t')));
+/// assert_eq!(tab::<_, (_, ErrorKind)>("\r\nc"), Err(Err::Error(("\r\nc", ErrorKind::Char))));
+/// assert_eq!(tab::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::tab`][crate::character::tab] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::tab` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn tab<I, Error: ParseError<I>>(input: I) -> IResult<I, char, Error>
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength,
+ <I as InputIter>::Item: AsChar,
+{
+ char('\t')(input)
+}
+
+/// Matches one byte as a character. Note that the input type will
+/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data.
+/// # Example
+///
+/// ```
+/// # use nom8::{character::streaming::anychar, Err, error::ErrorKind, IResult, Needed};
+/// assert_eq!(anychar::<_, (_, ErrorKind)>("abc"), Ok(("bc",'a')));
+/// assert_eq!(anychar::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::bytes::any`][crate::bytes::any] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::bytes::any` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E>
+where
+ T: InputIter + InputLength + Slice<RangeFrom<usize>>,
+ <T as InputIter>::Item: AsChar,
+{
+ crate::bytes::streaming::any(input).map(|(i, c)| (i, c.as_char()))
+}
+
+/// Recognizes zero or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphabetic character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::alpha0;
+/// assert_eq!(alpha0::<_, (_, ErrorKind)>("ab1c"), Ok(("1c", "ab")));
+/// assert_eq!(alpha0::<_, (_, ErrorKind)>("1c"), Ok(("1c", "")));
+/// assert_eq!(alpha0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha0`][crate::character::alpha0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alpha0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn alpha0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_streaming(|item| !item.is_alpha())
+ .into_output()
+}
+
+/// Recognizes one or more lowercase and uppercase ASCII alphabetic characters: a-z, A-Z
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphabetic character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::alpha1;
+/// assert_eq!(alpha1::<_, (_, ErrorKind)>("aB1c"), Ok(("1c", "aB")));
+/// assert_eq!(alpha1::<_, (_, ErrorKind)>("1c"), Err(Err::Error(("1c", ErrorKind::Alpha))));
+/// assert_eq!(alpha1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alpha1`][crate::character::alpha1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alpha1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn alpha1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_streaming(|item| !item.is_alpha(), ErrorKind::Alpha)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII numerical characters: 0-9
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::digit0;
+/// assert_eq!(digit0::<_, (_, ErrorKind)>("21c"), Ok(("c", "21")));
+/// assert_eq!(digit0::<_, (_, ErrorKind)>("a21c"), Ok(("a21c", "")));
+/// assert_eq!(digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::digit0`][crate::character::digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::digit0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_streaming(|item| !item.is_dec_digit())
+ .into_output()
+}
+
+/// Recognizes one or more ASCII numerical characters: 0-9
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::digit1;
+/// assert_eq!(digit1::<_, (_, ErrorKind)>("21c"), Ok(("c", "21")));
+/// assert_eq!(digit1::<_, (_, ErrorKind)>("c1"), Err(Err::Error(("c1", ErrorKind::Digit))));
+/// assert_eq!(digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::digit1`][crate::character::digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::digit1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_streaming(|item| !item.is_dec_digit(), ErrorKind::Digit)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non hexadecimal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::hex_digit0;
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(hex_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit0`][crate::character::hex_digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::hex_digit0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn hex_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_streaming(|item| !item.is_hex_digit())
+ .into_output()
+}
+
+/// Recognizes one or more ASCII hexadecimal numerical characters: 0-9, A-F, a-f
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non hexadecimal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::hex_digit1;
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::HexDigit))));
+/// assert_eq!(hex_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::hex_digit1`][crate::character::hex_digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::hex_digit1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn hex_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_streaming(|item| !item.is_hex_digit(), ErrorKind::HexDigit)
+ .into_output()
+}
+
+/// Recognizes zero or more octal characters: 0-7
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non octal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::oct_digit0;
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(oct_digit0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit0`][crate::character::oct_digit0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::oct_digit0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn oct_digit0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_streaming(|item| !item.is_oct_digit())
+ .into_output()
+}
+
+/// Recognizes one or more octal characters: 0-7
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non octal digit character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::oct_digit1;
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("21cZ"), Ok(("cZ", "21")));
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::OctDigit))));
+/// assert_eq!(oct_digit1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::oct_digit1`][crate::character::oct_digit1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::oct_digit1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn oct_digit1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_streaming(|item| !item.is_oct_digit(), ErrorKind::OctDigit)
+ .into_output()
+}
+
+/// Recognizes zero or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphanumerical character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::alphanumeric0;
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>("&Z21c"), Ok(("&Z21c", "")));
+/// assert_eq!(alphanumeric0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric0`][crate::character::alphanumeric0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alphanumeric0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn alphanumeric0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position_streaming(|item| !item.is_alphanum())
+ .into_output()
+}
+
+/// Recognizes one or more ASCII numerical and alphabetic characters: 0-9, a-z, A-Z
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non alphanumerical character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::alphanumeric1;
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("21cZ%1"), Ok(("%1", "21cZ")));
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>("&H2"), Err(Err::Error(("&H2", ErrorKind::AlphaNumeric))));
+/// assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::alphanumeric1`][crate::character::alphanumeric1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::alphanumeric1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn alphanumeric1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ input
+ .split_at_position1_streaming(|item| !item.is_alphanum(), ErrorKind::AlphaNumeric)
+ .into_output()
+}
+
+/// Recognizes zero or more spaces and tabs.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::space0;
+/// assert_eq!(space0::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t")));
+/// assert_eq!(space0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(space0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::space0`][crate::character::space0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::space0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn space0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position_streaming(|item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t')
+ })
+ .into_output()
+}
+/// Recognizes one or more spaces and tabs.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::space1;
+/// assert_eq!(space1::<_, (_, ErrorKind)>(" \t21c"), Ok(("21c", " \t")));
+/// assert_eq!(space1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::Space))));
+/// assert_eq!(space1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::space1`][crate::character::space1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::space1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn space1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position1_streaming(
+ |item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t')
+ },
+ ErrorKind::Space,
+ )
+ .into_output()
+}
+
+/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::multispace0;
+/// assert_eq!(multispace0::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(multispace0::<_, (_, ErrorKind)>("Z21c"), Ok(("Z21c", "")));
+/// assert_eq!(multispace0::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace0`][crate::character::multispace0] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::multispace0` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn multispace0<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position_streaming(|item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ })
+ .into_output()
+}
+
+/// Recognizes one or more spaces, tabs, carriage returns and line feeds.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there's not enough input data,
+/// or if no terminating token is found (a non space character).
+/// # Example
+///
+/// ```
+/// # use nom8::{Err, error::ErrorKind, IResult, Needed};
+/// # use nom8::character::streaming::multispace1;
+/// assert_eq!(multispace1::<_, (_, ErrorKind)>(" \t\n\r21c"), Ok(("21c", " \t\n\r")));
+/// assert_eq!(multispace1::<_, (_, ErrorKind)>("H2"), Err(Err::Error(("H2", ErrorKind::MultiSpace))));
+/// assert_eq!(multispace1::<_, (_, ErrorKind)>(""), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::multispace1`][crate::character::multispace1] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::multispace1` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn multispace1<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar + Clone,
+{
+ input
+ .split_at_position1_streaming(
+ |item| {
+ let c = item.as_char();
+ !(c == ' ' || c == '\t' || c == '\r' || c == '\n')
+ },
+ ErrorKind::MultiSpace,
+ )
+ .into_output()
+}
+
+pub(crate) fn sign<T, E: ParseError<T>>(input: T) -> IResult<T, bool, E>
+where
+ T: Clone + InputTake + InputLength,
+ T: IntoOutput,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ use crate::bytes::streaming::tag;
+ use crate::combinator::value;
+
+ let (i, opt_sign) = opt(alt((
+ value(false, tag(&b"-"[..])),
+ value(true, tag(&b"+"[..])),
+ )))(input)?;
+ let sign = opt_sign.unwrap_or(true);
+
+ Ok((i, sign))
+}
+
+#[doc(hidden)]
+macro_rules! ints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength + InputTake + Clone,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: for <'a> Compare<&'a[u8]>,
+ {
+ let (i, sign) = sign(input.clone())?;
+
+ if i.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::new(1)));
+ }
+
+ let mut value: $t = 0;
+ if sign {
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+ } else {
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_sub(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(input, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+ }
+
+ Err(Err::Incomplete(Needed::new(1)))
+ }
+ )+
+ }
+}
+
+ints! { i8 i16 i32 i64 i128 }
+
+#[doc(hidden)]
+macro_rules! uints {
+ ($($t:tt)+) => {
+ $(
+ /// will parse a number in text form to a number
+ ///
+ /// *Complete version*: can parse until the end of input.
+ pub fn $t<T, E: ParseError<T>>(input: T) -> IResult<T, $t, E>
+ where
+ T: InputIter + Slice<RangeFrom<usize>> + InputLength,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ {
+ let i = input;
+
+ if i.input_len() == 0 {
+ return Err(Err::Incomplete(Needed::new(1)));
+ }
+
+ let mut value: $t = 0;
+ for (pos, c) in i.iter_indices() {
+ match c.as_char().to_digit(10) {
+ None => {
+ if pos == 0 {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit)));
+ } else {
+ return Ok((i.slice(pos..), value));
+ }
+ },
+ Some(d) => match value.checked_mul(10).and_then(|v| v.checked_add(d as $t)) {
+ None => return Err(Err::Error(E::from_error_kind(i, ErrorKind::Digit))),
+ Some(v) => value = v,
+ }
+ }
+ }
+
+ Err(Err::Incomplete(Needed::new(1)))
+ }
+ )+
+ }
+}
+
+uints! { u8 u16 u32 u64 u128 }
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::error::ErrorKind;
+ use crate::input::ParseTo;
+ use crate::sequence::pair;
+ use crate::{Err, IResult, Needed};
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn anychar_str() {
+ use super::anychar;
+ assert_eq!(anychar::<_, (&str, ErrorKind)>("Ә"), Ok(("", 'Ә')));
+ }
+
+ #[test]
+ fn character() {
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::new(1))));
+ assert_parse!(alpha1(a), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &b"a"[..])));
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind)>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(
+ digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(a),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(c),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(d),
+ Ok(("zé12".as_bytes(), &b"a"[..]))
+ );
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(
+ oct_digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(a),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(c),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(
+ space1::<_, (_, ErrorKind)>(e),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(space1::<_, (_, ErrorKind)>(f), Ok((&b";"[..], &b" "[..])));
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind)>(a),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(c), Ok((&c[1..], &"a"[..])));
+ assert_eq!(alpha1::<_, (_, ErrorKind)>(d), Ok(("é12", &"az"[..])));
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(
+ digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(a),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind)>(c),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(hex_digit1::<_, (_, ErrorKind)>(d), Ok(("zé12", &"a"[..])));
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(
+ oct_digit1::<_, (_, ErrorKind)>(b),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(a),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind)>(c),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind)>(d), Ok(("é12", "az")));
+ assert_eq!(
+ space1::<_, (_, ErrorKind)>(e),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ use crate::input::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, (_, ErrorKind)>(a) {
+ Ok((i, _)) => {
+ assert_eq!(a.offset(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, (_, ErrorKind)>(b) {
+ Ok((i, _)) => {
+ assert_eq!(b.offset(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, (_, ErrorKind)>(c) {
+ Ok((i, _)) => {
+ assert_eq!(c.offset(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, (_, ErrorKind)>(d) {
+ Ok((i, _)) => {
+ assert_eq!(d.offset(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, (_, ErrorKind)>(e) {
+ Ok((i, _)) => {
+ assert_eq!(e.offset(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, (_, ErrorKind)>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, (_, ErrorKind)>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(a),
+ Ok((&b"\nefgh"[..], &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(b),
+ Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(c),
+ Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(d),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ /*
+ let a: &str = "ab12cd\nefgh";
+ assert_eq!(not_line_ending(a), Ok((&"\nefgh"[..], &"ab12cd"[..])));
+
+ let b: &str = "ab12cd\nefgh\nijkl";
+ assert_eq!(not_line_ending(b), Ok((&"\nefgh\nijkl"[..], &"ab12cd"[..])));
+
+ let c: &str = "ab12cd\r\nefgh\nijkl";
+ assert_eq!(not_line_ending(c), Ok((&"\r\nefgh\nijkl"[..], &"ab12cd"[..])));
+
+ let d = "βèƒôřè\nÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(d), Ok((&"\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
+
+ let e = "βèƒôřè\r\nÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(e), Ok((&"\r\nÂßÇáƒƭèř"[..], &"βèƒôřè"[..])));
+ */
+
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag))));
+
+ let g2: &str = "ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind)>(g2),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::OctDigit)))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
+ }
+
+ #[test]
+ fn full_line_unix() {
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(crlf(&b"\r"[..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ crlf(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(crlf("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(crlf("\r"), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ crlf("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..])));
+ assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ line_ending(&b"\r"[..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ line_ending(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(line_ending("\na"), Ok(("a", "\n")));
+ assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(line_ending("\r"), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ line_ending("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ fn digit_to_i16(input: &str) -> IResult<&str, i16> {
+ let i = input;
+ let (i, opt_sign) = opt(alt((char('+'), char('-'))))(i)?;
+ let sign = match opt_sign {
+ Some('+') => true,
+ Some('-') => false,
+ _ => true,
+ };
+
+ let (i, s) = match digit1::<_, crate::error::Error<_>>(i) {
+ Ok((i, s)) => (i, s),
+ Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)),
+ Err(_) => {
+ return Err(Err::Error(crate::error::Error::from_error_kind(
+ input,
+ ErrorKind::Digit,
+ )))
+ }
+ };
+ match s.parse_to() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ fn digit_to_u32(i: &str) -> IResult<&str, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ #[test]
+ fn one_of_test() {
+ fn f(i: &[u8]) -> IResult<&[u8], char> {
+ one_of("ab")(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(f(a), Ok((&b"bcd"[..], 'a')));
+
+ let b = &b"cde"[..];
+ assert_eq!(f(b), Err(Err::Error(error_position!(b, ErrorKind::OneOf))));
+
+ fn utf8(i: &str) -> IResult<&str, char> {
+ one_of("+\u{FF0B}")(i)
+ }
+
+ assert!(utf8("+").is_ok());
+ assert!(utf8("\u{FF0B}").is_ok());
+ }
+
+ #[test]
+ fn none_of_test() {
+ fn f(i: &[u8]) -> IResult<&[u8], char> {
+ none_of("ab")(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::NoneOf))));
+
+ let b = &b"cde"[..];
+ assert_eq!(f(b), Ok((&b"de"[..], 'c')));
+ }
+
+ #[test]
+ fn char_byteslice() {
+ fn f(i: &[u8]) -> IResult<&[u8], char> {
+ char('c')(i)
+ }
+
+ let a = &b"abcd"[..];
+ assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
+
+ let b = &b"cde"[..];
+ assert_eq!(f(b), Ok((&b"de"[..], 'c')));
+ }
+
+ #[test]
+ fn char_str() {
+ fn f(i: &str) -> IResult<&str, char> {
+ char('c')(i)
+ }
+
+ let a = &"abcd"[..];
+ assert_eq!(f(a), Err(Err::Error(error_position!(a, ErrorKind::Char))));
+
+ let b = &"cde"[..];
+ assert_eq!(f(b), Ok((&"de"[..], 'c')));
+ }
+
+ proptest! {
+ #[test]
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(&s);
+ let res2 = i16(s.as_str());
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(&s);
+ let res2 = u32(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+}
diff --git a/vendor/nom8/src/character/tests.rs b/vendor/nom8/src/character/tests.rs
new file mode 100644
index 000000000..d10cfd7cf
--- /dev/null
+++ b/vendor/nom8/src/character/tests.rs
@@ -0,0 +1,1030 @@
+use super::*;
+
+mod complete {
+ use super::*;
+ use crate::branch::alt;
+ use crate::combinator::opt;
+ use crate::error::ErrorKind;
+ use crate::input::ParseTo;
+ use crate::Err;
+ use proptest::prelude::*;
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn character() {
+ let empty: &[u8] = b"";
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, (_, ErrorKind)>(a), Err(Err::Incomplete(Needed::Size(1))));
+ assert_parse!(alpha1(a), Ok((empty, a)));
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), false>(c),
+ Ok((&c[1..], &b"a"[..]))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), false>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(c), Ok((empty, c)));
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), false>(d),
+ Ok(("zé12".as_bytes(), &b"a"[..]))
+ );
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind), false>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind), false>(c), Ok((empty, c)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), false>(d),
+ Ok(("é12".as_bytes(), &b"az"[..]))
+ );
+ assert_eq!(space1::<_, (_, ErrorKind), false>(e), Ok((empty, e)));
+ assert_eq!(
+ space1::<_, (_, ErrorKind), false>(f),
+ Ok((&b";"[..], &b" "[..]))
+ );
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let empty = "";
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(alpha1::<_, (_, ErrorKind), false>(a), Ok((empty, a)));
+ assert_eq!(alpha1(b), Err(Err::Error((b, ErrorKind::Alpha))));
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), false>(c),
+ Ok((&c[1..], &"a"[..]))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), false>(d),
+ Ok(("é12", &"az"[..]))
+ );
+ assert_eq!(digit1(a), Err(Err::Error((a, ErrorKind::Digit))));
+ assert_eq!(digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(digit1(c), Err(Err::Error((c, ErrorKind::Digit))));
+ assert_eq!(digit1(d), Err(Err::Error((d, ErrorKind::Digit))));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(a), Ok((empty, a)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(hex_digit1::<_, (_, ErrorKind), false>(c), Ok((empty, c)));
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), false>(d),
+ Ok(("zé12", &"a"[..]))
+ );
+ assert_eq!(hex_digit1(e), Err(Err::Error((e, ErrorKind::HexDigit))));
+ assert_eq!(oct_digit1(a), Err(Err::Error((a, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1::<_, (_, ErrorKind), false>(b), Ok((empty, b)));
+ assert_eq!(oct_digit1(c), Err(Err::Error((c, ErrorKind::OctDigit))));
+ assert_eq!(oct_digit1(d), Err(Err::Error((d, ErrorKind::OctDigit))));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind), false>(a), Ok((empty, a)));
+ //assert_eq!(fix_error!(b,(), alphanumeric), Ok((empty, b)));
+ assert_eq!(alphanumeric1::<_, (_, ErrorKind), false>(c), Ok((empty, c)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), false>(d),
+ Ok(("é12", "az"))
+ );
+ assert_eq!(space1::<_, (_, ErrorKind), false>(e), Ok((empty, e)));
+ }
+
+ use crate::input::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, (_, ErrorKind), false>(a) {
+ Ok((i, _)) => {
+ assert_eq!(a.offset(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, (_, ErrorKind), false>(b) {
+ Ok((i, _)) => {
+ assert_eq!(b.offset(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, (_, ErrorKind), false>(c) {
+ Ok((i, _)) => {
+ assert_eq!(c.offset(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, (_, ErrorKind), false>(d) {
+ Ok((i, _)) => {
+ assert_eq!(d.offset(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, (_, ErrorKind), false>(e) {
+ Ok((i, _)) => {
+ assert_eq!(e.offset(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, (_, ErrorKind), false>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, (_, ErrorKind), false>(f) {
+ Ok((i, _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), false>(a),
+ Ok((&b"\nefgh"[..], &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), false>(b),
+ Ok((&b"\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), false>(c),
+ Ok((&b"\r\nefgh\nijkl"[..], &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), false>(d),
+ Ok((&[][..], &d[..]))
+ );
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(not_line_ending(f), Err(Err::Error((f, ErrorKind::Tag))));
+
+ let g2: &str = "ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), false>(g2),
+ Ok(("", g2))
+ );
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(hex_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::HexDigit)))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(oct_digit1(i), Ok((&b";"[..], &i[..i.len() - 1])));
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(i),
+ Err(Err::Error(error_position!(i, ErrorKind::OctDigit)))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ use crate::sequence::pair;
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\r\n"[..]))));
+ }
+
+ #[test]
+ fn full_line_unix() {
+ use crate::sequence::pair;
+ fn take_full_line(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(input);
+ assert_eq!(output, Ok((&b""[..], (&b"abc"[..], &b"\n"[..]))));
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(&input[..]);
+ assert_parse!(output, Ok((&b""[..], &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(crlf(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ crlf(&b"\r"[..]),
+ Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ crlf(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(crlf("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ crlf("\r"),
+ Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ crlf("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(line_ending(&b"\na"[..]), Ok((&b"a"[..], &b"\n"[..])));
+ assert_parse!(line_ending(&b"\r\na"[..]), Ok((&b"a"[..], &b"\r\n"[..])));
+ assert_parse!(
+ line_ending(&b"\r"[..]),
+ Err(Err::Error(error_position!(&b"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ line_ending(&b"\ra"[..]),
+ Err(Err::Error(error_position!(&b"\ra"[..], ErrorKind::CrLf)))
+ );
+
+ assert_parse!(line_ending("\na"), Ok(("a", "\n")));
+ assert_parse!(line_ending("\r\na"), Ok(("a", "\r\n")));
+ assert_parse!(
+ line_ending("\r"),
+ Err(Err::Error(error_position!(&"\r"[..], ErrorKind::CrLf)))
+ );
+ assert_parse!(
+ line_ending("\ra"),
+ Err(Err::Error(error_position!("\ra", ErrorKind::CrLf)))
+ );
+ }
+
+ fn digit_to_i16(input: &str) -> IResult<&str, i16> {
+ let i = input;
+ let (i, opt_sign) = opt(alt(('+', '-')))(i)?;
+ let sign = match opt_sign {
+ Some('+') => true,
+ Some('-') => false,
+ _ => true,
+ };
+
+ let (i, s) = match digit1::<_, crate::error::Error<_>, false>(i) {
+ Ok((i, s)) => (i, s),
+ Err(_) => {
+ return Err(Err::Error(crate::error::Error::from_error_kind(
+ input,
+ ErrorKind::Digit,
+ )))
+ }
+ };
+
+ match s.parse_to() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ fn digit_to_u32(i: &str) -> IResult<&str, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(&s);
+ let res2 = i16(s.as_str());
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(&s);
+ let res2 = u32(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn float_test() {
+ let mut test_cases = vec![
+ "+3.14",
+ "3.14",
+ "-3.14",
+ "0",
+ "0.0",
+ "1.",
+ ".789",
+ "-.5",
+ "1e7",
+ "-1E-7",
+ ".3e-2",
+ "1.e4",
+ "1.2e4",
+ "12.34",
+ "-1.234E-12",
+ "-1.234e-12",
+ "0.00000000000000000087",
+ ];
+
+ for test in test_cases.drain(..) {
+ let expected32 = str::parse::<f32>(test).unwrap();
+ let expected64 = str::parse::<f64>(test).unwrap();
+
+ println!("now parsing: {} -> {}", test, expected32);
+
+ let larger = format!("{}", test);
+ assert_parse!(recognize_float(&larger[..]), Ok(("", test)));
+
+ assert_parse!(f32(larger.as_bytes()), Ok((&b""[..], expected32)));
+ assert_parse!(f32(&larger[..]), Ok(("", expected32)));
+
+ assert_parse!(f64(larger.as_bytes()), Ok((&b""[..], expected64)));
+ assert_parse!(f64(&larger[..]), Ok(("", expected64)));
+ }
+
+ let remaining_exponent = "-1.234E-";
+ assert_parse!(
+ recognize_float(remaining_exponent),
+ Err(Err::Failure(("", ErrorKind::Digit)))
+ );
+
+ let (_i, nan) = f32::<_, (), false>("NaN").unwrap();
+ assert!(nan.is_nan());
+
+ let (_i, inf) = f32::<_, (), false>("inf").unwrap();
+ assert!(inf.is_infinite());
+ let (_i, inf) = f32::<_, (), false>("infinite").unwrap();
+ assert!(inf.is_infinite());
+ }
+
+ #[cfg(feature = "std")]
+ fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
+ #[allow(deprecated)] // will just become `pub(crate)` later
+ match crate::number::complete::recognize_float_or_exceptions(i) {
+ Err(e) => Err(e),
+ Ok((i, s)) => {
+ if s.is_empty() {
+ return Err(Err::Error(()));
+ }
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(())),
+ }
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg(feature = "std")]
+ fn floats(s in "\\PC*") {
+ println!("testing {}", s);
+ let res1 = parse_f64(&s);
+ let res2 = f64::<_, (), false>(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+}
+
+mod streaming {
+ use super::*;
+ use crate::combinator::opt;
+ use crate::error::ErrorKind;
+ use crate::input::ParseTo;
+ use crate::input::Streaming;
+ use crate::sequence::pair;
+ use crate::{Err, IResult, Needed};
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn character() {
+ let a: &[u8] = b"abcd";
+ let b: &[u8] = b"1234";
+ let c: &[u8] = b"a123";
+ let d: &[u8] = "azé12".as_bytes();
+ let e: &[u8] = b" ";
+ let f: &[u8] = b" ;";
+ //assert_eq!(alpha1::<_, (_, ErrorKind), true>(a), Err(Err::Incomplete(Needed::new(1))));
+ assert_parse!(alpha1(Streaming(a)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(
+ alpha1(Streaming(b)),
+ Err(Err::Error((Streaming(b), ErrorKind::Alpha)))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Ok((Streaming(&c[1..]), &b"a"[..]))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("é12".as_bytes()), &b"az"[..]))
+ );
+ assert_eq!(
+ digit1(Streaming(a)),
+ Err(Err::Error((Streaming(a), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ digit1(Streaming(c)),
+ Err(Err::Error((Streaming(c), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ digit1(Streaming(d)),
+ Err(Err::Error((Streaming(d), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(a)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("zé12".as_bytes()), &b"a"[..]))
+ );
+ assert_eq!(
+ hex_digit1(Streaming(e)),
+ Err(Err::Error((Streaming(e), ErrorKind::HexDigit)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(a)),
+ Err(Err::Error((Streaming(a), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ oct_digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(c)),
+ Err(Err::Error((Streaming(c), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(d)),
+ Err(Err::Error((Streaming(d), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(a)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("é12".as_bytes()), &b"az"[..]))
+ );
+ assert_eq!(
+ space1::<_, (_, ErrorKind), true>(Streaming(e)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ space1::<_, (_, ErrorKind), true>(Streaming(f)),
+ Ok((Streaming(&b";"[..]), &b" "[..]))
+ );
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn character_s() {
+ let a = "abcd";
+ let b = "1234";
+ let c = "a123";
+ let d = "azé12";
+ let e = " ";
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), true>(Streaming(a)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alpha1(Streaming(b)),
+ Err(Err::Error((Streaming(b), ErrorKind::Alpha)))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Ok((Streaming(&c[1..]), &"a"[..]))
+ );
+ assert_eq!(
+ alpha1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("é12"), &"az"[..]))
+ );
+ assert_eq!(
+ digit1(Streaming(a)),
+ Err(Err::Error((Streaming(a), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ digit1(Streaming(c)),
+ Err(Err::Error((Streaming(c), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ digit1(Streaming(d)),
+ Err(Err::Error((Streaming(d), ErrorKind::Digit)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(a)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ hex_digit1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("zé12"), &"a"[..]))
+ );
+ assert_eq!(
+ hex_digit1(Streaming(e)),
+ Err(Err::Error((Streaming(e), ErrorKind::HexDigit)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(a)),
+ Err(Err::Error((Streaming(a), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ oct_digit1::<_, (_, ErrorKind), true>(Streaming(b)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(c)),
+ Err(Err::Error((Streaming(c), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ oct_digit1(Streaming(d)),
+ Err(Err::Error((Streaming(d), ErrorKind::OctDigit)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(a)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ //assert_eq!(fix_error!(b,(), alphanumeric1), Ok((empty, b)));
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(c)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ alphanumeric1::<_, (_, ErrorKind), true>(Streaming(d)),
+ Ok((Streaming("é12"), "az"))
+ );
+ assert_eq!(
+ space1::<_, (_, ErrorKind), true>(Streaming(e)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ use crate::input::Offset;
+ #[test]
+ fn offset() {
+ let a = &b"abcd;"[..];
+ let b = &b"1234;"[..];
+ let c = &b"a123;"[..];
+ let d = &b" \t;"[..];
+ let e = &b" \t\r\n;"[..];
+ let f = &b"123abcDEF;"[..];
+
+ match alpha1::<_, (_, ErrorKind), true>(Streaming(a)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(a.offset(i) + i.len(), a.len());
+ }
+ _ => panic!("wrong return type in offset test for alpha"),
+ }
+ match digit1::<_, (_, ErrorKind), true>(Streaming(b)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(b.offset(i) + i.len(), b.len());
+ }
+ _ => panic!("wrong return type in offset test for digit"),
+ }
+ match alphanumeric1::<_, (_, ErrorKind), true>(Streaming(c)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(c.offset(i) + i.len(), c.len());
+ }
+ _ => panic!("wrong return type in offset test for alphanumeric"),
+ }
+ match space1::<_, (_, ErrorKind), true>(Streaming(d)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(d.offset(i) + i.len(), d.len());
+ }
+ _ => panic!("wrong return type in offset test for space"),
+ }
+ match multispace1::<_, (_, ErrorKind), true>(Streaming(e)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(e.offset(i) + i.len(), e.len());
+ }
+ _ => panic!("wrong return type in offset test for multispace"),
+ }
+ match hex_digit1::<_, (_, ErrorKind), true>(Streaming(f)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for hex_digit"),
+ }
+ match oct_digit1::<_, (_, ErrorKind), true>(Streaming(f)) {
+ Ok((Streaming(i), _)) => {
+ assert_eq!(f.offset(i) + i.len(), f.len());
+ }
+ _ => panic!("wrong return type in offset test for oct_digit"),
+ }
+ }
+
+ #[test]
+ fn is_not_line_ending_bytes() {
+ let a: &[u8] = b"ab12cd\nefgh";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), true>(Streaming(a)),
+ Ok((Streaming(&b"\nefgh"[..]), &b"ab12cd"[..]))
+ );
+
+ let b: &[u8] = b"ab12cd\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), true>(Streaming(b)),
+ Ok((Streaming(&b"\nefgh\nijkl"[..]), &b"ab12cd"[..]))
+ );
+
+ let c: &[u8] = b"ab12cd\r\nefgh\nijkl";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), true>(Streaming(c)),
+ Ok((Streaming(&b"\r\nefgh\nijkl"[..]), &b"ab12cd"[..]))
+ );
+
+ let d: &[u8] = b"ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), true>(Streaming(d)),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn is_not_line_ending_str() {
+ let f = "βèƒôřè\rÂßÇáƒƭèř";
+ assert_eq!(
+ not_line_ending(Streaming(f)),
+ Err(Err::Error((Streaming(f), ErrorKind::Tag)))
+ );
+
+ let g2: &str = "ab12cd";
+ assert_eq!(
+ not_line_ending::<_, (_, ErrorKind), true>(Streaming(g2)),
+ Err(Err::Incomplete(Needed::Unknown))
+ );
+ }
+
+ #[test]
+ fn hex_digit_test() {
+ let i = &b"0123456789abcdefABCDEF;"[..];
+ assert_parse!(
+ hex_digit1(Streaming(i)),
+ Ok((Streaming(&b";"[..]), &i[..i.len() - 1]))
+ );
+
+ let i = &b"g"[..];
+ assert_parse!(
+ hex_digit1(Streaming(i)),
+ Err(Err::Error(error_position!(
+ Streaming(i),
+ ErrorKind::HexDigit
+ )))
+ );
+
+ let i = &b"G"[..];
+ assert_parse!(
+ hex_digit1(Streaming(i)),
+ Err(Err::Error(error_position!(
+ Streaming(i),
+ ErrorKind::HexDigit
+ )))
+ );
+
+ assert!(AsChar::is_hex_digit(b'0'));
+ assert!(AsChar::is_hex_digit(b'9'));
+ assert!(AsChar::is_hex_digit(b'a'));
+ assert!(AsChar::is_hex_digit(b'f'));
+ assert!(AsChar::is_hex_digit(b'A'));
+ assert!(AsChar::is_hex_digit(b'F'));
+ assert!(!AsChar::is_hex_digit(b'g'));
+ assert!(!AsChar::is_hex_digit(b'G'));
+ assert!(!AsChar::is_hex_digit(b'/'));
+ assert!(!AsChar::is_hex_digit(b':'));
+ assert!(!AsChar::is_hex_digit(b'@'));
+ assert!(!AsChar::is_hex_digit(b'\x60'));
+ }
+
+ #[test]
+ fn oct_digit_test() {
+ let i = &b"01234567;"[..];
+ assert_parse!(
+ oct_digit1(Streaming(i)),
+ Ok((Streaming(&b";"[..]), &i[..i.len() - 1]))
+ );
+
+ let i = &b"8"[..];
+ assert_parse!(
+ oct_digit1(Streaming(i)),
+ Err(Err::Error(error_position!(
+ Streaming(i),
+ ErrorKind::OctDigit
+ )))
+ );
+
+ assert!(AsChar::is_oct_digit(b'0'));
+ assert!(AsChar::is_oct_digit(b'7'));
+ assert!(!AsChar::is_oct_digit(b'8'));
+ assert!(!AsChar::is_oct_digit(b'9'));
+ assert!(!AsChar::is_oct_digit(b'a'));
+ assert!(!AsChar::is_oct_digit(b'A'));
+ assert!(!AsChar::is_oct_digit(b'/'));
+ assert!(!AsChar::is_oct_digit(b':'));
+ assert!(!AsChar::is_oct_digit(b'@'));
+ assert!(!AsChar::is_oct_digit(b'\x60'));
+ }
+
+ #[test]
+ fn full_line_windows() {
+ fn take_full_line(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\r\n";
+ let output = take_full_line(Streaming(input));
+ assert_eq!(
+ output,
+ Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\r\n"[..])))
+ );
+ }
+
+ #[test]
+ fn full_line_unix() {
+ fn take_full_line(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8])> {
+ pair(not_line_ending, line_ending)(i)
+ }
+ let input = b"abc\n";
+ let output = take_full_line(Streaming(input));
+ assert_eq!(output, Ok((Streaming(&b""[..]), (&b"abc"[..], &b"\n"[..]))));
+ }
+
+ #[test]
+ fn check_windows_lineending() {
+ let input = b"\r\n";
+ let output = line_ending(Streaming(&input[..]));
+ assert_parse!(output, Ok((Streaming(&b""[..]), &b"\r\n"[..])));
+ }
+
+ #[test]
+ fn check_unix_lineending() {
+ let input = b"\n";
+ let output = line_ending(Streaming(&input[..]));
+ assert_parse!(output, Ok((Streaming(&b""[..]), &b"\n"[..])));
+ }
+
+ #[test]
+ fn cr_lf() {
+ assert_parse!(
+ crlf(Streaming(&b"\r\na"[..])),
+ Ok((Streaming(&b"a"[..]), &b"\r\n"[..]))
+ );
+ assert_parse!(
+ crlf(Streaming(&b"\r"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ crlf(Streaming(&b"\ra"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"\ra"[..]),
+ ErrorKind::CrLf
+ )))
+ );
+
+ assert_parse!(crlf(Streaming("\r\na")), Ok((Streaming("a"), "\r\n")));
+ assert_parse!(crlf(Streaming("\r")), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ crlf(Streaming("\ra")),
+ Err(Err::Error(error_position!(
+ Streaming("\ra"),
+ ErrorKind::CrLf
+ )))
+ );
+ }
+
+ #[test]
+ fn end_of_line() {
+ assert_parse!(
+ line_ending(Streaming(&b"\na"[..])),
+ Ok((Streaming(&b"a"[..]), &b"\n"[..]))
+ );
+ assert_parse!(
+ line_ending(Streaming(&b"\r\na"[..])),
+ Ok((Streaming(&b"a"[..]), &b"\r\n"[..]))
+ );
+ assert_parse!(
+ line_ending(Streaming(&b"\r"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ line_ending(Streaming(&b"\ra"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"\ra"[..]),
+ ErrorKind::CrLf
+ )))
+ );
+
+ assert_parse!(line_ending(Streaming("\na")), Ok((Streaming("a"), "\n")));
+ assert_parse!(
+ line_ending(Streaming("\r\na")),
+ Ok((Streaming("a"), "\r\n"))
+ );
+ assert_parse!(
+ line_ending(Streaming("\r")),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ line_ending(Streaming("\ra")),
+ Err(Err::Error(error_position!(
+ Streaming("\ra"),
+ ErrorKind::CrLf
+ )))
+ );
+ }
+
+ fn digit_to_i16(input: Streaming<&str>) -> IResult<Streaming<&str>, i16> {
+ use crate::bytes::one_of;
+
+ let i = input;
+ let (i, opt_sign) = opt(one_of("+-"))(i)?;
+ let sign = match opt_sign {
+ Some('+') => true,
+ Some('-') => false,
+ _ => true,
+ };
+
+ let (i, s) = match digit1::<_, crate::error::Error<_>, true>(i) {
+ Ok((i, s)) => (i, s),
+ Err(Err::Incomplete(i)) => return Err(Err::Incomplete(i)),
+ Err(_) => {
+ return Err(Err::Error(crate::error::Error::from_error_kind(
+ input,
+ ErrorKind::Digit,
+ )))
+ }
+ };
+ match s.parse_to() {
+ Some(n) => {
+ if sign {
+ Ok((i, n))
+ } else {
+ Ok((i, -n))
+ }
+ }
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ fn digit_to_u32(i: Streaming<&str>) -> IResult<Streaming<&str>, u32> {
+ let (i, s) = digit1(i)?;
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(crate::error::Error::from_error_kind(
+ i,
+ ErrorKind::Digit,
+ ))),
+ }
+ }
+
+ proptest! {
+ #[test]
+ fn ints(s in "\\PC*") {
+ let res1 = digit_to_i16(Streaming(&s));
+ let res2 = i16(Streaming(s.as_str()));
+ assert_eq!(res1, res2);
+ }
+
+ #[test]
+ fn uints(s in "\\PC*") {
+ let res1 = digit_to_u32(Streaming(&s));
+ let res2 = u32(Streaming(s.as_str()));
+ assert_eq!(res1, res2);
+ }
+ }
+}
diff --git a/vendor/nom8/src/combinator/mod.rs b/vendor/nom8/src/combinator/mod.rs
new file mode 100644
index 000000000..c3049faf7
--- /dev/null
+++ b/vendor/nom8/src/combinator/mod.rs
@@ -0,0 +1,1528 @@
+//! # List of parsers and combinators
+//!
+//! **Note**: this list is meant to provide a nicer way to find a nom parser than reading through the documentation on docs.rs. Function combinators are organized in module so they are a bit easier to find.
+//!
+//! Links present in this document will nearly always point to `complete` version of the parser. Most of the parsers also have a `streaming` version.
+//!
+//! ## Basic elements
+//!
+//! Those are used to recognize the lowest level elements of your grammar, like, "here is a dot", or "here is an big endian integer".
+//!
+//! | combinator | usage | input | output | comment |
+//! |---|---|---|---|---|
+//! | [one_of][crate::bytes::one_of] | `one_of("abc")` | `"abc"` | `Ok(("bc", 'a'))` |Matches one of the provided characters (works with non ASCII characters too)|
+//! | [none_of][crate::bytes::none_of] | `none_of("abc")` | `"xyab"` | `Ok(("yab", 'x'))` |Matches anything but the provided characters|
+//! | [tag][crate::bytes::tag] | `tag("hello")` | `"hello world"` | `Ok((" world", "hello"))` |Recognizes a specific suite of characters or bytes|
+//! | [tag_no_case][crate::bytes::tag_no_case] | `tag_no_case("hello")` | `"HeLLo World"` | `Ok((" World", "HeLLo"))` |Case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises|
+//! | [take][crate::bytes::take] | `take(4)` | `"hello"` | `Ok(("o", "hell"))` |Takes a specific number of bytes or characters|
+//! | [take_while][crate::bytes::take_while] | `take_while(is_alphabetic)` | `"abc123"` | `Ok(("123", "abc"))` |Returns the longest list of bytes for which the provided pattern matches. `take_while1` does the same, but must return at least one character|
+//! | [take_till][crate::bytes::take_till] | `take_till(is_alphabetic)` | `"123abc"` | `Ok(("abc", "123"))` |Returns the longest list of bytes or characters until the provided pattern matches. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till(f)` is equivalent to `take_while(\|c\| !f(c))`|
+//! | [take_until][crate::bytes::take_until] | `take_until("world")` | `"Hello world"` | `Ok(("world", "Hello "))` |Returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character|
+//!
+//! ## Choice combinators
+//!
+//! | combinator | usage | input | output | comment |
+//! |---|---|---|---|---|
+//! | [alt][crate::branch::alt] | `alt((tag("ab"), tag("cd")))` | `"cdef"` | `Ok(("ef", "cd"))` |Try a list of parsers and return the result of the first successful one|
+//! | [permutation][crate::branch::permutation] | `permutation(tag("ab"), tag("cd"), tag("12"))` | `"cd12abc"` | `Ok(("c", ("ab", "cd", "12"))` |Succeeds when all its child parser have succeeded, whatever the order|
+//!
+//! ## Sequence combinators
+//!
+//! | combinator | usage | input | output | comment |
+//! |---|---|---|---|---|
+//! | [delimited][crate::sequence::delimited] | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `Ok(("cd", "ab"))` ||
+//! | [preceded][crate::sequence::preceded] | `preceded(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "XY"))` ||
+//! | [terminated][crate::sequence::terminated] | `terminated(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", "ab"))` ||
+//! | [pair][crate::sequence::pair] | `pair(tag("ab"), tag("XY"))` | `"abXYZ"` | `Ok(("Z", ("ab", "XY")))` ||
+//! | [separated_pair][crate::sequence::separated_pair] | `separated_pair(tag("hello"), char(','), tag("world"))` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` ||
+//! | [`(...)` (tuples)][crate::Parser] | `(tag("ab"), tag("XY"), take(1))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
+//!
+//! ## Applying a parser multiple times
+//!
+//! | combinator | usage | input | output | comment |
+//! |---|---|---|---|---|
+//! | [count][crate::multi::count] | `count(take(2), 3)` | `"abcdefgh"` | `Ok(("gh", vec!["ab", "cd", "ef"]))` |Applies the child parser a specified number of times|
+//! | [many0][crate::multi::many0] | `many0(tag("ab"))` | `"abababc"` | `Ok(("c", vec!["ab", "ab", "ab"]))` |Applies the parser 0 or more times and returns the list of results in a Vec. `many1` does the same operation but must return at least one element|
+//! | [many_m_n][crate::multi::many_m_n] | `many_m_n(1, 3, tag("ab"))` | `"ababc"` | `Ok(("c", vec!["ab", "ab"]))` |Applies the parser between m and n times (n included) and returns the list of results in a Vec|
+//! | [many_till][crate::multi::many_till] | `many_till(tag( "ab" ), tag( "ef" ))` | `"ababefg"` | `Ok(("g", (vec!["ab", "ab"], "ef")))` |Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second|
+//! | [separated_list0][crate::multi::separated_list0] | `separated_list0(tag(","), tag("ab"))` | `"ab,ab,ab."` | `Ok((".", vec!["ab", "ab", "ab"]))` |`separated_list1` works like `separated_list0` but must returns at least one element|
+//! | [fold_many0][crate::multi::fold_many0] | `fold_many0(be_u8, \|\| 0, \|acc, item\| acc + item)` | `[1, 2, 3]` | `Ok(([], 6))` |Applies the parser 0 or more times and folds the list of return values. The `fold_many1` version must apply the child parser at least one time|
+//! | [fold_many_m_n][crate::multi::fold_many_m_n] | `fold_many_m_n(1, 2, be_u8, \|\| 0, \|acc, item\| acc + item)` | `[1, 2, 3]` | `Ok(([3], 3))` |Applies the parser between m and n times (n included) and folds the list of return value|
+//! | [length_count][crate::multi::length_count] | `length_count(number, tag("ab"))` | `"2ababab"` | `Ok(("ab", vec!["ab", "ab"]))` |Gets a number from the first parser, then applies the second parser that many times|
+//!
+//! ## Integers
+//!
+//! Parsing integers from binary formats can be done in two ways: With parser functions, or combinators with configurable endianness.
+//!
+//! The following parsers could be found on [docs.rs number section][number/complete/index].
+//!
+//! - **configurable endianness:** [`i16`][crate::number::i16], [`i32`][crate::number::i32], [`i64`][crate::number::i64], [`u16`][crate::number::u16], [`u32`][crate::number::u32], [`u64`][crate::number::u64] are combinators that take as argument a [`nom8::number::Endianness`][number/enum.Endianness], like this: `i16(endianness)`. If the parameter is `nom8::number::Endianness::Big`, parse a big endian `i16` integer, otherwise a little endian `i16` integer.
+//! - **fixed endianness**: The functions are prefixed by `be_` for big endian numbers, and by `le_` for little endian numbers, and the suffix is the type they parse to. As an example, `be_u32` parses a big endian unsigned integer stored in 32 bits.
+//! - [`be_f32`][crate::number::be_f32], [`be_f64`][crate::number::be_f64]: Big endian floating point numbers
+//! - [`le_f32`][crate::number::le_f32], [`le_f64`][crate::number::le_f64]: Little endian floating point numbers
+//! - [`be_i8`][crate::number::be_i8], [`be_i16`][crate::number::be_i16], [`be_i24`][crate::number::be_i24], [`be_i32`][crate::number::be_i32], [`be_i64`][crate::number::be_i64], [`be_i128`][crate::number::be_i128]: Big endian signed integers
+//! - [`be_u8`][crate::number::be_u8], [`be_u16`][crate::number::be_u16], [`be_u24`][crate::number::be_u24], [`be_u32`][crate::number::be_u32], [`be_u64`][crate::number::be_u64], [`be_u128`][crate::number::be_u128]: Big endian unsigned integers
+//! - [`le_i8`][crate::number::le_i8], [`le_i16`][crate::number::le_i16], [`le_i24`][crate::number::le_i24], [`le_i32`][crate::number::le_i32], [`le_i64`][crate::number::le_i64], [`le_i128`][crate::number::le_i128]: Little endian signed integers
+//! - [`le_u8`][crate::number::le_u8], [`le_u16`][crate::number::le_u16], [`le_u24`][crate::number::le_u24], [`le_u32`][crate::number::le_u32], [`le_u64`][crate::number::le_u64], [`le_u128`][crate::number::le_u128]: Little endian unsigned integers
+//!
+//! ## Streaming related
+//!
+//! - [`eof`][eof]: Returns its input if it is at the end of input data
+//! - [`Parser::complete`][Parser::complete()]: Replaces an `Incomplete` returned by the child parser with an `Error`
+//!
+//! ## Modifiers
+//!
+//! - [`cond`][cond]: Conditional combinator. Wraps another parser and calls it if the condition is met
+//! - [`Parser::flat_map`][crate::Parser::flat_map]: method to map a new parser from the output of the first parser, then apply that parser over the rest of the input
+//! - [`Parser::value`][crate::Parser::value]: method to replace the result of a parser
+//! - [`Parser::map`][crate::Parser::map]: method to map a function on the result of a parser
+//! - [`Parser::and_then`][crate::Parser::and_then]: Applies a second parser over the output of the first one
+//! - [`Parser::map_opt`][Parser::map_opt]: Maps a function returning an `Option` on the output of a parser
+//! - [`Parser::map_res`][Parser::map_res]: Maps a function returning a `Result` on the output of a parser
+//! - [`not`][not]: Returns a result only if the embedded parser returns `Error` or `Incomplete`. Does not consume the input
+//! - [`opt`][opt]: Make the underlying parser optional
+//! - [`peek`][peek]: Returns a result without consuming the input
+//! - [`Parser::recognize`][Parser::recognize]: If the child parser was successful, return the consumed input as the produced value
+//! - [`Parser::with_recognized`][Parser::with_recognized]: If the child parser was successful, return a tuple of the consumed input and the produced output.
+//! - [`Parser::span`][Parser::span]: If the child parser was successful, return the location of the consumed input as the produced value
+//! - [`Parser::with_span`][Parser::with_span]: If the child parser was successful, return a tuple of the location of the consumed input and the produced output.
+//! - [`Parser::verify`]: Returns the result of the child parser if it satisfies a verification function
+//!
+//! ## Error management and debugging
+//!
+//! - [`Parser::context`]: Add context to the error if the parser fails
+//! - [`Parser::dbg_err`]: Prints a message and the input if the parser fails
+//!
+//! ## Text parsing
+//!
+//! - [`escaped`][crate::bytes::escaped]: Matches a byte string with escaped characters
+//! - [`escaped_transform`][crate::bytes::escaped_transform]: Matches a byte string with escaped characters, and returns a new string with the escaped characters replaced
+//!
+//! ## Binary format parsing
+//!
+//! - [`length_data`][crate::multi::length_data]: Gets a number from the first parser, then takes a subslice of the input of that size, and returns that subslice
+//! - [`length_value`][crate::multi::length_value]: Gets a number from the first parser, takes a subslice of the input of that size, then applies the second parser on that subslice. If the second parser returns `Incomplete`, `length_value` will return an error
+//!
+//! ## Bit stream parsing
+//!
+//! - [`bits`][crate::bits::bits]: Transforms the current input type (byte slice `&[u8]`) to a bit stream on which bit specific parsers and more general combinators can be applied
+//! - [`bytes`][crate::bits/::bytes]: Transforms its bits stream input back into a byte slice for the underlying parser
+//!
+//! ## Remaining combinators
+//!
+//! - [`success`][success]: Returns a value without consuming any input, always succeeds
+//! - [`fail`][fail]: Inversion of `success`. Always fails.
+//! - [`Parser::by_ref`]: Allow moving `&mut impl Parser` into other parsers
+//!
+//! ## Character test functions
+//!
+//! Use these functions with a combinator like `take_while`:
+//!
+//! - [`AsChar::is_alpha`][crate::input::AsChar::is_alpha]: Tests if byte is ASCII alphabetic: `[A-Za-z]`
+//! - [`AsChar::is_alphanum`][crate::input::AsChar::is_alphanum]: Tests if byte is ASCII alphanumeric: `[A-Za-z0-9]`
+//! - [`AsChar::is_dec_digit`][crate::input::AsChar::is_dec_digit]: Tests if byte is ASCII digit: `[0-9]`
+//! - [`AsChar::is_hex_digit`][crate::input::AsChar::is_hex_digit]: Tests if byte is ASCII hex digit: `[0-9A-Fa-f]`
+//! - [`AsChar::is_oct_digit`][crate::input::AsChar::is_oct_digit]: Tests if byte is ASCII octal digit: `[0-7]`
+//! - [`AsChar::is_space`][crate::input::AsChar::is_space]: Tests if byte is ASCII space or tab: `[ \t]`
+//! - [`AsChar::is_newline`][crate::input::AsChar::is_newline]: Tests if byte is ASCII newline: `[\n]`
+//!
+//! Alternatively there are ready to use functions:
+//!
+//! - [`alpha0`][crate::character::alpha0]: Recognizes zero or more lowercase and uppercase alphabetic characters: `[a-zA-Z]`. [`alpha1`][crate::character::alpha1] does the same but returns at least one character
+//! - [`alphanumeric0`][crate::character::alphanumeric0]: Recognizes zero or more numerical and alphabetic characters: `[0-9a-zA-Z]`. [`alphanumeric1`][crate::character::alphanumeric1] does the same but returns at least one character
+//! - [`any`][crate::bytes::any]: Matches one token
+//! - [`crlf`][crate::character::crlf]: Recognizes the string `\r\n`
+//! - [`digit0`][crate::character::digit0]: Recognizes zero or more numerical characters: `[0-9]`. [`digit1`][crate::character::digit1] does the same but returns at least one character
+//! - [`f64`][crate::character::f64]: Recognizes floating point number in a byte string and returns a `f64`
+//! - [`f32`][crate::character::f32]: Recognizes floating point number in a byte string and returns a `f32`
+//! - [`hex_digit0`][crate::character::hex_digit0]: Recognizes zero or more hexadecimal numerical characters: `[0-9A-Fa-f]`. [`hex_digit1`][crate::character::hex_digit1] does the same but returns at least one character
+//! - [`hex_u32`][crate::number::hex_u32]: Recognizes a hex-encoded integer
+//! - [`line_ending`][crate::character::line_ending]: Recognizes an end of line (both `\n` and `\r\n`)
+//! - [`multispace0`][crate::character::multispace0]: Recognizes zero or more spaces, tabs, carriage returns and line feeds. [`multispace1`][crate::character::multispace1] does the same but returns at least one character
+//! - [`newline`][crate::character::newline]: Matches a newline character `\n`
+//! - [`not_line_ending`][crate::character::not_line_ending]: Recognizes a string of any char except `\r` or `\n`
+//! - [`oct_digit0`][crate::character::oct_digit0]: Recognizes zero or more octal characters: `[0-7]`. [`oct_digit1`][crate::character::oct_digit1] does the same but returns at least one character
+//! - [`rest`][rest]: Return the remaining input
+//! - [`space0`][crate::character::space0]: Recognizes zero or more spaces and tabs. [`space1`][crate::character::space1] does the same but returns at least one character
+//! - [`tab`][crate::character::tab]: Matches a tab character `\t`
+
+#![allow(unused_imports)]
+
+#[cfg(feature = "alloc")]
+use crate::lib::std::boxed::Box;
+
+use crate::error::{ErrorKind, FromExternalError, ParseError};
+use crate::input::IntoOutput;
+use crate::input::{AsChar, InputIter, InputLength, InputTakeAtPosition, Location, ParseTo};
+use crate::input::{Compare, CompareResult, Offset, Slice};
+use crate::lib::std::borrow::Borrow;
+use crate::lib::std::convert;
+#[cfg(feature = "std")]
+use crate::lib::std::fmt::Debug;
+use crate::lib::std::mem::transmute;
+use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
+use crate::IntoOutputIResult;
+use crate::*;
+
+#[cfg(test)]
+mod tests;
+
+/// Return the remaining input.
+///
+/// ```rust
+/// # use nom8::error::ErrorKind;
+/// use nom8::combinator::rest;
+/// assert_eq!(rest::<_,(_, ErrorKind)>("abc"), Ok(("", "abc")));
+/// assert_eq!(rest::<_,(_, ErrorKind)>(""), Ok(("", "")));
+/// ```
+#[inline]
+pub fn rest<T, E: ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>>,
+ T: InputLength,
+ T: IntoOutput,
+{
+ Ok((input.slice(input.input_len()..), input)).into_output()
+}
+
+/// Return the length of the remaining input.
+///
+/// ```rust
+/// # use nom8::error::ErrorKind;
+/// use nom8::combinator::rest_len;
+/// assert_eq!(rest_len::<_,(_, ErrorKind)>("abc"), Ok(("abc", 3)));
+/// assert_eq!(rest_len::<_,(_, ErrorKind)>(""), Ok(("", 0)));
+/// ```
+#[inline]
+pub fn rest_len<T, E: ParseError<T>>(input: T) -> IResult<T, usize, E>
+where
+ T: InputLength,
+{
+ let len = input.input_len();
+ Ok((input, len))
+}
+
+/// Implementation of [`Parser::by_ref`][Parser::by_ref]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct ByRef<'p, P> {
+ p: &'p mut P,
+}
+
+impl<'p, P> ByRef<'p, P> {
+ pub(crate) fn new(p: &'p mut P) -> Self {
+ Self { p }
+ }
+}
+
+impl<'p, I, O, E, P: Parser<I, O, E>> Parser<I, O, E> for ByRef<'p, P> {
+ fn parse(&mut self, i: I) -> IResult<I, O, E> {
+ self.p.parse(i)
+ }
+}
+
+/// Maps a function on the result of a parser.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::map`]
+///
+/// ```rust
+/// use nom8::{Err,error::ErrorKind, IResult,Parser};
+/// use nom8::character::digit1;
+/// use nom8::combinator::map;
+/// # fn main() {
+///
+/// let mut parser = map(digit1, |s: &str| s.len());
+///
+/// // the parser will count how many characters were returned by digit1
+/// assert_eq!(parser.parse("123456"), Ok(("", 6)));
+///
+/// // this will fail if digit1 fails
+/// assert_eq!(parser.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::map")]
+pub fn map<I, O1, O2, E, F, G>(mut parser: F, mut f: G) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> O2,
+{
+ move |input: I| {
+ let (input, o1) = parser.parse(input)?;
+ Ok((input, f(o1)))
+ }
+}
+
+/// Implementation of [`Parser::map`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Map<F, G, O1> {
+ f: F,
+ g: G,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, G, O1> Map<F, G, O1> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self {
+ f,
+ g,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> O2> Parser<I, O2, E> for Map<F, G, O1> {
+ fn parse(&mut self, i: I) -> IResult<I, O2, E> {
+ match self.f.parse(i) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, (self.g)(o))),
+ }
+ }
+}
+
+/// Applies a function returning a `Result` over the result of a parser.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::map_res`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::character::digit1;
+/// use nom8::combinator::map_res;
+/// # fn main() {
+///
+/// let mut parse = map_res(digit1, |s: &str| s.parse::<u8>());
+///
+/// // the parser will convert the result of digit1 to a number
+/// assert_eq!(parse("123"), Ok(("", 123)));
+///
+/// // this will fail if digit1 fails
+/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+///
+/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
+/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::map_res")]
+pub fn map_res<I: Clone, O1, O2, E: FromExternalError<I, E2>, E2, F, G>(
+ mut parser: F,
+ mut f: G,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> Result<O2, E2>,
+{
+ move |input: I| {
+ let i = input.clone();
+ let (input, o1) = parser.parse(input)?;
+ match f(o1) {
+ Ok(o2) => Ok((input, o2)),
+ Err(e) => Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, e))),
+ }
+ }
+}
+
+/// Implementation of [`Parser::map_res`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct MapRes<F, G, O1> {
+ f: F,
+ g: G,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, G, O1> MapRes<F, G, O1> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self {
+ f,
+ g,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<I, O1, O2, E, E2, F, G> Parser<I, O2, E> for MapRes<F, G, O1>
+where
+ I: Clone,
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> Result<O2, E2>,
+ E: FromExternalError<I, E2>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, O2, E> {
+ let i = input.clone();
+ let (input, o1) = self.f.parse(input)?;
+ match (self.g)(o1) {
+ Ok(o2) => Ok((input, o2)),
+ Err(e) => Err(Err::Error(E::from_external_error(i, ErrorKind::MapRes, e))),
+ }
+ }
+}
+
+/// Applies a function returning an `Option` over the result of a parser.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::map_opt`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::character::digit1;
+/// use nom8::combinator::map_opt;
+/// # fn main() {
+///
+/// let mut parse = map_opt(digit1, |s: &str| s.parse::<u8>().ok());
+///
+/// // the parser will convert the result of digit1 to a number
+/// assert_eq!(parse("123"), Ok(("", 123)));
+///
+/// // this will fail if digit1 fails
+/// assert_eq!(parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+///
+/// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
+/// assert_eq!(parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::map_res")]
+pub fn map_opt<I: Clone, O1, O2, E: ParseError<I>, F, G>(
+ mut parser: F,
+ mut f: G,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> Option<O2>,
+{
+ move |input: I| {
+ let i = input.clone();
+ let (input, o1) = parser.parse(input)?;
+ match f(o1) {
+ Some(o2) => Ok((input, o2)),
+ None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
+ }
+ }
+}
+
+/// Implementation of [`Parser::map_opt`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct MapOpt<F, G, O1> {
+ f: F,
+ g: G,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, G, O1> MapOpt<F, G, O1> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self {
+ f,
+ g,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<I, O1, O2, E, F, G> Parser<I, O2, E> for MapOpt<F, G, O1>
+where
+ I: Clone,
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> Option<O2>,
+ E: ParseError<I>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, O2, E> {
+ let i = input.clone();
+ let (input, o1) = self.f.parse(input)?;
+ match (self.g)(o1) {
+ Some(o2) => Ok((input, o2)),
+ None => Err(Err::Error(E::from_error_kind(i, ErrorKind::MapOpt))),
+ }
+ }
+}
+
+/// Applies a parser over the result of another one.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::and_then`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::character::digit1;
+/// use nom8::bytes::take;
+/// use nom8::combinator::map_parser;
+/// # fn main() {
+///
+/// let mut parse = map_parser(take(5u8), digit1);
+///
+/// assert_eq!(parse("12345"), Ok(("", "12345")));
+/// assert_eq!(parse("123ab"), Ok(("", "123")));
+/// assert_eq!(parse("123"), Err(Err::Error(("123", ErrorKind::Eof))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::and_then")]
+pub fn map_parser<I, O1, O2, E: ParseError<I>, F, G>(
+ mut parser: F,
+ mut applied_parser: G,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<O1, O2, E>,
+{
+ move |input: I| {
+ let (input, o1) = parser.parse(input)?;
+ let (_, o2) = applied_parser.parse(o1)?;
+ Ok((input, o2))
+ }
+}
+
+/// Implementation of [`Parser::and_then`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct AndThen<F, G, O1> {
+ f: F,
+ g: G,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, G, O1> AndThen<F, G, O1> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self {
+ f,
+ g,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<O1, O2, E>> Parser<I, O2, E>
+ for AndThen<F, G, O1>
+{
+ fn parse(&mut self, i: I) -> IResult<I, O2, E> {
+ let (i, o1) = self.f.parse(i)?;
+ let (_, o2) = self.g.parse(o1)?;
+ Ok((i, o2))
+ }
+}
+
+/// Creates a new parser from the output of the first parser, then apply that parser over the rest of the input.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::flat_map`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::bytes::take;
+/// use nom8::number::u8;
+/// use nom8::combinator::flat_map;
+/// # fn main() {
+///
+/// let mut parse = flat_map(u8, take);
+///
+/// assert_eq!(parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
+/// assert_eq!(parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::flat_map")]
+pub fn flat_map<I, O1, O2, E: ParseError<I>, F, G, H>(
+ mut parser: F,
+ mut applied_parser: G,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: FnMut(O1) -> H,
+ H: Parser<I, O2, E>,
+{
+ move |input: I| {
+ let (input, o1) = parser.parse(input)?;
+ applied_parser(o1).parse(input)
+ }
+}
+
+/// Implementation of [`Parser::flat_map`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct FlatMap<F, G, O1> {
+ f: F,
+ g: G,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, G, O1> FlatMap<F, G, O1> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self {
+ f,
+ g,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Fn(O1) -> H, H: Parser<I, O2, E>> Parser<I, O2, E>
+ for FlatMap<F, G, O1>
+{
+ fn parse(&mut self, i: I) -> IResult<I, O2, E> {
+ let (i, o1) = self.f.parse(i)?;
+ (self.g)(o1).parse(i)
+ }
+}
+
+/// Optional parser, will return `None` on [`Err::Error`].
+///
+/// To chain an error up, see [`cut`].
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::opt;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// fn parser(i: &str) -> IResult<&str, Option<&str>> {
+/// opt(alpha1)(i)
+/// }
+///
+/// assert_eq!(parser("abcd;"), Ok((";", Some("abcd"))));
+/// assert_eq!(parser("123;"), Ok(("123;", None)));
+/// # }
+/// ```
+pub fn opt<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, Option<O>, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match f.parse(input) {
+ Ok((i, o)) => Ok((i, Some(o))),
+ Err(Err::Error(_)) => Ok((i, None)),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// Implementation of [`Parser::and`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct And<F, G> {
+ f: F,
+ g: G,
+}
+
+impl<F, G> And<F, G> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self { f, g }
+ }
+}
+
+impl<'a, I, O1, O2, E, F: Parser<I, O1, E>, G: Parser<I, O2, E>> Parser<I, (O1, O2), E>
+ for And<F, G>
+{
+ fn parse(&mut self, i: I) -> IResult<I, (O1, O2), E> {
+ let (i, o1) = self.f.parse(i)?;
+ let (i, o2) = self.g.parse(i)?;
+ Ok((i, (o1, o2)))
+ }
+}
+
+/// Implementation of [`Parser::or`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Or<F, G> {
+ f: F,
+ g: G,
+}
+
+impl<F, G> Or<F, G> {
+ pub(crate) fn new(f: F, g: G) -> Self {
+ Self { f, g }
+ }
+}
+
+impl<'a, I: Clone, O, E: crate::error::ParseError<I>, F: Parser<I, O, E>, G: Parser<I, O, E>>
+ Parser<I, O, E> for Or<F, G>
+{
+ fn parse(&mut self, i: I) -> IResult<I, O, E> {
+ match self.f.parse(i.clone()) {
+ Err(Err::Error(e1)) => match self.g.parse(i) {
+ Err(Err::Error(e2)) => Err(Err::Error(e1.or(e2))),
+ res => res,
+ },
+ res => res,
+ }
+ }
+}
+
+/// Calls the parser if the condition is met.
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, IResult};
+/// use nom8::combinator::cond;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// fn parser(b: bool, i: &str) -> IResult<&str, Option<&str>> {
+/// cond(b, alpha1)(i)
+/// }
+///
+/// assert_eq!(parser(true, "abcd;"), Ok((";", Some("abcd"))));
+/// assert_eq!(parser(false, "abcd;"), Ok(("abcd;", None)));
+/// assert_eq!(parser(true, "123;"), Err(Err::Error(Error::new("123;", ErrorKind::Alpha))));
+/// assert_eq!(parser(false, "123;"), Ok(("123;", None)));
+/// # }
+/// ```
+pub fn cond<I, O, E: ParseError<I>, F>(
+ b: bool,
+ mut f: F,
+) -> impl FnMut(I) -> IResult<I, Option<O>, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ if b {
+ match f.parse(input) {
+ Ok((i, o)) => Ok((i, Some(o))),
+ Err(e) => Err(e),
+ }
+ } else {
+ Ok((input, None))
+ }
+ }
+}
+
+/// Tries to apply its parser without consuming the input.
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::peek;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// let mut parser = peek(alpha1);
+///
+/// assert_eq!(parser("abcd;"), Ok(("abcd;", "abcd")));
+/// assert_eq!(parser("123;"), Err(Err::Error(("123;", ErrorKind::Alpha))));
+/// # }
+/// ```
+pub fn peek<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match f.parse(input) {
+ Ok((_, o)) => Ok((i, o)),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// returns its input if it is at the end of input data
+///
+/// When we're at the end of the data, this combinator
+/// will succeed
+///
+/// ```
+/// # use std::str;
+/// # use nom8::{Err, error::ErrorKind, IResult};
+/// # use nom8::combinator::eof;
+///
+/// # fn main() {
+/// let parser = eof;
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Eof))));
+/// assert_eq!(parser(""), Ok(("", "")));
+/// # }
+/// ```
+pub fn eof<I, E: ParseError<I>>(input: I) -> IResult<I, <I as IntoOutput>::Output, E>
+where
+ I: InputLength,
+ I: Clone,
+ I: IntoOutput,
+{
+ if input.input_len() == 0 {
+ let clone = input.clone();
+ Ok((input, clone)).into_output()
+ } else {
+ Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof)))
+ }
+}
+
+/// Transforms Incomplete into `Error`.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::complete`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult, input::Streaming};
+/// use nom8::bytes::take;
+/// use nom8::combinator::complete;
+/// # fn main() {
+///
+/// let mut parser = complete(take(5u8));
+///
+/// assert_eq!(parser(Streaming("abcdefg")), Ok((Streaming("fg"), "abcde")));
+/// assert_eq!(parser(Streaming("abcd")), Err(Err::Error((Streaming("abcd"), ErrorKind::Complete))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::complete")]
+pub fn complete<I: Clone, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match f.parse(input) {
+ Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))),
+ rest => rest,
+ }
+ }
+}
+
+/// Implementation of [`Parser::complete`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Complete<F> {
+ f: F,
+}
+
+impl<F> Complete<F> {
+ pub(crate) fn new(f: F) -> Self {
+ Self { f }
+ }
+}
+
+impl<F, I, O, E> Parser<I, O, E> for Complete<F>
+where
+ I: Clone,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, O, E> {
+ let i = input.clone();
+ match (self.f).parse(input) {
+ Err(Err::Incomplete(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Complete))),
+ rest => rest,
+ }
+ }
+}
+
+/// Succeeds if all the input has been consumed by its child parser.
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::all_consuming;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// let mut parser = all_consuming(alpha1);
+///
+/// assert_eq!(parser("abcd"), Ok(("", "abcd")));
+/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::Eof))));
+/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
+/// # }
+/// ```
+pub fn all_consuming<I, O, E: ParseError<I>, F>(mut f: F) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ I: InputLength,
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let (input, res) = f.parse(input)?;
+ if input.input_len() == 0 {
+ Ok((input, res))
+ } else {
+ Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof)))
+ }
+ }
+}
+
+/// Returns the result of the child parser if it satisfies a verification function.
+///
+/// The verification function takes as argument a reference to the output of the
+/// parser.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::map`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::verify;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// let mut parser = verify(alpha1, |s: &str| s.len() == 4);
+///
+/// assert_eq!(parser("abcd"), Ok(("", "abcd")));
+/// assert_eq!(parser("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify))));
+/// assert_eq!(parser("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::verify")]
+pub fn verify<I: Clone, O1, O2, E: ParseError<I>, F, G>(
+ mut first: F,
+ second: G,
+) -> impl FnMut(I) -> IResult<I, O1, E>
+where
+ F: Parser<I, O1, E>,
+ G: Fn(&O2) -> bool,
+ O1: Borrow<O2>,
+ O2: ?Sized,
+{
+ move |input: I| {
+ let i = input.clone();
+ let (input, o) = first.parse(input)?;
+
+ if second(o.borrow()) {
+ Ok((input, o))
+ } else {
+ Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)))
+ }
+ }
+}
+
+/// Implementation of [`Parser::verify`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Verify<F, G, O2: ?Sized> {
+ first: F,
+ second: G,
+ phantom: core::marker::PhantomData<O2>,
+}
+
+impl<F, G, O2: ?Sized> Verify<F, G, O2> {
+ pub(crate) fn new(first: F, second: G) -> Self {
+ Self {
+ first,
+ second,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<I, O1, O2, E, F: Parser<I, O1, E>, G> Parser<I, O1, E> for Verify<F, G, O2>
+where
+ I: Clone,
+ E: ParseError<I>,
+ F: Parser<I, O1, E>,
+ G: Fn(&O2) -> bool,
+ O1: Borrow<O2>,
+ O2: ?Sized,
+{
+ fn parse(&mut self, input: I) -> IResult<I, O1, E> {
+ let i = input.clone();
+ let (input, o) = (self.first).parse(input)?;
+
+ if (self.second)(o.borrow()) {
+ Ok((input, o))
+ } else {
+ Err(Err::Error(E::from_error_kind(i, ErrorKind::Verify)))
+ }
+ }
+}
+
+/// Returns the provided value if the child parser succeeds.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::value`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::value;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// let mut parser = value(1234, alpha1);
+///
+/// assert_eq!(parser("abcd"), Ok(("", 1234)));
+/// assert_eq!(parser("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::value")]
+pub fn value<I, O1: Clone, O2, E: ParseError<I>, F>(
+ val: O1,
+ mut parser: F,
+) -> impl FnMut(I) -> IResult<I, O1, E>
+where
+ F: Parser<I, O2, E>,
+{
+ move |input: I| parser.parse(input).map(|(i, _)| (i, val.clone()))
+}
+
+/// Implementation of [`Parser::value`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Value<F, O1, O2> {
+ parser: F,
+ val: O2,
+ phantom: core::marker::PhantomData<O1>,
+}
+
+impl<F, O1, O2> Value<F, O1, O2> {
+ pub(crate) fn new(parser: F, val: O2) -> Self {
+ Self {
+ parser,
+ val,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<I, O1, O2: Clone, E: ParseError<I>, F: Parser<I, O1, E>> Parser<I, O2, E>
+ for Value<F, O1, O2>
+{
+ fn parse(&mut self, input: I) -> IResult<I, O2, E> {
+ (self.parser)
+ .parse(input)
+ .map(|(i, _)| (i, self.val.clone()))
+ }
+}
+
+/// Succeeds if the child parser returns an error.
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::not;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// let mut parser = not(alpha1);
+///
+/// assert_eq!(parser("123"), Ok(("123", ())));
+/// assert_eq!(parser("abcd"), Err(Err::Error(("abcd", ErrorKind::Not))));
+/// # }
+/// ```
+pub fn not<I: Clone, O, E: ParseError<I>, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, (), E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match parser.parse(input) {
+ Ok(_) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Not))),
+ Err(Err::Error(_)) => Ok((i, ())),
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// If the child parser was successful, return the consumed input as produced value.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::recognize`]
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::recognize;
+/// use nom8::character::{alpha1};
+/// use nom8::sequence::separated_pair;
+/// # fn main() {
+///
+/// let mut parser = recognize(separated_pair(alpha1, ',', alpha1));
+///
+/// assert_eq!(parser("abcd,efgh"), Ok(("", "abcd,efgh")));
+/// assert_eq!(parser("abcd;"),Err(Err::Error((";", ErrorKind::OneOf))));
+/// # }
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::recognize")]
+pub fn recognize<I, O, E: ParseError<I>, F>(
+ mut parser: F,
+) -> impl FnMut(I) -> IResult<I, <I as IntoOutput>::Output, E>
+where
+ I: Clone,
+ I: Offset,
+ I: Slice<RangeTo<usize>>,
+ I: IntoOutput,
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match parser.parse(i) {
+ Ok((i, _)) => {
+ let index = input.offset(&i);
+ Ok((i, input.slice(..index))).into_output()
+ }
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// Implementation of [`Parser::recognize`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Recognize<F, O> {
+ parser: F,
+ o: core::marker::PhantomData<O>,
+}
+
+impl<F, O> Recognize<F, O> {
+ pub(crate) fn new(parser: F) -> Self {
+ Self {
+ parser,
+ o: Default::default(),
+ }
+ }
+}
+
+impl<I, O, E, F> Parser<I, <I as IntoOutput>::Output, E> for Recognize<F, O>
+where
+ I: Clone,
+ I: Offset,
+ I: Slice<RangeTo<usize>>,
+ I: IntoOutput,
+ E: ParseError<I>,
+ F: Parser<I, O, E>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, <I as IntoOutput>::Output, E> {
+ let i = input.clone();
+ match (self.parser).parse(i) {
+ Ok((i, _)) => {
+ let index = input.offset(&i);
+ Ok((i, input.slice(..index))).into_output()
+ }
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// if the child parser was successful, return the consumed input with the output
+/// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it
+/// returns the parser output as well.
+///
+/// This can be useful especially in cases where the output is not the same type
+/// as the input, or the input is a user defined type.
+///
+/// Returned tuple is of the format `(consumed input, produced output)`.
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::with_recognized`] (output ordering is changed)
+///
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::combinator::{consumed, value, recognize, map};
+/// use nom8::character::{alpha1};
+/// use nom8::bytes::tag;
+/// use nom8::sequence::separated_pair;
+///
+/// fn inner_parser(input: &str) -> IResult<&str, bool> {
+/// value(true, tag("1234"))(input)
+/// }
+///
+/// # fn main() {
+///
+/// let mut consumed_parser = consumed(value(true, separated_pair(alpha1, ',', alpha1)));
+///
+/// assert_eq!(consumed_parser("abcd,efgh1"), Ok(("1", ("abcd,efgh", true))));
+/// assert_eq!(consumed_parser("abcd;"),Err(Err::Error((";", ErrorKind::OneOf))));
+///
+///
+/// // the first output (representing the consumed input)
+/// // should be the same as that of the `recognize` parser.
+/// let mut recognize_parser = recognize(inner_parser);
+/// let mut consumed_parser = consumed(inner_parser).map(|(consumed, output)| consumed);
+///
+/// assert_eq!(recognize_parser("1234"), consumed_parser.parse("1234"));
+/// assert_eq!(recognize_parser("abcd"), consumed_parser.parse("abcd"));
+/// # }
+/// ```
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `Parser::with_recognized (output ordering is changed)"
+)]
+pub fn consumed<I, O, F, E>(
+ mut parser: F,
+) -> impl FnMut(I) -> IResult<I, (<I as IntoOutput>::Output, O), E>
+where
+ I: Clone + Offset + Slice<RangeTo<usize>>,
+ I: IntoOutput,
+ E: ParseError<I>,
+ F: Parser<I, O, E>,
+{
+ move |input: I| {
+ let i = input.clone();
+ match parser.parse(i) {
+ Ok((remaining, result)) => {
+ let index = input.offset(&remaining);
+ let consumed = input.slice(..index).into_output();
+ Ok((remaining, (consumed, result)))
+ }
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// Implementation of [`Parser::with_recognized`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct WithRecognized<F, O> {
+ parser: F,
+ o: core::marker::PhantomData<O>,
+}
+
+impl<F, O> WithRecognized<F, O> {
+ pub(crate) fn new(parser: F) -> Self {
+ Self {
+ parser,
+ o: Default::default(),
+ }
+ }
+}
+
+impl<I, O, E, F> Parser<I, (O, <I as IntoOutput>::Output), E> for WithRecognized<F, O>
+where
+ I: Clone,
+ I: Offset,
+ I: Slice<RangeTo<usize>>,
+ I: IntoOutput,
+ E: ParseError<I>,
+ F: Parser<I, O, E>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, (O, <I as IntoOutput>::Output), E> {
+ let i = input.clone();
+ match (self.parser).parse(i) {
+ Ok((remaining, result)) => {
+ let index = input.offset(&remaining);
+ let consumed = input.slice(..index).into_output();
+ Ok((remaining, (result, consumed)))
+ }
+ Err(e) => Err(e),
+ }
+ }
+}
+
+/// Implementation of [`Parser::span`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Span<F, O> {
+ parser: F,
+ o: core::marker::PhantomData<O>,
+}
+
+impl<F, O> Span<F, O> {
+ pub(crate) fn new(parser: F) -> Self {
+ Self {
+ parser,
+ o: Default::default(),
+ }
+ }
+}
+
+impl<I, O, E, F> Parser<I, Range<usize>, E> for Span<F, O>
+where
+ I: Clone + Location,
+ E: ParseError<I>,
+ F: Parser<I, O, E>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, Range<usize>, E> {
+ let start = input.location();
+ self.parser.parse(input).map(move |(remaining, _)| {
+ let end = remaining.location();
+ (remaining, (start..end))
+ })
+ }
+}
+
+/// Implementation of [`Parser::with_span`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct WithSpan<F, O> {
+ parser: F,
+ o: core::marker::PhantomData<O>,
+}
+
+impl<F, O> WithSpan<F, O> {
+ pub(crate) fn new(parser: F) -> Self {
+ Self {
+ parser,
+ o: Default::default(),
+ }
+ }
+}
+
+impl<I, O, E, F> Parser<I, (O, Range<usize>), E> for WithSpan<F, O>
+where
+ I: Clone + Location,
+ E: ParseError<I>,
+ F: Parser<I, O, E>,
+{
+ fn parse(&mut self, input: I) -> IResult<I, (O, Range<usize>), E> {
+ let start = input.location();
+ self.parser.parse(input).map(move |(remaining, output)| {
+ let end = remaining.location();
+ (remaining, (output, (start..end)))
+ })
+ }
+}
+
+/// Transforms an [`Err::Error`] (recoverable) to [`Err::Failure`] (unrecoverable)
+///
+/// This commits the parse result, preventing alternative branch paths like with
+/// [`nom8::branch::alt`][crate::branch::alt].
+///
+/// # Example
+///
+/// Without `cut`:
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// # use nom8::bytes::one_of;
+/// # use nom8::character::digit1;
+/// # use nom8::combinator::rest;
+/// # use nom8::branch::alt;
+/// # use nom8::sequence::preceded;
+/// # fn main() {
+///
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alt((
+/// preceded(one_of("+-"), digit1),
+/// rest
+/// ))(input)
+/// }
+///
+/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
+/// assert_eq!(parser("ab"), Ok(("", "ab")));
+/// assert_eq!(parser("+"), Ok(("", "+")));
+/// # }
+/// ```
+///
+/// With `cut`:
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult, error::Error};
+/// # use nom8::bytes::one_of;
+/// # use nom8::character::digit1;
+/// # use nom8::combinator::rest;
+/// # use nom8::branch::alt;
+/// # use nom8::sequence::preceded;
+/// use nom8::combinator::cut;
+/// # fn main() {
+///
+/// fn parser(input: &str) -> IResult<&str, &str> {
+/// alt((
+/// preceded(one_of("+-"), cut(digit1)),
+/// rest
+/// ))(input)
+/// }
+///
+/// assert_eq!(parser("+10 ab"), Ok((" ab", "10")));
+/// assert_eq!(parser("ab"), Ok(("", "ab")));
+/// assert_eq!(parser("+"), Err(Err::Failure(Error { input: "", code: ErrorKind::Digit })));
+/// # }
+/// ```
+pub fn cut<I, O, E: ParseError<I>, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |input: I| match parser.parse(input) {
+ Err(Err::Error(e)) => Err(Err::Failure(e)),
+ rest => rest,
+ }
+}
+
+/// automatically converts the child parser's result to another type
+///
+/// it will be able to convert the output value and the error value
+/// as long as the `Into` implementations are available
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::output_into`] and [`Parser::err_into`]
+///
+/// ```rust
+/// # use nom8::IResult;
+/// use nom8::combinator::into;
+/// use nom8::character::alpha1;
+/// # fn main() {
+///
+/// fn parser1(i: &str) -> IResult<&str, &str> {
+/// alpha1(i)
+/// }
+///
+/// let mut parser2 = into(parser1);
+///
+/// // the parser converts the &str output of the child parser into a Vec<u8>
+/// let bytes: IResult<&str, Vec<u8>> = parser2("abcd");
+/// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
+/// # }
+/// ```
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `Parser::output_into` and `Parser::err_into`"
+)]
+pub fn into<I, O1, O2, E1, E2, F>(mut parser: F) -> impl FnMut(I) -> IResult<I, O2, E2>
+where
+ O1: convert::Into<O2>,
+ E1: convert::Into<E2>,
+ E1: ParseError<I>,
+ E2: ParseError<I>,
+ F: Parser<I, O1, E1>,
+{
+ //map(parser, Into::into)
+ move |input: I| match parser.parse(input) {
+ Ok((i, o)) => Ok((i, o.into())),
+ Err(Err::Error(e)) => Err(Err::Error(e.into())),
+ Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
+ Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
+ }
+}
+
+/// Implementation of [`Parser::output_into`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct OutputInto<F, O1, O2: From<O1>> {
+ f: F,
+ phantom_out1: core::marker::PhantomData<O1>,
+ phantom_out2: core::marker::PhantomData<O2>,
+}
+
+impl<F, O1, O2: From<O1>> OutputInto<F, O1, O2> {
+ pub(crate) fn new(f: F) -> Self {
+ Self {
+ f,
+ phantom_out1: Default::default(),
+ phantom_out2: Default::default(),
+ }
+ }
+}
+
+impl<'a, I: Clone, O1, O2: From<O1>, E, F: Parser<I, O1, E>> Parser<I, O2, E>
+ for OutputInto<F, O1, O2>
+{
+ fn parse(&mut self, i: I) -> IResult<I, O2, E> {
+ match self.f.parse(i) {
+ Ok((i, o)) => Ok((i, o.into())),
+ Err(err) => Err(err),
+ }
+ }
+}
+
+/// Implementation of [`Parser::err_into`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct ErrInto<F, E1, E2: From<E1>> {
+ f: F,
+ phantom_err1: core::marker::PhantomData<E1>,
+ phantom_err2: core::marker::PhantomData<E2>,
+}
+
+impl<F, E1, E2: From<E1>> ErrInto<F, E1, E2> {
+ pub(crate) fn new(f: F) -> Self {
+ Self {
+ f,
+ phantom_err1: Default::default(),
+ phantom_err2: Default::default(),
+ }
+ }
+}
+
+impl<'a, I: Clone, O, E1, E2: crate::error::ParseError<I> + From<E1>, F: Parser<I, O, E1>>
+ Parser<I, O, E2> for ErrInto<F, E1, E2>
+{
+ fn parse(&mut self, i: I) -> IResult<I, O, E2> {
+ match self.f.parse(i) {
+ Ok(ok) => Ok(ok),
+ Err(Err::Error(e)) => Err(Err::Error(e.into())),
+ Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
+ Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
+ }
+ }
+}
+
+/// Creates an iterator from input data and a parser.
+///
+/// Call the iterator's [ParserIterator::finish] method to get the remaining input if successful,
+/// or the error value if we encountered an error.
+///
+/// On [`Err::Error`], iteration will stop. To instead chain an error up, see [`cut`].
+///
+/// ```rust
+/// use nom8::{combinator::iterator, IResult, bytes::tag, character::alpha1, sequence::terminated};
+/// use std::collections::HashMap;
+///
+/// let data = "abc|defg|hijkl|mnopqr|123";
+/// let mut it = iterator(data, terminated(alpha1, tag("|")));
+///
+/// let parsed = it.map(|v| (v, v.len())).collect::<HashMap<_,_>>();
+/// let res: IResult<_,_> = it.finish();
+///
+/// assert_eq!(parsed, [("abc", 3usize), ("defg", 4), ("hijkl", 5), ("mnopqr", 6)].iter().cloned().collect());
+/// assert_eq!(res, Ok(("123", ())));
+/// ```
+pub fn iterator<Input, Output, Error, F>(
+ input: Input,
+ f: F,
+) -> ParserIterator<Input, Output, Error, F>
+where
+ F: Parser<Input, Output, Error>,
+ Error: ParseError<Input>,
+{
+ ParserIterator {
+ iterator: f,
+ input,
+ output: Default::default(),
+ state: Some(State::Running),
+ }
+}
+
+/// Main structure associated to the [iterator] function.
+pub struct ParserIterator<I, O, E, F> {
+ iterator: F,
+ input: I,
+ output: core::marker::PhantomData<O>,
+ state: Option<State<E>>,
+}
+
+impl<I: Clone, O, E, F> ParserIterator<I, O, E, F> {
+ /// Returns the remaining input if parsing was successful, or the error if we encountered an error.
+ pub fn finish(mut self) -> IResult<I, (), E> {
+ match self.state.take().unwrap() {
+ State::Running | State::Done => Ok((self.input, ())),
+ State::Failure(e) => Err(Err::Failure(e)),
+ State::Incomplete(i) => Err(Err::Incomplete(i)),
+ }
+ }
+}
+
+impl<'a, Input, Output, Error, F> core::iter::Iterator
+ for &'a mut ParserIterator<Input, Output, Error, F>
+where
+ F: Parser<Input, Output, Error>,
+ Input: Clone,
+{
+ type Item = Output;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ if let State::Running = self.state.take().unwrap() {
+ let input = self.input.clone();
+
+ match self.iterator.parse(input) {
+ Ok((i, o)) => {
+ self.input = i;
+ self.state = Some(State::Running);
+ Some(o)
+ }
+ Err(Err::Error(_)) => {
+ self.state = Some(State::Done);
+ None
+ }
+ Err(Err::Failure(e)) => {
+ self.state = Some(State::Failure(e));
+ None
+ }
+ Err(Err::Incomplete(i)) => {
+ self.state = Some(State::Incomplete(i));
+ None
+ }
+ }
+ } else {
+ None
+ }
+ }
+}
+
+enum State<E> {
+ Running,
+ Done,
+ Failure(E),
+ Incomplete(Needed),
+}
+
+/// a parser which always succeeds with given value without consuming any input.
+///
+/// It can be used for example as the last alternative in `alt` to
+/// specify the default case.
+///
+/// ```rust
+/// # use nom8::{Err,error::ErrorKind, IResult};
+/// use nom8::branch::alt;
+/// use nom8::combinator::{success, value};
+/// # fn main() {
+///
+/// let mut parser = success::<_,_,(_,ErrorKind)>(10);
+/// assert_eq!(parser("xyz"), Ok(("xyz", 10)));
+///
+/// let mut sign = alt((value(-1, '-'), value(1, '+'), success::<_,_,(_,ErrorKind)>(1)));
+/// assert_eq!(sign("+10"), Ok(("10", 1)));
+/// assert_eq!(sign("-10"), Ok(("10", -1)));
+/// assert_eq!(sign("10"), Ok(("10", 1)));
+/// # }
+/// ```
+pub fn success<I, O: Clone, E: ParseError<I>>(val: O) -> impl Fn(I) -> IResult<I, O, E> {
+ move |input: I| Ok((input, val.clone()))
+}
+
+/// A parser which always fails.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, IResult};
+/// use nom8::combinator::fail;
+///
+/// let s = "string";
+/// assert_eq!(fail::<_, &str, _>(s), Err(Err::Error((s, ErrorKind::Fail))));
+/// ```
+pub fn fail<I, O, E: ParseError<I>>(i: I) -> IResult<I, O, E> {
+ Err(Err::Error(E::from_error_kind(i, ErrorKind::Fail)))
+}
diff --git a/vendor/nom8/src/combinator/tests.rs b/vendor/nom8/src/combinator/tests.rs
new file mode 100644
index 000000000..ff22c086a
--- /dev/null
+++ b/vendor/nom8/src/combinator/tests.rs
@@ -0,0 +1,398 @@
+use super::*;
+use crate::bytes::tag;
+use crate::bytes::take;
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::Streaming;
+#[cfg(feature = "alloc")]
+use crate::lib::std::boxed::Box;
+use crate::number::u8;
+use crate::Parser;
+use crate::{Err, IResult, Needed};
+
+macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+);
+
+#[test]
+fn eof_on_slices() {
+ let not_over: &[u8] = &b"Hello, world!"[..];
+ let is_over: &[u8] = &b""[..];
+
+ let res_not_over = eof(not_over);
+ assert_parse!(
+ res_not_over,
+ Err(Err::Error(error_position!(not_over, ErrorKind::Eof)))
+ );
+
+ let res_over = eof(is_over);
+ assert_parse!(res_over, Ok((is_over, is_over)));
+}
+
+#[test]
+fn eof_on_strs() {
+ let not_over: &str = "Hello, world!";
+ let is_over: &str = "";
+
+ let res_not_over = eof(not_over);
+ assert_parse!(
+ res_not_over,
+ Err(Err::Error(error_position!(not_over, ErrorKind::Eof)))
+ );
+
+ let res_over = eof(is_over);
+ assert_parse!(res_over, Ok((is_over, is_over)));
+}
+
+#[test]
+fn rest_on_slices() {
+ let input: &[u8] = &b"Hello, world!"[..];
+ let empty: &[u8] = &b""[..];
+ assert_parse!(rest(input), Ok((empty, input)));
+}
+
+#[test]
+fn rest_on_strs() {
+ let input: &str = "Hello, world!";
+ let empty: &str = "";
+ assert_parse!(rest(input), Ok((empty, input)));
+}
+
+#[test]
+fn rest_len_on_slices() {
+ let input: &[u8] = &b"Hello, world!"[..];
+ assert_parse!(rest_len(input), Ok((input, input.len())));
+}
+
+use crate::lib::std::convert::From;
+impl From<u32> for CustomError {
+ fn from(_: u32) -> Self {
+ CustomError
+ }
+}
+
+impl<I> ParseError<I> for CustomError {
+ fn from_error_kind(_: I, _: ErrorKind) -> Self {
+ CustomError
+ }
+
+ fn append(_: I, _: ErrorKind, _: CustomError) -> Self {
+ CustomError
+ }
+}
+
+struct CustomError;
+#[allow(dead_code)]
+fn custom_error(input: &[u8]) -> IResult<&[u8], &[u8], CustomError> {
+ //fix_error!(input, CustomError, alphanumeric)
+ crate::character::alphanumeric1(input)
+}
+
+#[test]
+fn test_flat_map() {
+ #![allow(deprecated)]
+ let input: &[u8] = &[3, 100, 101, 102, 103, 104][..];
+ assert_parse!(
+ flat_map(u8, take)(input),
+ Ok((&[103, 104][..], &[100, 101, 102][..]))
+ );
+}
+
+#[test]
+fn test_parser_flat_map() {
+ let input: &[u8] = &[3, 100, 101, 102, 103, 104][..];
+ assert_parse!(
+ u8.flat_map(take).parse(input),
+ Ok((&[103, 104][..], &[100, 101, 102][..]))
+ );
+}
+
+#[test]
+fn test_map_opt() {
+ #![allow(deprecated)]
+ let input: &[u8] = &[50][..];
+ assert_parse!(
+ map_opt(u8, |u| if u < 20 { Some(u) } else { None })(input),
+ Err(Err::Error((&[50][..], ErrorKind::MapOpt)))
+ );
+ assert_parse!(
+ map_opt(u8, |u| if u > 20 { Some(u) } else { None })(input),
+ Ok((&[][..], 50))
+ );
+}
+
+#[test]
+fn test_parser_map_opt() {
+ let input: &[u8] = &[50][..];
+ assert_parse!(
+ u8.map_opt(|u| if u < 20 { Some(u) } else { None })
+ .parse(input),
+ Err(Err::Error((&[50][..], ErrorKind::MapOpt)))
+ );
+ assert_parse!(
+ u8.map_opt(|u| if u > 20 { Some(u) } else { None })
+ .parse(input),
+ Ok((&[][..], 50))
+ );
+}
+
+#[test]
+fn test_map_parser() {
+ #![allow(deprecated)]
+ let input: &[u8] = &[100, 101, 102, 103, 104][..];
+ assert_parse!(
+ map_parser(take(4usize), take(2usize))(input),
+ Ok((&[104][..], &[100, 101][..]))
+ );
+}
+
+#[test]
+fn test_parser_map_parser() {
+ let input: &[u8] = &[100, 101, 102, 103, 104][..];
+ assert_parse!(
+ take(4usize).and_then(take(2usize)).parse(input),
+ Ok((&[104][..], &[100, 101][..]))
+ );
+}
+
+#[test]
+fn test_all_consuming() {
+ let input: &[u8] = &[100, 101, 102][..];
+ assert_parse!(
+ all_consuming(take(2usize))(input),
+ Err(Err::Error((&[102][..], ErrorKind::Eof)))
+ );
+ assert_parse!(
+ all_consuming(take(3usize))(input),
+ Ok((&[][..], &[100, 101, 102][..]))
+ );
+}
+
+#[test]
+#[allow(unused)]
+fn test_verify_ref() {
+ #![allow(deprecated)]
+ use crate::bytes::take;
+
+ let mut parser1 = verify(take(3u8), |s: &[u8]| s == &b"abc"[..]);
+
+ assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..])));
+ assert_eq!(
+ parser1(&b"defg"[..]),
+ Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
+ );
+
+ fn parser2(i: &[u8]) -> IResult<&[u8], u32> {
+ verify(crate::number::be_u32, |val: &u32| *val < 3)(i)
+ }
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn test_verify_alloc() {
+ #![allow(deprecated)]
+ use crate::bytes::take;
+ let mut parser1 = verify(take(3u8).map(|s: &[u8]| s.to_vec()), |s: &[u8]| {
+ s == &b"abc"[..]
+ });
+
+ assert_eq!(parser1(&b"abcd"[..]), Ok((&b"d"[..], (&b"abc").to_vec())));
+ assert_eq!(
+ parser1(&b"defg"[..]),
+ Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
+ );
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn test_into() {
+ #![allow(deprecated)]
+ use crate::bytes::take;
+ use crate::{
+ error::{Error, ParseError},
+ Err,
+ };
+
+ let mut parser = into(take::<_, _, Error<_>, false>(3u8));
+ let result: IResult<&[u8], Vec<u8>> = parser(&b"abcdefg"[..]);
+
+ assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99])));
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn test_parser_into() {
+ use crate::bytes::take;
+ use crate::{
+ error::{Error, ParseError},
+ Err,
+ };
+
+ let mut parser = take::<_, _, Error<_>, false>(3u8).output_into();
+ let result: IResult<&[u8], Vec<u8>> = parser.parse(&b"abcdefg"[..]);
+
+ assert_eq!(result, Ok((&b"defg"[..], vec![97, 98, 99])));
+}
+
+#[test]
+fn opt_test() {
+ fn opt_abcd(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Option<&[u8]>> {
+ opt(tag("abcd"))(i)
+ }
+
+ let a = &b"abcdef"[..];
+ let b = &b"bcdefg"[..];
+ let c = &b"ab"[..];
+ assert_eq!(
+ opt_abcd(Streaming(a)),
+ Ok((Streaming(&b"ef"[..]), Some(&b"abcd"[..])))
+ );
+ assert_eq!(
+ opt_abcd(Streaming(b)),
+ Ok((Streaming(&b"bcdefg"[..]), None))
+ );
+ assert_eq!(opt_abcd(Streaming(c)), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+fn peek_test() {
+ fn peek_tag(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ peek(tag("abcd"))(i)
+ }
+
+ assert_eq!(
+ peek_tag(Streaming(&b"abcdef"[..])),
+ Ok((Streaming(&b"abcdef"[..]), &b"abcd"[..]))
+ );
+ assert_eq!(
+ peek_tag(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ peek_tag(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn not_test() {
+ fn not_aaa(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, ()> {
+ not(tag("aaa"))(i)
+ }
+
+ assert_eq!(
+ not_aaa(Streaming(&b"aaa"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"aaa"[..]),
+ ErrorKind::Not
+ )))
+ );
+ assert_eq!(
+ not_aaa(Streaming(&b"aa"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ not_aaa(Streaming(&b"abcd"[..])),
+ Ok((Streaming(&b"abcd"[..]), ()))
+ );
+}
+
+#[test]
+fn verify_test() {
+ #![allow(deprecated)]
+ use crate::bytes::take;
+
+ fn test(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ verify(take(5u8), |slice: &[u8]| slice[0] == b'a')(i)
+ }
+ assert_eq!(
+ test(Streaming(&b"bcd"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ test(Streaming(&b"bcdefg"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"bcdefg"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_eq!(
+ test(Streaming(&b"abcdefg"[..])),
+ Ok((Streaming(&b"fg"[..]), &b"abcde"[..]))
+ );
+}
+
+#[test]
+fn test_parser_verify() {
+ use crate::bytes::take;
+
+ fn test(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take(5u8).verify(|slice: &[u8]| slice[0] == b'a').parse(i)
+ }
+ assert_eq!(
+ test(Streaming(&b"bcd"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ test(Streaming(&b"bcdefg"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"bcdefg"[..]),
+ ErrorKind::Verify
+ )))
+ );
+ assert_eq!(
+ test(Streaming(&b"abcdefg"[..])),
+ Ok((Streaming(&b"fg"[..]), &b"abcde"[..]))
+ );
+}
+
+#[test]
+#[allow(unused)]
+fn test_parser_verify_ref() {
+ use crate::bytes::take;
+
+ let mut parser1 = take(3u8).verify(|s: &[u8]| s == &b"abc"[..]);
+
+ assert_eq!(parser1.parse(&b"abcd"[..]), Ok((&b"d"[..], &b"abc"[..])));
+ assert_eq!(
+ parser1.parse(&b"defg"[..]),
+ Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
+ );
+
+ fn parser2(i: &[u8]) -> IResult<&[u8], u32> {
+ crate::number::be_u32.verify(|val: &u32| *val < 3).parse(i)
+ }
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn test_parser_verify_alloc() {
+ use crate::bytes::take;
+ let mut parser1 = take(3u8)
+ .map(|s: &[u8]| s.to_vec())
+ .verify(|s: &[u8]| s == &b"abc"[..]);
+
+ assert_eq!(
+ parser1.parse(&b"abcd"[..]),
+ Ok((&b"d"[..], (&b"abc").to_vec()))
+ );
+ assert_eq!(
+ parser1.parse(&b"defg"[..]),
+ Err(Err::Error((&b"defg"[..], ErrorKind::Verify)))
+ );
+}
+
+#[test]
+fn fail_test() {
+ let a = "string";
+ let b = "another string";
+
+ assert_eq!(fail::<_, &str, _>(a), Err(Err::Error((a, ErrorKind::Fail))));
+ assert_eq!(fail::<_, &str, _>(b), Err(Err::Error((b, ErrorKind::Fail))));
+}
diff --git a/vendor/nom8/src/error.rs b/vendor/nom8/src/error.rs
new file mode 100644
index 000000000..bbaa66d14
--- /dev/null
+++ b/vendor/nom8/src/error.rs
@@ -0,0 +1,1055 @@
+//! # Error management
+//!
+//! nom's errors are designed with multiple needs in mind:
+//! - indicate which parser failed and where in the input data
+//! - accumulate more context as the error goes up the parser chain
+//! - have a very low overhead, as errors are often discarded by the calling parser (examples: `many0`, `alt`)
+//! - can be modified according to the user's needs, because some languages need a lot more information
+//!
+//! To match these requirements, nom parsers have to return the following result
+//! type:
+//!
+//! ```rust
+//! pub type IResult<I, O, E=nom8::error::Error<I>> = Result<(I, O), nom8::Err<E>>;
+//!
+//! #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+//! pub enum Needed {
+//! Unknown,
+//! Size(u32)
+//! }
+//!
+//! pub enum Err<E> {
+//! Incomplete(Needed),
+//! Error(E),
+//! Failure(E),
+//! }
+//! ```
+//!
+//! The result is either an `Ok((I, O))` containing the remaining input and the
+//! parsed value, or an `Err(nom8::Err<E>)` with `E` the error type.
+//! `nom8::Err<E>` is an enum because combinators can have different behaviours
+//! depending on the value:
+//! - `Error` is a normal parser error. If a child parser of the `alt` combinator returns `Error`, it will try another child parser
+//! - `Failure` is an error from which we cannot recover: The `alt` combinator will not try other branches if a child parser returns `Failure`. This is used when we know we were in the right branch of `alt` and do not need to try other branches
+//! - `Incomplete` indicates that a parser did not have enough data to decide. This can be returned by parsers found in `streaming` submodules. Parsers in the `complete` submodules assume that they have the entire input data, so if it was not sufficient, they will instead return a `Err::Error`. When a parser returns `Incomplete`, we should accumulate more data in the buffer (example: reading from a socket) and call the parser again
+//!
+//! If we are running a parser and know it will not return `Err::Incomplete`, we can
+//! directly extract the error type from `Err::Error` or `Err::Failure` with the
+//! `finish()` method:
+//!
+//! ```rust,ignore
+//! # use nom8::IResult;
+//! # use nom8::prelude::*;
+//! # let parser = nom8::bytes::take_while1(|c: char| c == ' ');
+//! # let input = " ";
+//! let parser_result: IResult<_, _, _> = parser(input);
+//! let result: Result<_, _> = parser_result.finish();
+//! ```
+//!
+//! If we used a borrowed type as input, like `&[u8]` or `&str`, we might want to
+//! convert it to an owned type to transmit it somewhere, with the `to_owned()`
+//! method:
+//!
+//! ```rust,ignore
+//! # use nom8::Err;
+//! # type Value<'s> = &'s [u8];
+//! # let parser = nom8::bytes::take_while1(|c: u8| c == b' ');
+//! # let data = " ";
+//! let result: Result<(&[u8], Value<'_>), Err<Vec<u8>>> =
+//! parser(data).map_err(|e: E<&[u8]>| e.to_owned());
+//! ```
+//!
+//! nom provides a powerful error system that can adapt to your needs: you can
+//! get reduced error information if you want to improve performance, or you can
+//! get a precise trace of parser application, with fine grained position information.
+//!
+//! This is done through the third type parameter of `IResult`, nom's parser result
+//! type:
+//!
+//! ```rust
+//! pub type IResult<I, O, E=nom8::error::Error<I>> = Result<(I, O), Err<E>>;
+//!
+//! #[derive(Debug, PartialEq, Eq, Clone, Copy)]
+//! pub enum Needed {
+//! Unknown,
+//! Size(u32)
+//! }
+//!
+//! pub enum Err<E> {
+//! Incomplete(Needed),
+//! Error(E),
+//! Failure(E),
+//! }
+//! ```
+//!
+//! This error type is completely generic in nom's combinators, so you can choose
+//! exactly which error type you want to use when you define your parsers, or
+//! directly at the call site.
+//! See [the JSON parser](https://github.com/Geal/nom/blob/5405e1173f1052f7e006dcb0b9cfda2b06557b65/examples/json.rs#L209-L286)
+//! for an example of choosing different error types at the call site.
+//!
+//! The `Err<E>` enum expresses 3 conditions for a parser error:
+//! - `Incomplete` indicates that a parser did not have enough data to decide. This can be returned by parsers found in `streaming` submodules to indicate that we should buffer more data from a file or socket. Parsers in the `complete` submodules assume that they have the entire input data, so if it was not sufficient, they will instead return a `Err::Error`
+//! - `Error` is a normal parser error. If a child parser of the `alt` combinator returns `Error`, it will try another child parser
+//! - `Failure` is an error from which we cannot recover: The `alt` combinator will not try other branches if a child parser returns `Failure`. If we know we were in the right branch (example: we found a correct prefix character but input after that was wrong), we can transform a `Err::Error` into a `Err::Failure` with the `cut()` combinator
+//!
+//! ## Common error types
+//!
+//! ### the default error type: nom8::error::Error
+//!
+//! ```rust
+//! # use nom8::error::ErrorKind;
+//! #[derive(Debug, PartialEq)]
+//! pub struct Error<I> {
+//! /// position of the error in the input data
+//! pub input: I,
+//! /// nom error code
+//! pub code: ErrorKind,
+//! }
+//! ```
+//!
+//! This structure contains a `nom8::error::ErrorKind` indicating which kind of
+//! parser encountered an error (example: `ErrorKind::Tag` for the `tag()`
+//! combinator), and the input position of the error.
+//!
+//! This error type is fast and has very low overhead, so it is suitable for
+//! parsers that are called repeatedly, like in network protocols.
+//! It is very limited though, it will not tell you about the chain of
+//! parser calls, so it is not enough to write user friendly errors.
+//!
+//! Example error returned in a JSON-like parser (from `examples/json.rs`):
+//!
+//! ```rust,ignore
+//! let data = " { \"a\"\t: 42,
+//! \"b\": [ \"x\", \"y\", 12 ] ,
+//! \"c\": { 1\"hello\" : \"world\"
+//! }
+//! } ";
+//!
+//! // will print:
+//! // Err(
+//! // Failure(
+//! // Error {
+//! // input: "1\"hello\" : \"world\"\n }\n } ",
+//! // code: Char,
+//! // },
+//! // ),
+//! // )
+//! println!(
+//! "{:#?}\n",
+//! json::<Error<&str>>(data)
+//! );
+//! ```
+//!
+//! ### getting more information: nom8::error::VerboseError
+//!
+//! The `VerboseError<I>` type accumulates more information about the chain of
+//! parsers that encountered an error:
+//!
+//! ```rust
+//! # use nom8::error::ErrorKind;
+//! #[derive(Clone, Debug, PartialEq)]
+//! pub struct VerboseError<I> {
+//! /// List of errors accumulated by `VerboseError`, containing the affected
+//! /// part of input data, and some context
+//! pub errors: Vec<(I, VerboseErrorKind)>,
+//! }
+//!
+//! #[derive(Clone, Debug, PartialEq)]
+//! /// Error context for `VerboseError`
+//! pub enum VerboseErrorKind {
+//! /// Static string added by the `context` function
+//! Context(&'static str),
+//! /// Indicates which character was expected by the `char` function
+//! Char(char),
+//! /// Error kind given by various nom parsers
+//! Nom(ErrorKind),
+//! }
+//! ```
+//!
+//! It contains the input position and error code for each of those parsers.
+//! It does not accumulate errors from the different branches of `alt`, it will
+//! only contain errors from the last branch it tried.
+//!
+//! It can be used along with the `nom8::error::context` combinator to inform about
+//! the parser chain:
+//!
+//! ```rust,ignore
+//! # use nom8::error::context;
+//! # use nom8::sequence::preceded;
+//! # use nom8::character::char;
+//! # use nom8::combinator::cut;
+//! # use nom8::sequence::terminated;
+//! # let parse_str = nom8::bytes::take_while1(|c| c == ' ');
+//! # let i = " ";
+//! context(
+//! "string",
+//! preceded('\"', cut(terminated(parse_str, '\"'))),
+//! )(i);
+//! ```
+//!
+//! It is not very usable if printed directly:
+//!
+//! ```rust,ignore
+//! // parsed verbose: Err(
+//! // Failure(
+//! // VerboseError {
+//! // errors: [
+//! // (
+//! // "1\"hello\" : \"world\"\n }\n } ",
+//! // Char(
+//! // '}',
+//! // ),
+//! // ),
+//! // (
+//! // "{ 1\"hello\" : \"world\"\n }\n } ",
+//! // Context(
+//! // "map",
+//! // ),
+//! // ),
+//! // (
+//! // "{ \"a\"\t: 42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } ",
+//! // Context(
+//! // "map",
+//! // ),
+//! // ),
+//! // ],
+//! // },
+//! // ),
+//! // )
+//! println!("parsed verbose: {:#?}", json::<VerboseError<&str>>(data));
+//! ```
+//!
+//! But by looking at the original input and the chain of errors, we can build
+//! a more user friendly error message. The `nom8::error::convert_error` function
+//! can build such a message.
+//!
+//! ```rust,ignore
+//! let e = json::<VerboseError<&str>>(data).finish().err().unwrap();
+//! // here we use the `convert_error` function, to transform a `VerboseError<&str>`
+//! // into a printable trace.
+//! //
+//! // This will print:
+//! // verbose errors - `json::<VerboseError<&str>>(data)`:
+//! // 0: at line 2:
+//! // "c": { 1"hello" : "world"
+//! // ^
+//! // expected '}', found 1
+//! //
+//! // 1: at line 2, in map:
+//! // "c": { 1"hello" : "world"
+//! // ^
+//! //
+//! // 2: at line 0, in map:
+//! // { "a" : 42,
+//! // ^
+//! println!(
+//! "verbose errors - `json::<VerboseError<&str>>(data)`:\n{}",
+//! convert_error(data, e)
+//! );
+//! ```
+//!
+//! Note that `VerboseError` and `convert_error` are meant as a starting point for
+//! language errors, but that they cannot cover all use cases. So a custom
+//! `convert_error` function should probably be written.
+//!
+//! ### Improving usability: nom_locate and nom-supreme
+//!
+//! These crates were developed to improve the user experience when writing nom
+//! parsers.
+//!
+//! #### nom_locate
+//!
+//! [nom_locate](https://docs.rs/nom_locate/) wraps the input data in a `Span`
+//! type that can be understood by nom parsers. That type provides location
+//! information, like line and column.
+//!
+//! #### nom-supreme
+//!
+//! [nom-supreme](https://docs.rs/nom-supreme/) provides the `ErrorTree<I>` error
+//! type, that provides the same chain of parser errors as `VerboseError`, but also
+//! accumulates errors from the various branches tried by `alt`.
+//!
+//! With this error type, you can explore everything that has been tried by the
+//! parser.
+//!
+//! ## The `ParseError` trait
+//!
+//! If those error types are not enough, we can define our own, by implementing
+//! the `ParseError<I>` trait. All nom combinators are generic over that trait
+//! for their errors, so we only need to define it in the parser result type,
+//! and it will be used everywhere.
+//!
+//! ```rust
+//! # use nom8::error::ErrorKind;
+//! pub trait ParseError<I>: Sized {
+//! /// Creates an error from the input position and an [ErrorKind]
+//! fn from_error_kind(input: I, kind: ErrorKind) -> Self;
+//!
+//! /// Combines an existing error with a new one created from the input
+//! /// position and an [ErrorKind]. This is useful when backtracking
+//! /// through a parse tree, accumulating error context on the way
+//! fn append(input: I, kind: ErrorKind, other: Self) -> Self;
+//!
+//! /// Combines two existing errors. This function is used to compare errors
+//! /// generated in various branches of `alt`
+//! fn or(self, other: Self) -> Self {
+//! other
+//! }
+//! }
+//! ```
+//!
+//! Any error type has to implement that trait, that requires ways to build an
+//! error:
+//! - `from_error_kind`: From the input position and the `ErrorKind` enum that indicates in which parser we got an error
+//! - `append`: Allows the creation of a chain of errors as we backtrack through the parser tree (various combinators will add more context)
+//! - `from_char`: Creates an error that indicates which character we were expecting
+//! - `or`: In combinators like `alt`, allows choosing between errors from various branches (or accumulating them)
+//!
+//! We can also implement the `ContextError` trait to support the `context()`
+//! combinator used by `VerboseError<I>`:
+//!
+//! ```rust
+//! pub trait ContextError<I, C>: Sized {
+//! fn add_context(_input: I, _ctx: C, other: Self) -> Self {
+//! other
+//! }
+//! }
+//! ```
+//!
+//! And there is also the `FromExternalError<I, E>` used by `map_res` to wrap
+//! errors returned by other functions:
+//!
+//! ```rust
+//! # use nom8::error::ErrorKind;
+//! pub trait FromExternalError<I, ExternalError> {
+//! fn from_external_error(input: I, kind: ErrorKind, e: ExternalError) -> Self;
+//! }
+//! ```
+//!
+//! ### Example usage
+//!
+//! Let's define a debugging error type, that will print something every time an
+//! error is generated. This will give us a good insight into what the parser tried.
+//! Since errors can be combined with each other, we want it to keep some info on
+//! the error that was just returned. We'll just store that in a string:
+//!
+//! ```rust
+//! struct DebugError {
+//! message: String,
+//! }
+//! ```
+//!
+//! Now let's implement `ParseError` and `ContextError` on it:
+//!
+//! ```rust
+//! # use nom8::error::ParseError;
+//! # use nom8::error::ErrorKind;
+//! # use nom8::error::ContextError;
+//! # struct DebugError {
+//! # message: String,
+//! # }
+//! impl ParseError<&str> for DebugError {
+//! // on one line, we show the error code and the input that caused it
+//! fn from_error_kind(input: &str, kind: ErrorKind) -> Self {
+//! let message = format!("{:?}:\t{:?}\n", kind, input);
+//! println!("{}", message);
+//! DebugError { message }
+//! }
+//!
+//! // if combining multiple errors, we show them one after the other
+//! fn append(input: &str, kind: ErrorKind, other: Self) -> Self {
+//! let message = format!("{}{:?}:\t{:?}\n", other.message, kind, input);
+//! println!("{}", message);
+//! DebugError { message }
+//! }
+//!
+//! fn or(self, other: Self) -> Self {
+//! let message = format!("{}\tOR\n{}\n", self.message, other.message);
+//! println!("{}", message);
+//! DebugError { message }
+//! }
+//! }
+//!
+//! impl ContextError<&str, &'static str> for DebugError {
+//! fn add_context(input: &str, ctx: &'static str, other: Self) -> Self {
+//! let message = format!("{}\"{}\":\t{:?}\n", other.message, ctx, input);
+//! println!("{}", message);
+//! DebugError { message }
+//! }
+//! }
+//! ```
+//!
+//! So when calling our JSON parser with this error type, we will get a trace
+//! of all the times a parser stoppped and backtracked:
+//!
+//! ```rust,ignore
+//! println!("debug: {:#?}", root::<DebugError>(data));
+//! ```
+//!
+//! ```text
+//! AlphaNumeric: "\"\t: 42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//!
+//! '{': "42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//!
+//! '{': "42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//! "map": "42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//!
+//! [..]
+//!
+//! AlphaNumeric: "\": { 1\"hello\" : \"world\"\n }\n } "
+//!
+//! '"': "1\"hello\" : \"world\"\n }\n } "
+//!
+//! '"': "1\"hello\" : \"world\"\n }\n } "
+//! "string": "1\"hello\" : \"world\"\n }\n } "
+//!
+//! '}': "1\"hello\" : \"world\"\n }\n } "
+//!
+//! '}': "1\"hello\" : \"world\"\n }\n } "
+//! "map": "{ 1\"hello\" : \"world\"\n }\n } "
+//!
+//! '}': "1\"hello\" : \"world\"\n }\n } "
+//! "map": "{ 1\"hello\" : \"world\"\n }\n } "
+//! "map": "{ \"a\"\t: 42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//!
+//! debug: Err(
+//! Failure(
+//! DebugError {
+//! message: "'}':\t\"1\\\"hello\\\" : \\\"world\\\"\\n }\\n } \"\n\"map\":\t\"{ 1\\\"hello\\\" : \\\"world
+//! \\"\\n }\\n } \"\n\"map\":\t\"{ \\\"a\\\"\\t: 42,\\n \\\"b\\\": [ \\\"x\\\", \\\"y\\\", 12 ] ,\\n \\\"c\\\": { 1\
+//! \"hello\\\" : \\\"world\\\"\\n }\\n } \"\n",
+//! },
+//! ),
+//! )
+//! ```
+//!
+//! Here we can see that when parsing `{ 1\"hello\" : \"world\"\n }\n }`, after
+//! getting past the initial `{`, we tried:
+//! - parsing a `"` because we're expecting a key name, and that parser was part of the
+//! "string" parser
+//! - parsing a `}` because the map might be empty. When this fails, we backtrack,
+//! through 2 recursive map parsers:
+//!
+//! ```text
+//! '}': "1\"hello\" : \"world\"\n }\n } "
+//! "map": "{ 1\"hello\" : \"world\"\n }\n } "
+//! "map": "{ \"a\"\t: 42,\n \"b\": [ \"x\", \"y\", 12 ] ,\n \"c\": { 1\"hello\" : \"world\"\n }\n } "
+//! ```
+//!
+//! ## Debugging parsers
+//!
+//! While you are writing your parsers, you will sometimes need to follow
+//! which part of the parser sees which part of the input.
+//!
+//! To that end, nom provides the `dbg_err` function that will observe
+//! a parser's input and output, and print a hexdump of the input if there was an
+//! error. Here is what it could return:
+//!
+#![cfg_attr(feature = "std", doc = "```")]
+#![cfg_attr(not(feature = "std"), doc = "```ignore")]
+//! use nom8::prelude::*;
+//! # use nom8::bytes::tag;
+//! fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+//! tag("abcd").dbg_err("tag").parse(i)
+//! }
+//!
+//! let a = &b"efghijkl"[..];
+//!
+//! // Will print the following message:
+//! // tag: Error(Error(Error { input: [101, 102, 103, 104, 105, 106, 107, 108], code: Tag })) at:
+//! // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
+//! f(a);
+//! ```
+//!
+//! You can go further with the [nom-trace crate](https://github.com/rust-bakery/nom-trace)
+
+use crate::lib::std::fmt;
+use crate::Parser;
+
+/// This trait must be implemented by the error type of a nom parser.
+///
+/// There are already implementations of it for `(Input, ErrorKind)`
+/// and `VerboseError<Input>`.
+///
+/// It provides methods to create an error from some combinators,
+/// and combine existing errors in combinators like `alt`.
+pub trait ParseError<I>: Sized {
+ /// Creates an error from the input position and an [ErrorKind]
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self;
+
+ /// Combines an existing error with a new one created from the input
+ /// position and an [ErrorKind]. This is useful when backtracking
+ /// through a parse tree, accumulating error context on the way
+ fn append(input: I, kind: ErrorKind, other: Self) -> Self;
+
+ /// Creates an error from an input position and an expected character
+ #[deprecated(since = "8.0.0", note = "Replaced with `ContextError`")]
+ fn from_char(input: I, _: char) -> Self {
+ Self::from_error_kind(input, ErrorKind::Char)
+ }
+
+ /// Combines two existing errors. This function is used to compare errors
+ /// generated in various branches of `alt`.
+ fn or(self, other: Self) -> Self {
+ other
+ }
+}
+
+/// This trait is required by the `context` combinator to add a static string
+/// to an existing error
+pub trait ContextError<I, C>: Sized {
+ /// Creates a new error from an input position, a static string and an existing error.
+ /// This is used mainly in the [context] combinator, to add user friendly information
+ /// to errors when backtracking through a parse tree
+ fn add_context(_input: I, _ctx: C, other: Self) -> Self {
+ other
+ }
+}
+
+/// This trait is required by the `map_res` combinator to integrate
+/// error types from external functions, like [std::str::FromStr]
+pub trait FromExternalError<I, E> {
+ /// Creates a new error from an input position, an [ErrorKind] indicating the
+ /// wrapping parser, and an external error
+ fn from_external_error(input: I, kind: ErrorKind, e: E) -> Self;
+}
+
+/// default error type, only contains the error' location and code
+#[derive(Debug, PartialEq)]
+pub struct Error<I> {
+ /// position of the error in the input data
+ pub input: I,
+ /// nom error code
+ pub code: ErrorKind,
+}
+
+impl<I> Error<I> {
+ /// creates a new basic error
+ pub fn new(input: I, code: ErrorKind) -> Error<I> {
+ Error { input, code }
+ }
+}
+
+impl<I> ParseError<I> for Error<I> {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ Error { input, code: kind }
+ }
+
+ fn append(_: I, _: ErrorKind, other: Self) -> Self {
+ other
+ }
+}
+
+impl<I, C> ContextError<I, C> for Error<I> {}
+
+impl<I, E> FromExternalError<I, E> for Error<I> {
+ /// Create a new error from an input position and an external error
+ fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
+ Error { input, code: kind }
+ }
+}
+
+/// The Display implementation allows the std::error::Error implementation
+impl<I: fmt::Display> fmt::Display for Error<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "error {:?} at: {}", self.code, self.input)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I: fmt::Debug + fmt::Display> std::error::Error for Error<I> {}
+
+// for backward compatibility, keep those trait implementations
+// for the previously used error type
+impl<I> ParseError<I> for (I, ErrorKind) {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ (input, kind)
+ }
+
+ fn append(_: I, _: ErrorKind, other: Self) -> Self {
+ other
+ }
+}
+
+impl<I, C> ContextError<I, C> for (I, ErrorKind) {}
+
+impl<I, E> FromExternalError<I, E> for (I, ErrorKind) {
+ fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
+ (input, kind)
+ }
+}
+
+impl<I> ParseError<I> for () {
+ fn from_error_kind(_: I, _: ErrorKind) -> Self {}
+
+ fn append(_: I, _: ErrorKind, _: Self) -> Self {}
+}
+
+impl<I, C> ContextError<I, C> for () {}
+
+impl<I, E> FromExternalError<I, E> for () {
+ fn from_external_error(_input: I, _kind: ErrorKind, _e: E) -> Self {}
+}
+
+/// Creates an error from the input position and an [ErrorKind]
+#[deprecated(since = "8.0.0", note = "Replaced with `ParseError::from_error_kind`")]
+pub fn make_error<I, E: ParseError<I>>(input: I, kind: ErrorKind) -> E {
+ E::from_error_kind(input, kind)
+}
+
+/// Combines an existing error with a new one created from the input
+/// position and an [ErrorKind]. This is useful when backtracking
+/// through a parse tree, accumulating error context on the way
+#[deprecated(since = "8.0.0", note = "Replaced with `ParseError::append`")]
+pub fn append_error<I, E: ParseError<I>>(input: I, kind: ErrorKind, other: E) -> E {
+ E::append(input, kind, other)
+}
+
+/// This error type accumulates errors and their position when backtracking
+/// through a parse tree. With some post processing (cf `examples/json.rs`),
+/// it can be used to display user friendly error messages
+#[cfg(feature = "alloc")]
+#[derive(Clone, Debug, PartialEq)]
+pub struct VerboseError<I> {
+ /// List of errors accumulated by `VerboseError`, containing the affected
+ /// part of input data, and some context
+ pub errors: crate::lib::std::vec::Vec<(I, VerboseErrorKind)>,
+}
+
+#[cfg(feature = "alloc")]
+#[derive(Clone, Debug, PartialEq)]
+/// Error context for `VerboseError`
+pub enum VerboseErrorKind {
+ /// Static string added by the `context` function
+ Context(&'static str),
+ /// Error kind given by various nom parsers
+ Nom(ErrorKind),
+}
+
+#[cfg(feature = "alloc")]
+impl<I> ParseError<I> for VerboseError<I> {
+ fn from_error_kind(input: I, kind: ErrorKind) -> Self {
+ VerboseError {
+ errors: vec![(input, VerboseErrorKind::Nom(kind))],
+ }
+ }
+
+ fn append(input: I, kind: ErrorKind, mut other: Self) -> Self {
+ other.errors.push((input, VerboseErrorKind::Nom(kind)));
+ other
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I> ContextError<I, &'static str> for VerboseError<I> {
+ fn add_context(input: I, ctx: &'static str, mut other: Self) -> Self {
+ other.errors.push((input, VerboseErrorKind::Context(ctx)));
+ other
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I, E> FromExternalError<I, E> for VerboseError<I> {
+ /// Create a new error from an input position and an external error
+ fn from_external_error(input: I, kind: ErrorKind, _e: E) -> Self {
+ Self::from_error_kind(input, kind)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I: fmt::Display> fmt::Display for VerboseError<I> {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ writeln!(f, "Parse error:")?;
+ for (input, error) in &self.errors {
+ match error {
+ VerboseErrorKind::Nom(e) => writeln!(f, "{:?} at: {}", e, input)?,
+ VerboseErrorKind::Context(s) => writeln!(f, "in section '{}', at: {}", s, input)?,
+ }
+ }
+
+ Ok(())
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I: fmt::Debug + fmt::Display> std::error::Error for VerboseError<I> {}
+
+use crate::{Err, IResult};
+
+/// Create a new error from an input position, a static string and an existing error.
+/// This is used mainly in the [context] combinator, to add user friendly information
+/// to errors when backtracking through a parse tree
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::context`]
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::context")]
+pub fn context<I: Clone, E: ContextError<I, &'static str>, F, O>(
+ context: &'static str,
+ mut f: F,
+) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ F: Parser<I, O, E>,
+{
+ move |i: I| match f.parse(i.clone()) {
+ Ok(o) => Ok(o),
+ Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
+ Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, context, e))),
+ Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, context, e))),
+ }
+}
+
+/// Implementation of [`Parser::context`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub struct Context<F, O, C: Clone> {
+ f: F,
+ context: C,
+ phantom: core::marker::PhantomData<O>,
+}
+
+impl<F, O, C: Clone> Context<F, O, C> {
+ pub(crate) fn new(f: F, context: C) -> Self {
+ Self {
+ f,
+ context,
+ phantom: Default::default(),
+ }
+ }
+}
+
+impl<I, O, E, F: Parser<I, O, E>, C> Parser<I, O, E> for Context<F, O, C>
+where
+ I: Clone,
+ C: Clone,
+ E: ContextError<I, C>,
+ F: Parser<I, O, E>,
+{
+ fn parse(&mut self, i: I) -> IResult<I, O, E> {
+ match (self.f).parse(i.clone()) {
+ Ok(o) => Ok(o),
+ Err(Err::Incomplete(i)) => Err(Err::Incomplete(i)),
+ Err(Err::Error(e)) => Err(Err::Error(E::add_context(i, self.context.clone(), e))),
+ Err(Err::Failure(e)) => Err(Err::Failure(E::add_context(i, self.context.clone(), e))),
+ }
+ }
+}
+
+/// Transforms a `VerboseError` into a trace with input position information
+#[cfg(feature = "alloc")]
+pub fn convert_error<I: core::ops::Deref<Target = str>>(
+ input: I,
+ e: VerboseError<I>,
+) -> crate::lib::std::string::String {
+ use crate::input::Offset;
+ use crate::lib::std::fmt::Write;
+
+ let mut result = crate::lib::std::string::String::new();
+
+ for (i, (substring, kind)) in e.errors.iter().enumerate() {
+ let offset = input.offset(substring);
+
+ if input.is_empty() {
+ match kind {
+ VerboseErrorKind::Context(s) => write!(&mut result, "{}: in {}, got empty input\n\n", i, s),
+ VerboseErrorKind::Nom(e) => write!(&mut result, "{}: in {:?}, got empty input\n\n", i, e),
+ }
+ } else {
+ let prefix = &input.as_bytes()[..offset];
+
+ // Count the number of newlines in the first `offset` bytes of input
+ let line_number = prefix.iter().filter(|&&b| b == b'\n').count() + 1;
+
+ // Find the line that includes the subslice:
+ // Find the *last* newline before the substring starts
+ let line_begin = prefix
+ .iter()
+ .rev()
+ .position(|&b| b == b'\n')
+ .map(|pos| offset - pos)
+ .unwrap_or(0);
+
+ // Find the full line after that newline
+ let line = input[line_begin..]
+ .lines()
+ .next()
+ .unwrap_or(&input[line_begin..])
+ .trim_end();
+
+ // The (1-indexed) column number is the offset of our substring into that line
+ let column_number = line.offset(substring) + 1;
+
+ match kind {
+ VerboseErrorKind::Context(s) => write!(
+ &mut result,
+ "{i}: at line {line_number}, in {context}:\n\
+ {line}\n\
+ {caret:>column$}\n\n",
+ i = i,
+ line_number = line_number,
+ context = s,
+ line = line,
+ caret = '^',
+ column = column_number,
+ ),
+ VerboseErrorKind::Nom(e) => write!(
+ &mut result,
+ "{i}: at line {line_number}, in {nom_err:?}:\n\
+ {line}\n\
+ {caret:>column$}\n\n",
+ i = i,
+ line_number = line_number,
+ nom_err = e,
+ line = line,
+ caret = '^',
+ column = column_number,
+ ),
+ }
+ }
+ // Because `write!` to a `String` is infallible, this `unwrap` is fine.
+ .unwrap();
+ }
+
+ result
+}
+
+/// Indicates which parser returned an error
+#[rustfmt::skip]
+#[derive(Debug,PartialEq,Eq,Hash,Clone,Copy)]
+#[allow(deprecated,missing_docs)]
+pub enum ErrorKind {
+ Tag,
+ MapRes,
+ MapOpt,
+ Alt,
+ IsNot,
+ IsA,
+ SeparatedList,
+ SeparatedNonEmptyList,
+ Many0,
+ Many1,
+ ManyTill,
+ Count,
+ TakeUntil,
+ LengthValue,
+ TagClosure,
+ Alpha,
+ Digit,
+ HexDigit,
+ OctDigit,
+ AlphaNumeric,
+ Space,
+ MultiSpace,
+ LengthValueFn,
+ Eof,
+ Switch,
+ TagBits,
+ OneOf,
+ NoneOf,
+ Char,
+ CrLf,
+ RegexpMatch,
+ RegexpMatches,
+ RegexpFind,
+ RegexpCapture,
+ RegexpCaptures,
+ TakeWhile1,
+ Complete,
+ Fix,
+ Escaped,
+ EscapedTransform,
+ NonEmpty,
+ ManyMN,
+ Not,
+ Permutation,
+ Verify,
+ TakeTill1,
+ TakeWhileMN,
+ TooLarge,
+ Many0Count,
+ Many1Count,
+ Float,
+ Satisfy,
+ Fail,
+}
+
+impl ErrorKind {
+ #[rustfmt::skip]
+ #[allow(deprecated)]
+ /// Converts an ErrorKind to a text description
+ pub fn description(&self) -> &str {
+ match *self {
+ ErrorKind::Tag => "Tag",
+ ErrorKind::MapRes => "Map on Result",
+ ErrorKind::MapOpt => "Map on Option",
+ ErrorKind::Alt => "Alternative",
+ ErrorKind::IsNot => "IsNot",
+ ErrorKind::IsA => "IsA",
+ ErrorKind::SeparatedList => "Separated list",
+ ErrorKind::SeparatedNonEmptyList => "Separated non empty list",
+ ErrorKind::Many0 => "Many0",
+ ErrorKind::Many1 => "Many1",
+ ErrorKind::Count => "Count",
+ ErrorKind::TakeUntil => "Take until",
+ ErrorKind::LengthValue => "Length followed by value",
+ ErrorKind::TagClosure => "Tag closure",
+ ErrorKind::Alpha => "Alphabetic",
+ ErrorKind::Digit => "Digit",
+ ErrorKind::AlphaNumeric => "AlphaNumeric",
+ ErrorKind::Space => "Space",
+ ErrorKind::MultiSpace => "Multiple spaces",
+ ErrorKind::LengthValueFn => "LengthValueFn",
+ ErrorKind::Eof => "End of file",
+ ErrorKind::Switch => "Switch",
+ ErrorKind::TagBits => "Tag on bitstream",
+ ErrorKind::OneOf => "OneOf",
+ ErrorKind::NoneOf => "NoneOf",
+ ErrorKind::Char => "Char",
+ ErrorKind::CrLf => "CrLf",
+ ErrorKind::RegexpMatch => "RegexpMatch",
+ ErrorKind::RegexpMatches => "RegexpMatches",
+ ErrorKind::RegexpFind => "RegexpFind",
+ ErrorKind::RegexpCapture => "RegexpCapture",
+ ErrorKind::RegexpCaptures => "RegexpCaptures",
+ ErrorKind::TakeWhile1 => "TakeWhile1",
+ ErrorKind::Complete => "Complete",
+ ErrorKind::Fix => "Fix",
+ ErrorKind::Escaped => "Escaped",
+ ErrorKind::EscapedTransform => "EscapedTransform",
+ ErrorKind::NonEmpty => "NonEmpty",
+ ErrorKind::ManyMN => "Many(m, n)",
+ ErrorKind::HexDigit => "Hexadecimal Digit",
+ ErrorKind::OctDigit => "Octal digit",
+ ErrorKind::Not => "Negation",
+ ErrorKind::Permutation => "Permutation",
+ ErrorKind::ManyTill => "ManyTill",
+ ErrorKind::Verify => "predicate verification",
+ ErrorKind::TakeTill1 => "TakeTill1",
+ ErrorKind::TakeWhileMN => "TakeWhileMN",
+ ErrorKind::TooLarge => "Needed data size is too large",
+ ErrorKind::Many0Count => "Count occurrence of >=0 patterns",
+ ErrorKind::Many1Count => "Count occurrence of >=1 patterns",
+ ErrorKind::Float => "Float",
+ ErrorKind::Satisfy => "Satisfy",
+ ErrorKind::Fail => "Fail",
+ }
+ }
+}
+
+/// Creates a parse error from a [`ErrorKind`]
+/// and the position in the input
+#[allow(unused_variables)]
+#[macro_export(local_inner_macros)]
+macro_rules! error_position(
+ ($input:expr, $code:expr) => ({
+ $crate::error::ParseError::from_error_kind($input, $code)
+ });
+);
+
+/// Creates a parse error from a [`ErrorKind`],
+/// the position in the input and the next error in
+/// the parsing tree
+#[allow(unused_variables)]
+#[macro_export(local_inner_macros)]
+macro_rules! error_node_position(
+ ($input:expr, $code:expr, $next:expr) => ({
+ $crate::error::ParseError::append($input, $code, $next)
+ });
+);
+
+/// Prints a message and the input if the parser fails.
+///
+/// The message prints the `Error` or `Incomplete`
+/// and the parser's calling code.
+///
+/// It also displays the input in hexdump format
+///
+/// **WARNING:** Deprecated, replaced with [`Parser::dbg_err`]
+///
+/// ```rust
+/// use nom8::{IResult, error::dbg_dmp, bytes::tag};
+///
+/// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+/// dbg_dmp(tag("abcd"), "tag")(i)
+/// }
+///
+/// let a = &b"efghijkl"[..];
+///
+/// // Will print the following message:
+/// // Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at l.5 by ' tag ! ( "abcd" ) '
+/// // 00000000 65 66 67 68 69 6a 6b 6c efghijkl
+/// f(a);
+/// ```
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser::dbg_err")]
+#[cfg(feature = "std")]
+pub fn dbg_dmp<'a, F, O, E: std::fmt::Debug>(
+ f: F,
+ context: &'static str,
+) -> impl Fn(&'a [u8]) -> IResult<&'a [u8], O, E>
+where
+ F: Fn(&'a [u8]) -> IResult<&'a [u8], O, E>,
+{
+ use crate::input::HexDisplay;
+ move |i: &'a [u8]| match f(i) {
+ Err(e) => {
+ println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
+ Err(e)
+ }
+ a => a,
+ }
+}
+
+/// Implementation of [`Parser::dbg_err`]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+#[cfg(feature = "std")]
+pub struct DbgErr<F, O, C> {
+ f: F,
+ context: C,
+ phantom: core::marker::PhantomData<O>,
+}
+
+#[cfg(feature = "std")]
+impl<F, O, C> DbgErr<F, O, C> {
+ pub(crate) fn new(f: F, context: C) -> Self {
+ Self {
+ f,
+ context,
+ phantom: Default::default(),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, O, E, F: Parser<I, O, E>, C> Parser<I, O, E> for DbgErr<F, O, C>
+where
+ I: crate::input::AsBytes,
+ I: Clone,
+ E: std::fmt::Debug,
+ F: Parser<I, O, E>,
+ C: std::fmt::Display,
+{
+ fn parse(&mut self, input: I) -> IResult<I, O, E> {
+ use crate::input::HexDisplay;
+ let i = input.clone();
+ match self.f.parse(i) {
+ Err(e) => {
+ let input = input.as_bytes();
+ eprintln!("{}: Error({:?}) at:\n{}", self.context, e, input.to_hex(8));
+ Err(e)
+ }
+ a => a,
+ }
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "alloc")]
+mod tests {
+ use super::*;
+ use crate::bytes::one_of;
+
+ #[test]
+ fn convert_error_panic() {
+ let input = "";
+
+ let _result: IResult<_, _, VerboseError<&str>> = one_of('x')(input);
+ }
+}
diff --git a/vendor/nom8/src/input.rs b/vendor/nom8/src/input.rs
new file mode 100644
index 000000000..3e87042ae
--- /dev/null
+++ b/vendor/nom8/src/input.rs
@@ -0,0 +1,2929 @@
+//! Input capability for nom combinators to parse
+//!
+//! Input types include:
+//! - `&str` and `&[u8]` are the standard input types
+//! - [`Located`] can track the location within the original buffer to report
+//! [spans][crate::Parser::with_span]
+//! - [`Stateful`] to thread global state through your parsers
+//! - [`Streaming`] can mark an input as partial buffer that is being streamed into
+//!
+//! # How do a parse a custom input type?
+//!
+//! While historically, nom has worked mainly on `&[u8]` and `&str`, it can actually
+//! use any type as input, as long as they follow a specific set of traits.
+//! Those traits were developed first to abstract away the differences between
+//! `&[u8]` and `&str`, but were then employed for more interesting types,
+//! like [nom_locate](https://github.com/fflorent/nom_locate), a wrapper type
+//! that can carry line and column information, or to parse
+//! [a list of tokens](https://github.com/Rydgel/monkey-rust/blob/master/lib/parser/mod.rs).
+//!
+//! ## Implementing a custom type
+//!
+//! Let's assume we have an input type we'll call `MyInput`. `MyInput` is a sequence of `MyItem` type.
+//! The goal is to define nom parsers with this signature: `MyInput -> IResult<MyInput, Output>`.
+//!
+//! ```rust,ignore
+//! fn parser(i: MyInput) -> IResult<MyInput, Output> {
+//! tag("test")(i)
+//! }
+//! ```
+//!
+//! Here are the traits we have to implement for `MyInput`:
+//!
+//! | trait | usage |
+//! |---|---|
+//! | [InputIsStreaming] | Marks the input as being the complete buffer or a partial buffer for streaming input |
+//! | [AsBytes] |Casts the input type to a byte slice|
+//! | [Compare] |Character comparison operations|
+//! | [ExtendInto] |Abstracts something which can extend an `Extend`|
+//! | [FindSubstring] |Look for a substring in self|
+//! | [FindToken] |Look for self in the given input stream|
+//! | [InputIter] |Common iteration operations on the input type|
+//! | [InputLength] |Calculate the input length|
+//! | [IntoOutput] |Adapt a captired `Input` into an appropriate type|
+//! | [Location] |Calculate location within initial input|
+//! | [InputTake] |Slicing operations|
+//! | [InputTakeAtPosition] |Look for a specific token and split at its position|
+//! | [Offset] |Calculate the offset between slices|
+//! | [ParseTo] |Used to integrate `&str`'s `parse()` method|
+//! | [Slice] |Slicing operations using ranges|
+//!
+//! Here are the traits we have to implement for `MyItem`:
+//!
+//! | trait | usage |
+//! |---|---|
+//! | [AsChar][AsChar] |Transforms common types to a char for basic token parsing|
+
+use core::num::NonZeroUsize;
+
+use crate::error::{ErrorKind, ParseError};
+use crate::lib::std::iter::{Copied, Enumerate};
+use crate::lib::std::ops::{
+ Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
+};
+use crate::lib::std::slice::Iter;
+use crate::lib::std::str::from_utf8;
+use crate::lib::std::str::CharIndices;
+use crate::lib::std::str::Chars;
+use crate::lib::std::str::FromStr;
+use crate::{Err, IResult, Needed};
+
+#[cfg(feature = "alloc")]
+use crate::lib::std::string::String;
+#[cfg(feature = "alloc")]
+use crate::lib::std::vec::Vec;
+
+/// Allow collecting the span of a parsed token
+///
+/// See [`Parser::span`][crate::Parser::span] and [`Parser::with_span`][crate::Parser::with_span] for more details
+#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Located<I> {
+ initial: I,
+ input: I,
+}
+
+impl<I> Located<I>
+where
+ I: Clone + IntoOutput + Offset,
+{
+ /// Wrap another Input with span tracking
+ pub fn new(input: I) -> Self {
+ let initial = input.clone();
+ Self { initial, input }
+ }
+
+ fn location(&self) -> usize {
+ self.initial.offset(&self.input)
+ }
+}
+
+impl<I> AsRef<I> for Located<I> {
+ fn as_ref(&self) -> &I {
+ &self.input
+ }
+}
+
+impl<I> crate::lib::std::ops::Deref for Located<I> {
+ type Target = I;
+
+ #[inline(always)]
+ fn deref(&self) -> &Self::Target {
+ &self.input
+ }
+}
+
+/// Thread global state through your parsers
+///
+/// Use cases
+/// - Recusion checks
+/// - Errror recovery
+/// - Debugging
+///
+/// # Example
+///
+/// ```
+/// # use std::cell::Cell;
+/// # use nom8::prelude::*;
+/// # use nom8::input::Stateful;
+/// # use nom8::character::alpha1;
+/// # type Error = ();
+///
+/// #[derive(Clone, Debug)]
+/// struct State<'s>(&'s Cell<u32>);
+///
+/// impl<'s> State<'s> {
+/// fn count(&self) {
+/// self.0.set(self.0.get() + 1);
+/// }
+/// }
+///
+/// type Input<'is> = Stateful<&'is str, State<'is>>;
+///
+/// fn word(i: Input<'_>) -> IResult<Input<'_>, &str> {
+/// i.state.count();
+/// alpha1(i)
+/// }
+///
+/// let data = "Hello";
+/// let state = Cell::new(0);
+/// let input = Input { input: data, state: State(&state) };
+/// let output = word.parse(input).finish().unwrap();
+/// assert_eq!(state.get(), 1);
+/// ```
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub struct Stateful<I, S> {
+ /// Inner input being wrapped in state
+ pub input: I,
+ /// User-provided state
+ pub state: S,
+}
+
+impl<I, S> AsRef<I> for Stateful<I, S> {
+ fn as_ref(&self) -> &I {
+ &self.input
+ }
+}
+
+impl<I, S> crate::lib::std::ops::Deref for Stateful<I, S> {
+ type Target = I;
+
+ fn deref(&self) -> &Self::Target {
+ self.as_ref()
+ }
+}
+
+/// Mark the input as a partial buffer for streaming input.
+///
+/// Complete input means that we already have all of the data. This will be the common case with
+/// small files that can be read entirely to memory.
+///
+/// In contrast, streaming input assumes that we might not have all of the data.
+/// This can happen with some network protocol or large file parsers, where the
+/// input buffer can be full and need to be resized or refilled.
+/// - [`Err::Incomplete`] will report how much more data is needed.
+/// - [`Parser::complete`][crate::Parser::complete] transform [`Err::Incomplete`] to
+/// [`Err::Error`]
+///
+/// See also [`InputIsStreaming`] to tell whether the input supports complete or streaming parsing.
+///
+/// # Example
+///
+/// Here is how it works in practice:
+///
+/// ```rust
+/// use nom8::{IResult, Err, Needed, error::{Error, ErrorKind}, bytes, character, input::Streaming};
+///
+/// fn take_streaming(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// bytes::take(4u8)(i)
+/// }
+///
+/// fn take_complete(i: &[u8]) -> IResult<&[u8], &[u8]> {
+/// bytes::take(4u8)(i)
+/// }
+///
+/// // both parsers will take 4 bytes as expected
+/// assert_eq!(take_streaming(Streaming(&b"abcde"[..])), Ok((Streaming(&b"e"[..]), &b"abcd"[..])));
+/// assert_eq!(take_complete(&b"abcde"[..]), Ok((&b"e"[..], &b"abcd"[..])));
+///
+/// // if the input is smaller than 4 bytes, the streaming parser
+/// // will return `Incomplete` to indicate that we need more data
+/// assert_eq!(take_streaming(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(1))));
+///
+/// // but the complete parser will return an error
+/// assert_eq!(take_complete(&b"abc"[..]), Err(Err::Error(Error::new(&b"abc"[..], ErrorKind::Eof))));
+///
+/// // the alpha0 function recognizes 0 or more alphabetic characters
+/// fn alpha0_streaming(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+/// character::alpha0(i)
+/// }
+///
+/// fn alpha0_complete(i: &str) -> IResult<&str, &str> {
+/// character::alpha0(i)
+/// }
+///
+/// // if there's a clear limit to the recognized characters, both parsers work the same way
+/// assert_eq!(alpha0_streaming(Streaming("abcd;")), Ok((Streaming(";"), "abcd")));
+/// assert_eq!(alpha0_complete("abcd;"), Ok((";", "abcd")));
+///
+/// // but when there's no limit, the streaming version returns `Incomplete`, because it cannot
+/// // know if more input data should be recognized. The whole input could be "abcd;", or
+/// // "abcde;"
+/// assert_eq!(alpha0_streaming(Streaming("abcd")), Err(Err::Incomplete(Needed::new(1))));
+///
+/// // while the complete version knows that all of the data is there
+/// assert_eq!(alpha0_complete("abcd"), Ok(("", "abcd")));
+/// ```
+#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Streaming<I>(pub I);
+
+impl<I> Streaming<I> {
+ /// Convert to complete counterpart
+ #[inline(always)]
+ pub fn into_complete(self) -> I {
+ self.0
+ }
+}
+
+impl<I> crate::lib::std::ops::Deref for Streaming<I> {
+ type Target = I;
+
+ #[inline(always)]
+ fn deref(&self) -> &Self::Target {
+ &self.0
+ }
+}
+
+/// Number of indices input has advanced since start of parsing
+pub trait Location {
+ /// Number of indices input has advanced since start of parsing
+ fn location(&self) -> usize;
+}
+
+impl<I> Location for Located<I>
+where
+ I: Clone + IntoOutput + Offset,
+{
+ fn location(&self) -> usize {
+ self.location()
+ }
+}
+
+impl<I, S> Location for Stateful<I, S>
+where
+ I: Location,
+{
+ fn location(&self) -> usize {
+ self.input.location()
+ }
+}
+
+impl<I> Location for Streaming<I>
+where
+ I: Location,
+{
+ fn location(&self) -> usize {
+ self.0.location()
+ }
+}
+
+/// Marks the input as being the complete buffer or a partial buffer for streaming input
+///
+/// See [Streaming] for marking a presumed complete buffer type as a streaming buffer.
+pub trait InputIsStreaming<const YES: bool>: Sized {
+ /// Complete counterpart
+ ///
+ /// - Set to `Self` if this is a complete buffer.
+ /// - Set to [`std::convert::Infallible`] if there isn't an associated complete buffer type
+ type Complete: InputIsStreaming<false>;
+ /// Streaming counterpart
+ ///
+ /// - Set to `Self` if this is a streaming buffer.
+ /// - Set to [`std::convert::Infallible`] if there isn't an associated streaming buffer type
+ type Streaming: InputIsStreaming<true>;
+
+ /// Convert to complete counterpart
+ fn into_complete(self) -> Self::Complete;
+ /// Convert to streaming counterpart
+ fn into_streaming(self) -> Self::Streaming;
+}
+
+impl<I> InputIsStreaming<true> for Located<I>
+where
+ I: InputIsStreaming<true>,
+{
+ type Complete = Located<<I as InputIsStreaming<true>>::Complete>;
+ type Streaming = Self;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ Located {
+ initial: self.initial.into_complete(),
+ input: self.input.into_complete(),
+ }
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ self
+ }
+}
+
+impl<I> InputIsStreaming<false> for Located<I>
+where
+ I: InputIsStreaming<false>,
+{
+ type Complete = Self;
+ type Streaming = Located<<I as InputIsStreaming<false>>::Streaming>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Located {
+ initial: self.initial.into_streaming(),
+ input: self.input.into_streaming(),
+ }
+ }
+}
+
+impl<I, S> InputIsStreaming<true> for Stateful<I, S>
+where
+ I: InputIsStreaming<true>,
+{
+ type Complete = Stateful<<I as InputIsStreaming<true>>::Complete, S>;
+ type Streaming = Self;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ Stateful {
+ input: self.input.into_complete(),
+ state: self.state,
+ }
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ self
+ }
+}
+
+impl<I, S> InputIsStreaming<false> for Stateful<I, S>
+where
+ I: InputIsStreaming<false>,
+{
+ type Complete = Self;
+ type Streaming = Stateful<<I as InputIsStreaming<false>>::Streaming, S>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Stateful {
+ input: self.input.into_streaming(),
+ state: self.state,
+ }
+ }
+}
+
+impl<I> InputIsStreaming<true> for Streaming<I>
+where
+ I: InputIsStreaming<false>,
+{
+ type Complete = I;
+ type Streaming = Self;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self.0
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ self
+ }
+}
+
+impl<'a, T> InputIsStreaming<false> for &'a [T] {
+ type Complete = Self;
+ type Streaming = Streaming<Self>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Streaming(self)
+ }
+}
+
+impl<T, const L: usize> InputIsStreaming<false> for [T; L] {
+ type Complete = Self;
+ type Streaming = Streaming<Self>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Streaming(self)
+ }
+}
+
+impl<'a, T, const L: usize> InputIsStreaming<false> for &'a [T; L] {
+ type Complete = Self;
+ type Streaming = Streaming<Self>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Streaming(self)
+ }
+}
+
+impl<'a> InputIsStreaming<false> for &'a str {
+ type Complete = Self;
+ type Streaming = Streaming<Self>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Streaming(self)
+ }
+}
+
+impl<'a> InputIsStreaming<false> for (&'a [u8], usize) {
+ type Complete = Self;
+ type Streaming = Streaming<Self>;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ Streaming(self)
+ }
+}
+
+impl<const YES: bool> InputIsStreaming<YES> for crate::lib::std::convert::Infallible {
+ type Complete = Self;
+ type Streaming = Self;
+
+ #[inline(always)]
+ fn into_complete(self) -> Self::Complete {
+ self
+ }
+ #[inline(always)]
+ fn into_streaming(self) -> Self::Streaming {
+ self
+ }
+}
+
+/// Abstract method to calculate the input length
+pub trait InputLength {
+ /// Calculates the input length, as indicated by its name,
+ /// and the name of the trait itself
+ fn input_len(&self) -> usize;
+}
+
+impl<I> InputLength for Located<I>
+where
+ I: InputLength,
+{
+ fn input_len(&self) -> usize {
+ self.input.input_len()
+ }
+}
+
+impl<I, S> InputLength for Stateful<I, S>
+where
+ I: InputLength,
+{
+ fn input_len(&self) -> usize {
+ self.input.input_len()
+ }
+}
+
+impl<I> InputLength for Streaming<I>
+where
+ I: InputLength,
+{
+ #[inline(always)]
+ fn input_len(&self) -> usize {
+ self.0.input_len()
+ }
+}
+
+impl<'a, T> InputLength for &'a [T] {
+ #[inline]
+ fn input_len(&self) -> usize {
+ self.len()
+ }
+}
+
+impl<const LEN: usize> InputLength for [u8; LEN] {
+ #[inline]
+ fn input_len(&self) -> usize {
+ self.len()
+ }
+}
+
+impl<'a, const LEN: usize> InputLength for &'a [u8; LEN] {
+ #[inline]
+ fn input_len(&self) -> usize {
+ self.len()
+ }
+}
+
+impl<'a> InputLength for &'a str {
+ #[inline]
+ fn input_len(&self) -> usize {
+ self.len()
+ }
+}
+
+impl<'a> InputLength for (&'a [u8], usize) {
+ #[inline]
+ fn input_len(&self) -> usize {
+ self.0.len() * 8 - self.1
+ }
+}
+
+/// Useful functions to calculate the offset between slices and show a hexdump of a slice
+pub trait Offset {
+ /// Offset between the first byte of self and the first byte of the argument
+ fn offset(&self, second: &Self) -> usize;
+}
+
+impl<I> Offset for Located<I>
+where
+ I: Offset,
+{
+ fn offset(&self, other: &Self) -> usize {
+ self.input.offset(&other.input)
+ }
+}
+
+impl<I, S> Offset for Stateful<I, S>
+where
+ I: Offset,
+{
+ fn offset(&self, other: &Self) -> usize {
+ self.input.offset(&other.input)
+ }
+}
+
+impl<I> Offset for Streaming<I>
+where
+ I: Offset,
+{
+ #[inline(always)]
+ fn offset(&self, second: &Self) -> usize {
+ self.0.offset(&second.0)
+ }
+}
+
+impl Offset for [u8] {
+ fn offset(&self, second: &Self) -> usize {
+ let fst = self.as_ptr();
+ let snd = second.as_ptr();
+
+ snd as usize - fst as usize
+ }
+}
+
+impl<'a> Offset for &'a [u8] {
+ fn offset(&self, second: &Self) -> usize {
+ let fst = self.as_ptr();
+ let snd = second.as_ptr();
+
+ snd as usize - fst as usize
+ }
+}
+
+impl Offset for str {
+ fn offset(&self, second: &Self) -> usize {
+ let fst = self.as_ptr();
+ let snd = second.as_ptr();
+
+ snd as usize - fst as usize
+ }
+}
+
+impl<'a> Offset for &'a str {
+ fn offset(&self, second: &Self) -> usize {
+ let fst = self.as_ptr();
+ let snd = second.as_ptr();
+
+ snd as usize - fst as usize
+ }
+}
+
+/// Helper trait for types that can be viewed as a byte slice
+pub trait AsBytes {
+ /// Casts the input type to a byte slice
+ fn as_bytes(&self) -> &[u8];
+}
+
+impl<I> AsBytes for Located<I>
+where
+ I: AsBytes,
+{
+ fn as_bytes(&self) -> &[u8] {
+ self.input.as_bytes()
+ }
+}
+
+impl<I, S> AsBytes for Stateful<I, S>
+where
+ I: AsBytes,
+{
+ fn as_bytes(&self) -> &[u8] {
+ self.input.as_bytes()
+ }
+}
+
+impl<I> AsBytes for Streaming<I>
+where
+ I: AsBytes,
+{
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ self.0.as_bytes()
+ }
+}
+
+impl AsBytes for [u8] {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ self
+ }
+}
+
+impl<'a> AsBytes for &'a [u8] {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ *self
+ }
+}
+
+impl<const LEN: usize> AsBytes for [u8; LEN] {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ self
+ }
+}
+
+impl<'a, const LEN: usize> AsBytes for &'a [u8; LEN] {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ *self
+ }
+}
+
+impl<'a> AsBytes for &'a str {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ (*self).as_bytes()
+ }
+}
+
+impl AsBytes for str {
+ #[inline(always)]
+ fn as_bytes(&self) -> &[u8] {
+ self.as_ref()
+ }
+}
+
+/// Transforms common types to a char for basic token parsing
+pub trait AsChar {
+ /// Makes a char from self
+ ///
+ /// ```
+ /// use nom8::input::AsChar as _;
+ ///
+ /// assert_eq!('a'.as_char(), 'a');
+ /// assert_eq!(u8::MAX.as_char(), std::char::from_u32(u8::MAX as u32).unwrap());
+ /// ```
+ fn as_char(self) -> char;
+
+ /// Tests that self is an alphabetic character
+ ///
+ /// Warning: for `&str` it recognizes alphabetic
+ /// characters outside of the 52 ASCII letters
+ fn is_alpha(self) -> bool;
+
+ /// Tests that self is an alphabetic character
+ /// or a decimal digit
+ fn is_alphanum(self) -> bool;
+ /// Tests that self is a decimal digit
+ fn is_dec_digit(self) -> bool;
+ /// Tests that self is an hex digit
+ fn is_hex_digit(self) -> bool;
+ /// Tests that self is an octal digit
+ fn is_oct_digit(self) -> bool;
+ /// Gets the len in bytes for self
+ fn len(self) -> usize;
+ /// Tests that self is ASCII space or tab
+ fn is_space(self) -> bool;
+ /// Tests if byte is ASCII newline: \n
+ fn is_newline(self) -> bool;
+}
+
+impl AsChar for u8 {
+ #[inline]
+ fn as_char(self) -> char {
+ self as char
+ }
+ #[inline]
+ fn is_alpha(self) -> bool {
+ (self >= 0x41 && self <= 0x5A) || (self >= 0x61 && self <= 0x7A)
+ }
+ #[inline]
+ fn is_alphanum(self) -> bool {
+ self.is_alpha() || self.is_dec_digit()
+ }
+ #[inline]
+ fn is_dec_digit(self) -> bool {
+ self >= 0x30 && self <= 0x39
+ }
+ #[inline]
+ fn is_hex_digit(self) -> bool {
+ (self >= 0x30 && self <= 0x39)
+ || (self >= 0x41 && self <= 0x46)
+ || (self >= 0x61 && self <= 0x66)
+ }
+ #[inline]
+ fn is_oct_digit(self) -> bool {
+ self >= 0x30 && self <= 0x37
+ }
+ #[inline]
+ fn len(self) -> usize {
+ 1
+ }
+ #[inline]
+ fn is_space(self) -> bool {
+ self == b' ' || self == b'\t'
+ }
+ fn is_newline(self) -> bool {
+ self == b'\n'
+ }
+}
+impl<'a> AsChar for &'a u8 {
+ #[inline]
+ fn as_char(self) -> char {
+ *self as char
+ }
+ #[inline]
+ fn is_alpha(self) -> bool {
+ (*self >= 0x41 && *self <= 0x5A) || (*self >= 0x61 && *self <= 0x7A)
+ }
+ #[inline]
+ fn is_alphanum(self) -> bool {
+ self.is_alpha() || self.is_dec_digit()
+ }
+ #[inline]
+ fn is_dec_digit(self) -> bool {
+ *self >= 0x30 && *self <= 0x39
+ }
+ #[inline]
+ fn is_hex_digit(self) -> bool {
+ (*self >= 0x30 && *self <= 0x39)
+ || (*self >= 0x41 && *self <= 0x46)
+ || (*self >= 0x61 && *self <= 0x66)
+ }
+ #[inline]
+ fn is_oct_digit(self) -> bool {
+ *self >= 0x30 && *self <= 0x37
+ }
+ #[inline]
+ fn len(self) -> usize {
+ 1
+ }
+ #[inline]
+ fn is_space(self) -> bool {
+ *self == b' ' || *self == b'\t'
+ }
+ fn is_newline(self) -> bool {
+ *self == b'\n'
+ }
+}
+
+impl AsChar for char {
+ #[inline]
+ fn as_char(self) -> char {
+ self
+ }
+ #[inline]
+ fn is_alpha(self) -> bool {
+ self.is_ascii_alphabetic()
+ }
+ #[inline]
+ fn is_alphanum(self) -> bool {
+ self.is_alpha() || self.is_dec_digit()
+ }
+ #[inline]
+ fn is_dec_digit(self) -> bool {
+ self.is_ascii_digit()
+ }
+ #[inline]
+ fn is_hex_digit(self) -> bool {
+ self.is_ascii_hexdigit()
+ }
+ #[inline]
+ fn is_oct_digit(self) -> bool {
+ self.is_digit(8)
+ }
+ #[inline]
+ fn len(self) -> usize {
+ self.len_utf8()
+ }
+ #[inline]
+ fn is_space(self) -> bool {
+ self == ' ' || self == '\t'
+ }
+ fn is_newline(self) -> bool {
+ self == '\n'
+ }
+}
+
+impl<'a> AsChar for &'a char {
+ #[inline]
+ fn as_char(self) -> char {
+ *self
+ }
+ #[inline]
+ fn is_alpha(self) -> bool {
+ self.is_ascii_alphabetic()
+ }
+ #[inline]
+ fn is_alphanum(self) -> bool {
+ self.is_alpha() || self.is_dec_digit()
+ }
+ #[inline]
+ fn is_dec_digit(self) -> bool {
+ self.is_ascii_digit()
+ }
+ #[inline]
+ fn is_hex_digit(self) -> bool {
+ self.is_ascii_hexdigit()
+ }
+ #[inline]
+ fn is_oct_digit(self) -> bool {
+ self.is_digit(8)
+ }
+ #[inline]
+ fn len(self) -> usize {
+ self.len_utf8()
+ }
+ #[inline]
+ fn is_space(self) -> bool {
+ *self == ' ' || *self == '\t'
+ }
+ fn is_newline(self) -> bool {
+ *self == '\n'
+ }
+}
+
+/// Abstracts common iteration operations on the input type
+pub trait InputIter {
+ /// The current input type is a sequence of that `Item` type.
+ ///
+ /// Example: `u8` for `&[u8]` or `char` for `&str`
+ type Item;
+ /// An iterator over the input type, producing the item and its position
+ /// for use with [Slice]. If we're iterating over `&str`, the position
+ /// corresponds to the byte index of the character
+ type Iter: Iterator<Item = (usize, Self::Item)>;
+
+ /// An iterator over the input type, producing the item
+ type IterElem: Iterator<Item = Self::Item>;
+
+ /// Returns an iterator over the elements and their byte offsets
+ fn iter_indices(&self) -> Self::Iter;
+ /// Returns an iterator over the elements
+ fn iter_elements(&self) -> Self::IterElem;
+ /// Finds the byte position of the element
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool;
+ /// Get the byte offset from the element's position in the stream
+ fn slice_index(&self, count: usize) -> Result<usize, Needed>;
+}
+
+impl<I> InputIter for Located<I>
+where
+ I: InputIter,
+{
+ type Item = I::Item;
+ type Iter = I::Iter;
+ type IterElem = I::IterElem;
+
+ fn iter_indices(&self) -> Self::Iter {
+ self.input.iter_indices()
+ }
+
+ fn iter_elements(&self) -> Self::IterElem {
+ self.input.iter_elements()
+ }
+
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ self.input.position(predicate)
+ }
+
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ self.input.slice_index(count)
+ }
+}
+
+impl<I, S> InputIter for Stateful<I, S>
+where
+ I: InputIter,
+{
+ type Item = I::Item;
+ type Iter = I::Iter;
+ type IterElem = I::IterElem;
+
+ fn iter_indices(&self) -> Self::Iter {
+ self.input.iter_indices()
+ }
+
+ fn iter_elements(&self) -> Self::IterElem {
+ self.input.iter_elements()
+ }
+
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ self.input.position(predicate)
+ }
+
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ self.input.slice_index(count)
+ }
+}
+
+impl<I> InputIter for Streaming<I>
+where
+ I: InputIter,
+{
+ type Item = I::Item;
+ type Iter = I::Iter;
+ type IterElem = I::IterElem;
+
+ #[inline(always)]
+ fn iter_indices(&self) -> Self::Iter {
+ self.0.iter_indices()
+ }
+ #[inline(always)]
+ fn iter_elements(&self) -> Self::IterElem {
+ self.0.iter_elements()
+ }
+ #[inline(always)]
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ self.0.position(predicate)
+ }
+ #[inline(always)]
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ self.0.slice_index(count)
+ }
+}
+impl<'a> InputIter for &'a [u8] {
+ type Item = u8;
+ type Iter = Enumerate<Self::IterElem>;
+ type IterElem = Copied<Iter<'a, u8>>;
+
+ #[inline]
+ fn iter_indices(&self) -> Self::Iter {
+ self.iter_elements().enumerate()
+ }
+ #[inline]
+ fn iter_elements(&self) -> Self::IterElem {
+ self.iter().copied()
+ }
+ #[inline]
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ self.iter().position(|b| predicate(*b))
+ }
+ #[inline]
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ if let Some(needed) = count.checked_sub(self.len()).and_then(NonZeroUsize::new) {
+ Err(Needed::Size(needed))
+ } else {
+ Ok(count)
+ }
+ }
+}
+
+impl<'a, const LEN: usize> InputIter for &'a [u8; LEN] {
+ type Item = u8;
+ type Iter = Enumerate<Self::IterElem>;
+ type IterElem = Copied<Iter<'a, u8>>;
+
+ fn iter_indices(&self) -> Self::Iter {
+ (&self[..]).iter_indices()
+ }
+
+ fn iter_elements(&self) -> Self::IterElem {
+ (&self[..]).iter_elements()
+ }
+
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ (&self[..]).position(predicate)
+ }
+
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ (&self[..]).slice_index(count)
+ }
+}
+
+impl<'a> InputIter for &'a str {
+ type Item = char;
+ type Iter = CharIndices<'a>;
+ type IterElem = Chars<'a>;
+ #[inline]
+ fn iter_indices(&self) -> Self::Iter {
+ self.char_indices()
+ }
+ #[inline]
+ fn iter_elements(&self) -> Self::IterElem {
+ self.chars()
+ }
+ fn position<P>(&self, predicate: P) -> Option<usize>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ for (o, c) in self.char_indices() {
+ if predicate(c) {
+ return Some(o);
+ }
+ }
+ None
+ }
+ #[inline]
+ fn slice_index(&self, count: usize) -> Result<usize, Needed> {
+ let mut cnt = 0;
+ for (index, _) in self.char_indices() {
+ if cnt == count {
+ return Ok(index);
+ }
+ cnt += 1;
+ }
+ if cnt == count {
+ return Ok(self.len());
+ }
+ Err(Needed::Unknown)
+ }
+}
+
+/// Abstracts slicing operations
+pub trait InputTake: Sized {
+ /// Returns a slice of `count` bytes. panics if count > length
+ fn take(&self, count: usize) -> Self;
+ /// Split the stream at the `count` byte offset. panics if count > length
+ fn take_split(&self, count: usize) -> (Self, Self);
+}
+
+impl<I> InputTake for Located<I>
+where
+ I: InputTake + Clone,
+{
+ fn take(&self, count: usize) -> Self {
+ Self {
+ initial: self.initial.clone(),
+ input: self.input.take(count),
+ }
+ }
+
+ fn take_split(&self, count: usize) -> (Self, Self) {
+ let (left, right) = self.input.take_split(count);
+ (
+ Self {
+ initial: self.initial.clone(),
+ input: left,
+ },
+ Self {
+ initial: self.initial.clone(),
+ input: right,
+ },
+ )
+ }
+}
+
+impl<I, S> InputTake for Stateful<I, S>
+where
+ I: InputTake,
+ S: Clone,
+{
+ fn take(&self, count: usize) -> Self {
+ Self {
+ input: self.input.take(count),
+ state: self.state.clone(),
+ }
+ }
+
+ fn take_split(&self, count: usize) -> (Self, Self) {
+ let (left, right) = self.input.take_split(count);
+ (
+ Self {
+ input: left,
+ state: self.state.clone(),
+ },
+ Self {
+ input: right,
+ state: self.state.clone(),
+ },
+ )
+ }
+}
+
+impl<I> InputTake for Streaming<I>
+where
+ I: InputTake,
+{
+ #[inline(always)]
+ fn take(&self, count: usize) -> Self {
+ Streaming(self.0.take(count))
+ }
+ #[inline(always)]
+ fn take_split(&self, count: usize) -> (Self, Self) {
+ let (start, end) = self.0.take_split(count);
+ (Streaming(start), Streaming(end))
+ }
+}
+
+impl<'a> InputTake for &'a [u8] {
+ #[inline]
+ fn take(&self, count: usize) -> Self {
+ &self[0..count]
+ }
+ #[inline]
+ fn take_split(&self, count: usize) -> (Self, Self) {
+ let (prefix, suffix) = self.split_at(count);
+ (suffix, prefix)
+ }
+}
+
+impl<'a> InputTake for &'a str {
+ #[inline]
+ fn take(&self, count: usize) -> Self {
+ &self[..count]
+ }
+
+ // return byte index
+ #[inline]
+ fn take_split(&self, count: usize) -> (Self, Self) {
+ let (prefix, suffix) = self.split_at(count);
+ (suffix, prefix)
+ }
+}
+
+/// Dummy trait used for default implementations (currently only used for `InputTakeAtPosition` and `Compare`).
+///
+/// When implementing a custom input type, it is possible to use directly the
+/// default implementation: If the input type implements `InputLength`, `InputIter`,
+/// `InputTake` and `Clone`, you can implement `UnspecializedInput` and get
+/// a default version of `InputTakeAtPosition` and `Compare`.
+///
+/// For performance reasons, you might want to write a custom implementation of
+/// `InputTakeAtPosition` (like the one for `&[u8]`).
+pub trait UnspecializedInput {}
+
+/// Methods to take as much input as possible until the provided function returns true for the current element.
+///
+/// A large part of nom's basic parsers are built using this trait.
+pub trait InputTakeAtPosition: Sized {
+ /// The current input type is a sequence of that `Item` type.
+ ///
+ /// Example: `u8` for `&[u8]` or `char` for `&str`
+ type Item;
+
+ /// Looks for the first element of the input type for which the condition returns true,
+ /// and returns the input up to this position.
+ ///
+ /// *streaming version*: If no element is found matching the condition, this will return `Incomplete`
+ fn split_at_position_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool;
+
+ /// Looks for the first element of the input type for which the condition returns true
+ /// and returns the input up to this position.
+ ///
+ /// Fails if the produced slice is empty.
+ ///
+ /// *streaming version*: If no element is found matching the condition, this will return `Incomplete`
+ fn split_at_position1_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool;
+
+ /// Looks for the first element of the input type for which the condition returns true,
+ /// and returns the input up to this position.
+ ///
+ /// *complete version*: If no element is found matching the condition, this will return the whole input
+ fn split_at_position_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool;
+
+ /// Looks for the first element of the input type for which the condition returns true
+ /// and returns the input up to this position.
+ ///
+ /// Fails if the produced slice is empty.
+ ///
+ /// *complete version*: If no element is found matching the condition, this will return the whole input
+ fn split_at_position1_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool;
+}
+
+impl<I> InputTakeAtPosition for Located<I>
+where
+ I: InputTakeAtPosition + Clone,
+{
+ type Item = <I as InputTakeAtPosition>::Item;
+
+ fn split_at_position_complete<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ located_clone_map_result(self, move |data| data.split_at_position_complete(predicate))
+ }
+
+ fn split_at_position_streaming<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ located_clone_map_result(self, move |data| {
+ data.split_at_position_streaming(predicate)
+ })
+ }
+
+ fn split_at_position1_streaming<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ located_clone_map_result(self, move |data| {
+ data.split_at_position1_streaming(predicate, kind)
+ })
+ }
+
+ fn split_at_position1_complete<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ located_clone_map_result(self, move |data| {
+ data.split_at_position1_complete(predicate, kind)
+ })
+ }
+}
+
+fn located_clone_map_result<I, E, F>(input: &Located<I>, f: F) -> IResult<Located<I>, Located<I>, E>
+where
+ I: Clone,
+ E: ParseError<Located<I>>,
+ F: FnOnce(&I) -> IResult<I, I>,
+{
+ let map_error = |error: crate::error::Error<I>| {
+ E::from_error_kind(
+ Located {
+ initial: input.initial.clone(),
+ input: error.input,
+ },
+ error.code,
+ )
+ };
+ f(&input.input)
+ .map(|(remaining, output)| {
+ (
+ Located {
+ initial: input.initial.clone(),
+ input: remaining,
+ },
+ Located {
+ initial: input.initial.clone(),
+ input: output,
+ },
+ )
+ })
+ .map_err(|error| match error {
+ Err::Error(error) => Err::Error(map_error(error)),
+ Err::Failure(error) => Err::Failure(map_error(error)),
+ Err::Incomplete(needed) => Err::Incomplete(needed),
+ })
+}
+
+impl<I, S> InputTakeAtPosition for Stateful<I, S>
+where
+ I: InputTakeAtPosition,
+ S: Clone,
+{
+ type Item = <I as InputTakeAtPosition>::Item;
+
+ fn split_at_position_complete<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ stateful_clone_map_result(self, move |data| data.split_at_position_complete(predicate))
+ }
+
+ fn split_at_position_streaming<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ stateful_clone_map_result(self, move |data| {
+ data.split_at_position_streaming(predicate)
+ })
+ }
+
+ fn split_at_position1_streaming<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ stateful_clone_map_result(self, move |data| {
+ data.split_at_position1_streaming(predicate, kind)
+ })
+ }
+
+ fn split_at_position1_complete<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ stateful_clone_map_result(self, move |data| {
+ data.split_at_position1_complete(predicate, kind)
+ })
+ }
+}
+
+fn stateful_clone_map_result<I, S, E, F>(
+ input: &Stateful<I, S>,
+ f: F,
+) -> IResult<Stateful<I, S>, Stateful<I, S>, E>
+where
+ E: ParseError<Stateful<I, S>>,
+ S: Clone,
+ F: FnOnce(&I) -> IResult<I, I>,
+{
+ let map_error = |error: crate::error::Error<I>| {
+ E::from_error_kind(
+ Stateful {
+ input: error.input,
+ state: input.state.clone(),
+ },
+ error.code,
+ )
+ };
+ f(&input.input)
+ .map(|(remaining, output)| {
+ (
+ Stateful {
+ input: remaining,
+ state: input.state.clone(),
+ },
+ Stateful {
+ input: output,
+ state: input.state.clone(),
+ },
+ )
+ })
+ .map_err(|error| match error {
+ Err::Error(error) => Err::Error(map_error(error)),
+ Err::Failure(error) => Err::Failure(map_error(error)),
+ Err::Incomplete(needed) => Err::Incomplete(needed),
+ })
+}
+
+impl<I> InputTakeAtPosition for Streaming<I>
+where
+ I: InputTakeAtPosition,
+{
+ type Item = <I as InputTakeAtPosition>::Item;
+
+ fn split_at_position_complete<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ streaming_clone_map_result(self, move |data| data.split_at_position_complete(predicate))
+ }
+
+ fn split_at_position_streaming<P, E>(&self, predicate: P) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ streaming_clone_map_result(self, move |data| {
+ data.split_at_position_streaming(predicate)
+ })
+ }
+
+ fn split_at_position1_streaming<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ streaming_clone_map_result(self, move |data| {
+ data.split_at_position1_streaming(predicate, kind)
+ })
+ }
+
+ fn split_at_position1_complete<P, E>(
+ &self,
+ predicate: P,
+ kind: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ E: ParseError<Self>,
+ {
+ streaming_clone_map_result(self, move |data| {
+ data.split_at_position1_complete(predicate, kind)
+ })
+ }
+}
+
+fn streaming_clone_map_result<I, E, F>(
+ input: &Streaming<I>,
+ f: F,
+) -> IResult<Streaming<I>, Streaming<I>, E>
+where
+ E: ParseError<Streaming<I>>,
+ F: FnOnce(&I) -> IResult<I, I>,
+{
+ let map_error =
+ |error: crate::error::Error<I>| E::from_error_kind(Streaming(error.input), error.code);
+ f(&input.0)
+ .map(|(remaining, output)| (Streaming(remaining), Streaming(output)))
+ .map_err(|error| match error {
+ Err::Error(error) => Err::Error(map_error(error)),
+ Err::Failure(error) => Err::Failure(map_error(error)),
+ Err::Incomplete(needed) => Err::Incomplete(needed),
+ })
+}
+
+impl<I: InputLength + InputIter + InputTake + Clone + UnspecializedInput> InputTakeAtPosition
+ for I
+{
+ type Item = <I as InputIter>::Item;
+
+ fn split_at_position_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.position(predicate) {
+ Some(n) => Ok(self.take_split(n)),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position1_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.position(predicate) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
+ Some(n) => Ok(self.take_split(n)),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.position(predicate) {
+ Some(n) => Ok(self.take_split(n)),
+ None => Ok(self.take_split(self.input_len())),
+ }
+ }
+
+ fn split_at_position1_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.position(predicate) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self.clone(), e))),
+ Some(n) => Ok(self.take_split(n)),
+ None => {
+ if self.input_len() == 0 {
+ Err(Err::Error(E::from_error_kind(self.clone(), e)))
+ } else {
+ Ok(self.take_split(self.input_len()))
+ }
+ }
+ }
+ }
+}
+
+impl<'a> InputTakeAtPosition for &'a [u8] {
+ type Item = u8;
+
+ fn split_at_position_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.iter().position(|c| predicate(*c)) {
+ Some(i) => Ok(self.take_split(i)),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position1_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.iter().position(|c| predicate(*c)) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self, e))),
+ Some(i) => Ok(self.take_split(i)),
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.iter().position(|c| predicate(*c)) {
+ Some(i) => Ok(self.take_split(i)),
+ None => Ok(self.take_split(self.input_len())),
+ }
+ }
+
+ fn split_at_position1_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.iter().position(|c| predicate(*c)) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self, e))),
+ Some(i) => Ok(self.take_split(i)),
+ None => {
+ if self.is_empty() {
+ Err(Err::Error(E::from_error_kind(self, e)))
+ } else {
+ Ok(self.take_split(self.input_len()))
+ }
+ }
+ }
+ }
+}
+
+impl<'a> InputTakeAtPosition for &'a str {
+ type Item = char;
+
+ fn split_at_position_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.find(predicate) {
+ // find() returns a byte index that is already in the slice at a char boundary
+ Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) },
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position1_streaming<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.find(predicate) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self, e))),
+ // find() returns a byte index that is already in the slice at a char boundary
+ Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) },
+ None => Err(Err::Incomplete(Needed::new(1))),
+ }
+ }
+
+ fn split_at_position_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.find(predicate) {
+ // find() returns a byte index that is already in the slice at a char boundary
+ Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) },
+ // the end of slice is a char boundary
+ None => unsafe {
+ Ok((
+ self.get_unchecked(self.len()..),
+ self.get_unchecked(..self.len()),
+ ))
+ },
+ }
+ }
+
+ fn split_at_position1_complete<P, E: ParseError<Self>>(
+ &self,
+ predicate: P,
+ e: ErrorKind,
+ ) -> IResult<Self, Self, E>
+ where
+ P: Fn(Self::Item) -> bool,
+ {
+ match self.find(predicate) {
+ Some(0) => Err(Err::Error(E::from_error_kind(self, e))),
+ // find() returns a byte index that is already in the slice at a char boundary
+ Some(i) => unsafe { Ok((self.get_unchecked(i..), self.get_unchecked(..i))) },
+ None => {
+ if self.is_empty() {
+ Err(Err::Error(E::from_error_kind(self, e)))
+ } else {
+ // the end of slice is a char boundary
+ unsafe {
+ Ok((
+ self.get_unchecked(self.len()..),
+ self.get_unchecked(..self.len()),
+ ))
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Indicates whether a comparison was successful, an error, or
+/// if more data was needed
+#[derive(Debug, PartialEq)]
+pub enum CompareResult {
+ /// Comparison was successful
+ Ok,
+ /// We need more data to be sure
+ Incomplete,
+ /// Comparison failed
+ Error,
+}
+
+/// Abstracts comparison operations
+pub trait Compare<T> {
+ /// Compares self to another value for equality
+ fn compare(&self, t: T) -> CompareResult;
+ /// Compares self to another value for equality
+ /// independently of the case.
+ ///
+ /// Warning: for `&str`, the comparison is done
+ /// by lowercasing both strings and comparing
+ /// the result. This is a temporary solution until
+ /// a better one appears
+ fn compare_no_case(&self, t: T) -> CompareResult;
+}
+
+impl<I, U> Compare<U> for Located<I>
+where
+ I: Compare<U>,
+{
+ fn compare(&self, other: U) -> CompareResult {
+ self.input.compare(other)
+ }
+
+ fn compare_no_case(&self, other: U) -> CompareResult {
+ self.input.compare_no_case(other)
+ }
+}
+
+impl<I, S, U> Compare<U> for Stateful<I, S>
+where
+ I: Compare<U>,
+{
+ fn compare(&self, other: U) -> CompareResult {
+ self.input.compare(other)
+ }
+
+ fn compare_no_case(&self, other: U) -> CompareResult {
+ self.input.compare_no_case(other)
+ }
+}
+
+impl<I, T> Compare<T> for Streaming<I>
+where
+ I: Compare<T>,
+{
+ #[inline(always)]
+ fn compare(&self, t: T) -> CompareResult {
+ self.0.compare(t)
+ }
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: T) -> CompareResult {
+ self.0.compare_no_case(t)
+ }
+}
+
+fn lowercase_byte(c: u8) -> u8 {
+ match c {
+ b'A'..=b'Z' => c - b'A' + b'a',
+ _ => c,
+ }
+}
+
+impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: &'b [u8]) -> CompareResult {
+ let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b);
+
+ match pos {
+ Some(_) => CompareResult::Error,
+ None => {
+ if self.len() >= t.len() {
+ CompareResult::Ok
+ } else {
+ CompareResult::Incomplete
+ }
+ }
+ }
+ }
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
+ if self
+ .iter()
+ .zip(t)
+ .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b))
+ {
+ CompareResult::Error
+ } else if self.len() < t.len() {
+ CompareResult::Incomplete
+ } else {
+ CompareResult::Ok
+ }
+ }
+}
+
+impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: &'b [u8; LEN]) -> CompareResult {
+ self.compare(&t[..])
+ }
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult {
+ self.compare_no_case(&t[..])
+ }
+}
+
+impl<
+ T: InputLength + InputIter<Item = u8> + InputTake + UnspecializedInput,
+ O: InputLength + InputIter<Item = u8> + InputTake,
+ > Compare<O> for T
+{
+ #[inline(always)]
+ fn compare(&self, t: O) -> CompareResult {
+ let pos = self
+ .iter_elements()
+ .zip(t.iter_elements())
+ .position(|(a, b)| a != b);
+
+ match pos {
+ Some(_) => CompareResult::Error,
+ None => {
+ if self.input_len() >= t.input_len() {
+ CompareResult::Ok
+ } else {
+ CompareResult::Incomplete
+ }
+ }
+ }
+ }
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: O) -> CompareResult {
+ if self
+ .iter_elements()
+ .zip(t.iter_elements())
+ .any(|(a, b)| lowercase_byte(a) != lowercase_byte(b))
+ {
+ CompareResult::Error
+ } else if self.input_len() < t.input_len() {
+ CompareResult::Incomplete
+ } else {
+ CompareResult::Ok
+ }
+ }
+}
+
+impl<'a, 'b> Compare<&'b str> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: &'b str) -> CompareResult {
+ self.compare(AsBytes::as_bytes(t))
+ }
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b str) -> CompareResult {
+ self.compare_no_case(AsBytes::as_bytes(t))
+ }
+}
+
+impl<'a, 'b> Compare<&'b str> for &'a str {
+ #[inline(always)]
+ fn compare(&self, t: &'b str) -> CompareResult {
+ self.as_bytes().compare(t.as_bytes())
+ }
+
+ //FIXME: this version is too simple and does not use the current locale
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b str) -> CompareResult {
+ let pos = self
+ .chars()
+ .zip(t.chars())
+ .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase()));
+
+ match pos {
+ Some(_) => CompareResult::Error,
+ None => {
+ if self.len() >= t.len() {
+ CompareResult::Ok
+ } else {
+ CompareResult::Incomplete
+ }
+ }
+ }
+ }
+}
+
+impl<'a, 'b> Compare<&'b [u8]> for &'a str {
+ #[inline(always)]
+ fn compare(&self, t: &'b [u8]) -> CompareResult {
+ AsBytes::as_bytes(self).compare(t)
+ }
+ #[inline(always)]
+ fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
+ AsBytes::as_bytes(self).compare_no_case(t)
+ }
+}
+
+impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: [u8; LEN]) -> CompareResult {
+ self.compare(&t[..])
+ }
+
+ #[inline(always)]
+ fn compare_no_case(&self, t: [u8; LEN]) -> CompareResult {
+ self.compare_no_case(&t[..])
+ }
+}
+
+/// Check if a token in in a set of possible tokens
+///
+/// This is generally implemented on patterns that a token may match and supports `u8` and `char`
+/// tokens along with the following patterns
+/// - `b'c'` and `'c'`
+/// - `b""` and `""`
+/// - `|c| true`
+/// - `b'a'..=b'z'`, `'a'..='z'` (etc for each [range type][std::ops])
+/// - `(pattern1, pattern2, ...)`
+///
+/// For example, you could implement `hex_digit0` as:
+/// ```
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::ErrorKind, error::Error, Needed};
+/// # use nom8::bytes::take_while1;
+/// fn hex_digit1(input: &str) -> IResult<&str, &str> {
+/// take_while1(('a'..='f', 'A'..='F', '0'..='9')).parse(input)
+/// }
+///
+/// assert_eq!(hex_digit1("21cZ"), Ok(("Z", "21c")));
+/// assert_eq!(hex_digit1("H2"), Err(Err::Error(Error::new("H2", ErrorKind::TakeWhile1))));
+/// assert_eq!(hex_digit1(""), Err(Err::Error(Error::new("", ErrorKind::TakeWhile1))));
+/// ```
+pub trait FindToken<T> {
+ /// Returns true if self contains the token
+ fn find_token(&self, token: T) -> bool;
+}
+
+impl<I, T> FindToken<T> for Streaming<I>
+where
+ I: FindToken<T>,
+{
+ #[inline(always)]
+ fn find_token(&self, token: T) -> bool {
+ self.0.find_token(token)
+ }
+}
+
+impl FindToken<u8> for u8 {
+ fn find_token(&self, token: u8) -> bool {
+ *self == token
+ }
+}
+
+impl<'a> FindToken<&'a u8> for u8 {
+ fn find_token(&self, token: &u8) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl FindToken<char> for u8 {
+ fn find_token(&self, token: char) -> bool {
+ self.as_char() == token
+ }
+}
+
+impl<'a> FindToken<&'a char> for u8 {
+ fn find_token(&self, token: &char) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<C: AsChar> FindToken<C> for char {
+ fn find_token(&self, token: C) -> bool {
+ *self == token.as_char()
+ }
+}
+
+impl<C: AsChar, F: Fn(C) -> bool> FindToken<C> for F {
+ fn find_token(&self, token: C) -> bool {
+ self(token)
+ }
+}
+
+impl<C1: AsChar, C2: AsChar + Clone> FindToken<C1> for Range<C2> {
+ fn find_token(&self, token: C1) -> bool {
+ let start = self.start.clone().as_char();
+ let end = self.end.clone().as_char();
+ (start..end).contains(&token.as_char())
+ }
+}
+
+impl<C1: AsChar, C2: AsChar + Clone> FindToken<C1> for RangeInclusive<C2> {
+ fn find_token(&self, token: C1) -> bool {
+ let start = self.start().clone().as_char();
+ let end = self.end().clone().as_char();
+ (start..=end).contains(&token.as_char())
+ }
+}
+
+impl<C1: AsChar, C2: AsChar + Clone> FindToken<C1> for RangeFrom<C2> {
+ fn find_token(&self, token: C1) -> bool {
+ let start = self.start.clone().as_char();
+ (start..).contains(&token.as_char())
+ }
+}
+
+impl<C1: AsChar, C2: AsChar + Clone> FindToken<C1> for RangeTo<C2> {
+ fn find_token(&self, token: C1) -> bool {
+ let end = self.end.clone().as_char();
+ (..end).contains(&token.as_char())
+ }
+}
+
+impl<C1: AsChar, C2: AsChar + Clone> FindToken<C1> for RangeToInclusive<C2> {
+ fn find_token(&self, token: C1) -> bool {
+ let end = self.end.clone().as_char();
+ (..=end).contains(&token.as_char())
+ }
+}
+
+impl<C1: AsChar> FindToken<C1> for RangeFull {
+ fn find_token(&self, _token: C1) -> bool {
+ true
+ }
+}
+
+impl<'a> FindToken<u8> for &'a [u8] {
+ fn find_token(&self, token: u8) -> bool {
+ memchr::memchr(token, self).is_some()
+ }
+}
+
+impl<'a, 'b> FindToken<&'a u8> for &'b [u8] {
+ fn find_token(&self, token: &u8) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<'a> FindToken<char> for &'a [u8] {
+ fn find_token(&self, token: char) -> bool {
+ self.iter().any(|i| i.as_char() == token)
+ }
+}
+
+impl<'a, 'b> FindToken<&'a char> for &'b [u8] {
+ fn find_token(&self, token: &char) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<const LEN: usize> FindToken<u8> for [u8; LEN] {
+ fn find_token(&self, token: u8) -> bool {
+ memchr::memchr(token, &self[..]).is_some()
+ }
+}
+
+impl<'a, const LEN: usize> FindToken<&'a u8> for [u8; LEN] {
+ fn find_token(&self, token: &u8) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<'a, const LEN: usize> FindToken<char> for [u8; LEN] {
+ fn find_token(&self, token: char) -> bool {
+ self.iter().any(|i| i.as_char() == token)
+ }
+}
+
+impl<'a, const LEN: usize> FindToken<&'a char> for [u8; LEN] {
+ fn find_token(&self, token: &char) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<'a> FindToken<u8> for &'a str {
+ fn find_token(&self, token: u8) -> bool {
+ self.as_bytes().find_token(token)
+ }
+}
+
+impl<'a, 'b> FindToken<&'a u8> for &'b str {
+ fn find_token(&self, token: &u8) -> bool {
+ self.as_bytes().find_token(token)
+ }
+}
+
+impl<'a> FindToken<char> for &'a str {
+ fn find_token(&self, token: char) -> bool {
+ self.chars().any(|i| i == token)
+ }
+}
+
+impl<'a, 'b> FindToken<&'a char> for &'b str {
+ fn find_token(&self, token: &char) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<'a> FindToken<u8> for &'a [char] {
+ fn find_token(&self, token: u8) -> bool {
+ self.iter().any(|i| *i == token.as_char())
+ }
+}
+
+impl<'a, 'b> FindToken<&'a u8> for &'b [char] {
+ fn find_token(&self, token: &u8) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<'a> FindToken<char> for &'a [char] {
+ fn find_token(&self, token: char) -> bool {
+ self.iter().any(|i| *i == token)
+ }
+}
+
+impl<'a, 'b> FindToken<&'a char> for &'b [char] {
+ fn find_token(&self, token: &char) -> bool {
+ self.find_token(*token)
+ }
+}
+
+impl<T> FindToken<T> for () {
+ fn find_token(&self, _token: T) -> bool {
+ false
+ }
+}
+
+macro_rules! impl_find_token_for_tuple {
+ ($($haystack:ident),+) => (
+ #[allow(non_snake_case)]
+ impl<T, $($haystack),+> FindToken<T> for ($($haystack),+,)
+ where
+ T: Clone,
+ $($haystack: FindToken<T>),+
+ {
+ fn find_token(&self, token: T) -> bool {
+ let ($(ref $haystack),+,) = *self;
+ $($haystack.find_token(token.clone()) || )+ false
+ }
+ }
+ )
+}
+
+macro_rules! impl_find_token_for_tuples {
+ ($haystack1:ident, $($haystack:ident),+) => {
+ impl_find_token_for_tuples!(__impl $haystack1; $($haystack),+);
+ };
+ (__impl $($haystack:ident),+; $haystack1:ident $(,$haystack2:ident)*) => {
+ impl_find_token_for_tuple!($($haystack),+);
+ impl_find_token_for_tuples!(__impl $($haystack),+, $haystack1; $($haystack2),*);
+ };
+ (__impl $($haystack:ident),+;) => {
+ impl_find_token_for_tuple!($($haystack),+);
+ }
+}
+
+impl_find_token_for_tuples!(
+ F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, F13, F14, F15, F16, F17, F18, F19, F20, F21
+);
+
+/// Look for a substring in self
+pub trait FindSubstring<T> {
+ /// Returns the byte position of the substring if it is found
+ fn find_substring(&self, substr: T) -> Option<usize>;
+}
+
+impl<I, T> FindSubstring<T> for Located<I>
+where
+ I: FindSubstring<T>,
+{
+ #[inline(always)]
+ fn find_substring(&self, substr: T) -> Option<usize> {
+ self.input.find_substring(substr)
+ }
+}
+
+impl<I, S, T> FindSubstring<T> for Stateful<I, S>
+where
+ I: FindSubstring<T>,
+{
+ #[inline(always)]
+ fn find_substring(&self, substr: T) -> Option<usize> {
+ self.input.find_substring(substr)
+ }
+}
+
+impl<I, T> FindSubstring<T> for Streaming<I>
+where
+ I: FindSubstring<T>,
+{
+ #[inline(always)]
+ fn find_substring(&self, substr: T) -> Option<usize> {
+ self.0.find_substring(substr)
+ }
+}
+
+impl<'a, 'b> FindSubstring<&'b [u8]> for &'a [u8] {
+ fn find_substring(&self, substr: &'b [u8]) -> Option<usize> {
+ if substr.len() > self.len() {
+ return None;
+ }
+
+ let (&substr_first, substr_rest) = match substr.split_first() {
+ Some(split) => split,
+ // an empty substring is found at position 0
+ // This matches the behavior of str.find("").
+ None => return Some(0),
+ };
+
+ if substr_rest.is_empty() {
+ return memchr::memchr(substr_first, self);
+ }
+
+ let mut offset = 0;
+ let haystack = &self[..self.len() - substr_rest.len()];
+
+ while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) {
+ offset += position;
+ let next_offset = offset + 1;
+ if &self[next_offset..][..substr_rest.len()] == substr_rest {
+ return Some(offset);
+ }
+
+ offset = next_offset;
+ }
+
+ None
+ }
+}
+
+impl<'a, 'b> FindSubstring<&'b str> for &'a [u8] {
+ fn find_substring(&self, substr: &'b str) -> Option<usize> {
+ self.find_substring(AsBytes::as_bytes(substr))
+ }
+}
+
+impl<'a, 'b> FindSubstring<&'b str> for &'a str {
+ //returns byte index
+ fn find_substring(&self, substr: &'b str) -> Option<usize> {
+ self.find(substr)
+ }
+}
+
+/// Used to integrate `str`'s `parse()` method
+pub trait ParseTo<R> {
+ /// Succeeds if `parse()` succeeded. The byte slice implementation
+ /// will first convert it to a `&str`, then apply the `parse()` function
+ fn parse_to(&self) -> Option<R>;
+}
+
+impl<I, R> ParseTo<R> for Located<I>
+where
+ I: ParseTo<R>,
+{
+ #[inline(always)]
+ fn parse_to(&self) -> Option<R> {
+ self.input.parse_to()
+ }
+}
+
+impl<I, S, R> ParseTo<R> for Stateful<I, S>
+where
+ I: ParseTo<R>,
+{
+ #[inline(always)]
+ fn parse_to(&self) -> Option<R> {
+ self.input.parse_to()
+ }
+}
+
+impl<I, R> ParseTo<R> for Streaming<I>
+where
+ I: ParseTo<R>,
+{
+ #[inline(always)]
+ fn parse_to(&self) -> Option<R> {
+ self.0.parse_to()
+ }
+}
+
+impl<'a, R: FromStr> ParseTo<R> for &'a [u8] {
+ fn parse_to(&self) -> Option<R> {
+ from_utf8(self).ok().and_then(|s| s.parse().ok())
+ }
+}
+
+impl<'a, R: FromStr> ParseTo<R> for &'a str {
+ fn parse_to(&self) -> Option<R> {
+ self.parse().ok()
+ }
+}
+
+/// Slicing operations using ranges.
+///
+/// This trait is loosely based on
+/// `Index`, but can actually return
+/// something else than a `&[T]` or `&str`
+pub trait Slice<R> {
+ /// Slices self according to the range argument
+ fn slice(&self, range: R) -> Self;
+}
+
+impl<I, R> Slice<R> for Located<I>
+where
+ I: Slice<R> + Clone,
+{
+ #[inline(always)]
+ fn slice(&self, range: R) -> Self {
+ Located {
+ initial: self.initial.clone(),
+ input: self.input.slice(range),
+ }
+ }
+}
+
+impl<I, S, R> Slice<R> for Stateful<I, S>
+where
+ I: Slice<R>,
+ S: Clone,
+{
+ #[inline(always)]
+ fn slice(&self, range: R) -> Self {
+ Self {
+ input: self.input.slice(range),
+ state: self.state.clone(),
+ }
+ }
+}
+
+impl<I, R> Slice<R> for Streaming<I>
+where
+ I: Slice<R>,
+{
+ #[inline(always)]
+ fn slice(&self, range: R) -> Self {
+ Streaming(self.0.slice(range))
+ }
+}
+
+macro_rules! impl_fn_slice {
+ ( $ty:ty ) => {
+ fn slice(&self, range: $ty) -> Self {
+ &self[range]
+ }
+ };
+}
+
+macro_rules! slice_range_impl {
+ ( [ $for_type:ident ], $ty:ty ) => {
+ impl<'a, $for_type> Slice<$ty> for &'a [$for_type] {
+ impl_fn_slice!($ty);
+ }
+ };
+ ( $for_type:ty, $ty:ty ) => {
+ impl<'a> Slice<$ty> for &'a $for_type {
+ impl_fn_slice!($ty);
+ }
+ };
+}
+
+macro_rules! slice_ranges_impl {
+ ( [ $for_type:ident ] ) => {
+ slice_range_impl! {[$for_type], Range<usize>}
+ slice_range_impl! {[$for_type], RangeTo<usize>}
+ slice_range_impl! {[$for_type], RangeFrom<usize>}
+ slice_range_impl! {[$for_type], RangeFull}
+ };
+ ( $for_type:ty ) => {
+ slice_range_impl! {$for_type, Range<usize>}
+ slice_range_impl! {$for_type, RangeTo<usize>}
+ slice_range_impl! {$for_type, RangeFrom<usize>}
+ slice_range_impl! {$for_type, RangeFull}
+ };
+}
+
+slice_ranges_impl! {[T]}
+slice_ranges_impl! {str}
+
+/// Convert an `Input` into an appropriate `Output` type
+pub trait IntoOutput {
+ /// Output type
+ type Output;
+ /// Convert an `Input` into an appropriate `Output` type
+ fn into_output(self) -> Self::Output;
+ /// Convert an `Output` type to be used as `Input`
+ fn merge_output(self, inner: Self::Output) -> Self;
+}
+
+impl<I> IntoOutput for Located<I>
+where
+ I: IntoOutput,
+{
+ type Output = I::Output;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self.input.into_output()
+ }
+ #[inline]
+ fn merge_output(mut self, inner: Self::Output) -> Self {
+ self.input = I::merge_output(self.input, inner);
+ self
+ }
+}
+
+impl<I, S> IntoOutput for Stateful<I, S>
+where
+ I: IntoOutput,
+{
+ type Output = I::Output;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self.input.into_output()
+ }
+ #[inline]
+ fn merge_output(mut self, inner: Self::Output) -> Self {
+ self.input = I::merge_output(self.input, inner);
+ self
+ }
+}
+
+impl<I> IntoOutput for Streaming<I>
+where
+ I: IntoOutput,
+{
+ type Output = I::Output;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self.into_complete().into_output()
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ Streaming(I::merge_output(self.0, inner))
+ }
+}
+
+impl<'a, T> IntoOutput for &'a [T] {
+ type Output = Self;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ inner
+ }
+}
+
+impl<const LEN: usize> IntoOutput for [u8; LEN] {
+ type Output = Self;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ inner
+ }
+}
+
+impl<'a, const LEN: usize> IntoOutput for &'a [u8; LEN] {
+ type Output = Self;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ inner
+ }
+}
+
+impl<'a> IntoOutput for &'a str {
+ type Output = Self;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ inner
+ }
+}
+
+impl<'a> IntoOutput for (&'a [u8], usize) {
+ type Output = Self;
+ #[inline]
+ fn into_output(self) -> Self::Output {
+ self
+ }
+ #[inline]
+ fn merge_output(self, inner: Self::Output) -> Self {
+ inner
+ }
+}
+
+/// Abstracts something which can extend an `Extend`.
+/// Used to build modified input slices in `escaped_transform`
+pub trait ExtendInto {
+ /// The current input type is a sequence of that `Item` type.
+ ///
+ /// Example: `u8` for `&[u8]` or `char` for `&str`
+ type Item;
+
+ /// The type that will be produced
+ type Extender;
+
+ /// Create a new `Extend` of the correct type
+ fn new_builder(&self) -> Self::Extender;
+ /// Accumulate the input into an accumulator
+ fn extend_into(&self, acc: &mut Self::Extender);
+}
+
+impl<I> ExtendInto for Located<I>
+where
+ I: ExtendInto,
+{
+ type Item = I::Item;
+ type Extender = I::Extender;
+
+ fn new_builder(&self) -> Self::Extender {
+ self.input.new_builder()
+ }
+
+ fn extend_into(&self, extender: &mut Self::Extender) {
+ self.input.extend_into(extender)
+ }
+}
+
+impl<I, S> ExtendInto for Stateful<I, S>
+where
+ I: ExtendInto,
+{
+ type Item = I::Item;
+ type Extender = I::Extender;
+
+ fn new_builder(&self) -> Self::Extender {
+ self.input.new_builder()
+ }
+
+ fn extend_into(&self, extender: &mut Self::Extender) {
+ self.input.extend_into(extender)
+ }
+}
+
+impl<I> ExtendInto for Streaming<I>
+where
+ I: ExtendInto,
+{
+ type Item = I::Item;
+ type Extender = I::Extender;
+
+ #[inline(always)]
+ fn new_builder(&self) -> Self::Extender {
+ self.0.new_builder()
+ }
+ #[inline(always)]
+ fn extend_into(&self, acc: &mut Self::Extender) {
+ self.0.extend_into(acc)
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl ExtendInto for [u8] {
+ type Item = u8;
+ type Extender = Vec<u8>;
+
+ #[inline]
+ fn new_builder(&self) -> Vec<u8> {
+ Vec::new()
+ }
+ #[inline]
+ fn extend_into(&self, acc: &mut Vec<u8>) {
+ acc.extend(self.iter().cloned());
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl ExtendInto for &[u8] {
+ type Item = u8;
+ type Extender = Vec<u8>;
+
+ #[inline]
+ fn new_builder(&self) -> Vec<u8> {
+ Vec::new()
+ }
+ #[inline]
+ fn extend_into(&self, acc: &mut Vec<u8>) {
+ acc.extend_from_slice(self);
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl ExtendInto for str {
+ type Item = char;
+ type Extender = String;
+
+ #[inline]
+ fn new_builder(&self) -> String {
+ String::new()
+ }
+ #[inline]
+ fn extend_into(&self, acc: &mut String) {
+ acc.push_str(self);
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl ExtendInto for &str {
+ type Item = char;
+ type Extender = String;
+
+ #[inline]
+ fn new_builder(&self) -> String {
+ String::new()
+ }
+ #[inline]
+ fn extend_into(&self, acc: &mut String) {
+ acc.push_str(self);
+ }
+}
+
+/// Helper trait to convert numbers to usize.
+///
+/// By default, usize implements `From<u8>` and `From<u16>` but not
+/// `From<u32>` and `From<u64>` because that would be invalid on some
+/// platforms. This trait implements the conversion for platforms
+/// with 32 and 64 bits pointer platforms
+pub trait ToUsize {
+ /// converts self to usize
+ fn to_usize(&self) -> usize;
+}
+
+impl ToUsize for u8 {
+ #[inline]
+ fn to_usize(&self) -> usize {
+ *self as usize
+ }
+}
+
+impl ToUsize for u16 {
+ #[inline]
+ fn to_usize(&self) -> usize {
+ *self as usize
+ }
+}
+
+impl ToUsize for usize {
+ #[inline]
+ fn to_usize(&self) -> usize {
+ *self
+ }
+}
+
+#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
+impl ToUsize for u32 {
+ #[inline]
+ fn to_usize(&self) -> usize {
+ *self as usize
+ }
+}
+
+#[cfg(target_pointer_width = "64")]
+impl ToUsize for u64 {
+ #[inline]
+ fn to_usize(&self) -> usize {
+ *self as usize
+ }
+}
+
+/// Equivalent From implementation to avoid orphan rules in bits parsers
+pub trait ErrorConvert<E> {
+ /// Transform to another error type
+ fn convert(self) -> E;
+}
+
+impl<I> ErrorConvert<(I, ErrorKind)> for ((I, usize), ErrorKind) {
+ fn convert(self) -> (I, ErrorKind) {
+ ((self.0).0, self.1)
+ }
+}
+
+impl<I> ErrorConvert<((I, usize), ErrorKind)> for (I, ErrorKind) {
+ fn convert(self) -> ((I, usize), ErrorKind) {
+ ((self.0, 0), self.1)
+ }
+}
+
+use crate::error;
+impl<I> ErrorConvert<error::Error<I>> for error::Error<(I, usize)> {
+ fn convert(self) -> error::Error<I> {
+ error::Error {
+ input: self.input.0,
+ code: self.code,
+ }
+ }
+}
+
+impl<I> ErrorConvert<error::Error<(I, usize)>> for error::Error<I> {
+ fn convert(self) -> error::Error<(I, usize)> {
+ error::Error {
+ input: (self.input, 0),
+ code: self.code,
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I> ErrorConvert<error::VerboseError<I>> for error::VerboseError<(I, usize)> {
+ fn convert(self) -> error::VerboseError<I> {
+ error::VerboseError {
+ errors: self.errors.into_iter().map(|(i, e)| (i.0, e)).collect(),
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+impl<I> ErrorConvert<error::VerboseError<(I, usize)>> for error::VerboseError<I> {
+ fn convert(self) -> error::VerboseError<(I, usize)> {
+ error::VerboseError {
+ errors: self.errors.into_iter().map(|(i, e)| ((i, 0), e)).collect(),
+ }
+ }
+}
+
+/// Helper trait to show a byte slice as a hex dump
+#[cfg(feature = "std")]
+pub trait HexDisplay {
+ /// Converts the value of `self` to a hex dump, returning the owned
+ /// `String`.
+ fn to_hex(&self, chunk_size: usize) -> String;
+
+ /// Converts the value of `self` to a hex dump beginning at `from` address, returning the owned
+ /// `String`.
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String;
+}
+
+#[cfg(feature = "std")]
+static CHARS: &[u8] = b"0123456789abcdef";
+
+#[cfg(feature = "std")]
+impl<I> HexDisplay for Located<I>
+where
+ I: HexDisplay,
+{
+ #[inline(always)]
+ fn to_hex(&self, chunk_size: usize) -> String {
+ self.input.to_hex(chunk_size)
+ }
+
+ #[inline(always)]
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
+ self.input.to_hex_from(chunk_size, from)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I, S> HexDisplay for Stateful<I, S>
+where
+ I: HexDisplay,
+{
+ #[inline(always)]
+ fn to_hex(&self, chunk_size: usize) -> String {
+ self.input.to_hex(chunk_size)
+ }
+
+ #[inline(always)]
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
+ self.input.to_hex_from(chunk_size, from)
+ }
+}
+
+#[cfg(feature = "std")]
+impl<I> HexDisplay for Streaming<I>
+where
+ I: HexDisplay,
+{
+ #[inline(always)]
+ fn to_hex(&self, chunk_size: usize) -> String {
+ self.0.to_hex(chunk_size)
+ }
+
+ #[inline(always)]
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
+ self.0.to_hex_from(chunk_size, from)
+ }
+}
+
+#[cfg(feature = "std")]
+impl HexDisplay for [u8] {
+ #[allow(unused_variables)]
+ fn to_hex(&self, chunk_size: usize) -> String {
+ self.to_hex_from(chunk_size, 0)
+ }
+
+ #[allow(unused_variables)]
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
+ let mut v = Vec::with_capacity(self.len() * 3);
+ let mut i = from;
+ for chunk in self.chunks(chunk_size) {
+ let s = format!("{:08x}", i);
+ for &ch in s.as_bytes().iter() {
+ v.push(ch);
+ }
+ v.push(b'\t');
+
+ i += chunk_size;
+
+ for &byte in chunk {
+ v.push(CHARS[(byte >> 4) as usize]);
+ v.push(CHARS[(byte & 0xf) as usize]);
+ v.push(b' ');
+ }
+ if chunk_size > chunk.len() {
+ for j in 0..(chunk_size - chunk.len()) {
+ v.push(b' ');
+ v.push(b' ');
+ v.push(b' ');
+ }
+ }
+ v.push(b'\t');
+
+ for &byte in chunk {
+ if (byte >= 32 && byte <= 126) || byte >= 128 {
+ v.push(byte);
+ } else {
+ v.push(b'.');
+ }
+ }
+ v.push(b'\n');
+ }
+
+ String::from_utf8_lossy(&v[..]).into_owned()
+ }
+}
+
+#[cfg(feature = "std")]
+impl HexDisplay for str {
+ #[allow(unused_variables)]
+ fn to_hex(&self, chunk_size: usize) -> String {
+ self.to_hex_from(chunk_size, 0)
+ }
+
+ #[allow(unused_variables)]
+ fn to_hex_from(&self, chunk_size: usize, from: usize) -> String {
+ self.as_bytes().to_hex_from(chunk_size, from)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_offset_u8() {
+ let s = b"abcd123";
+ let a = &s[..];
+ let b = &a[2..];
+ let c = &a[..4];
+ let d = &a[3..5];
+ assert_eq!(a.offset(b), 2);
+ assert_eq!(a.offset(c), 0);
+ assert_eq!(a.offset(d), 3);
+ }
+
+ #[test]
+ fn test_offset_str() {
+ let s = "abcřèÂßÇd123";
+ let a = &s[..];
+ let b = &a[7..];
+ let c = &a[..5];
+ let d = &a[5..9];
+ assert_eq!(a.offset(b), 7);
+ assert_eq!(a.offset(c), 0);
+ assert_eq!(a.offset(d), 5);
+ }
+}
diff --git a/vendor/nom8/src/lib.rs b/vendor/nom8/src/lib.rs
new file mode 100644
index 000000000..b6c87cfe6
--- /dev/null
+++ b/vendor/nom8/src/lib.rs
@@ -0,0 +1,430 @@
+//! # nom, eating data byte by byte
+//!
+//! **NOTE:** This is an unofficial, short-lived fork. I'm nominating nom8 to be nom v8.
+//!
+//! nom is a parser combinator library, supporting:
+//! - String (`&str`), byte (`&[u8]`), and [custom input types][crate::input]
+//! - [Streaming parsing][crate::input::Streaming]
+//! - Zero copy parsing
+//!
+//! ## Example
+//!
+//! ```rust
+//! use nom8::prelude::*;
+//! use nom8::bytes::{tag, take_while_m_n};
+//!
+//! #[derive(Debug,PartialEq)]
+//! pub struct Color {
+//! pub red: u8,
+//! pub green: u8,
+//! pub blue: u8,
+//! }
+//!
+//! fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
+//! u8::from_str_radix(input, 16)
+//! }
+//!
+//! fn is_hex_digit(c: char) -> bool {
+//! c.is_digit(16)
+//! }
+//!
+//! fn hex_primary(input: &str) -> IResult<&str, u8> {
+//! take_while_m_n(2, 2, is_hex_digit).map_res(from_hex).parse(input)
+//! }
+//!
+//! fn hex_color(input: &str) -> IResult<&str, Color> {
+//! let (input, _) = tag("#")(input)?;
+//! let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?;
+//!
+//! Ok((input, Color { red, green, blue }))
+//! }
+//!
+//! fn main() {
+//! let result = hex_color("#2F14DF").finish();
+//! assert_eq!(result, Ok(Color {
+//! red: 47,
+//! green: 20,
+//! blue: 223,
+//! }));
+//! }
+//! ```
+//!
+//! The code is available on [Github](https://github.com/Geal/nom)
+//!
+//! There are a few [guides](https://github.com/Geal/nom/tree/main/doc) with more details
+//! about [how to write parsers][_tutorial],
+//! or the [error management system][error].
+//! You can also check out the [_cookbook] module that contains examples of common patterns.
+//!
+//! **Looking for a specific combinator? Read the
+//! ["choose a combinator" guide][combinator]**
+//!
+//! If you are upgrading to nom 5.0, please read the
+//! [migration document](https://github.com/Geal/nom/blob/main/doc/upgrading_to_nom_5.md).
+//!
+//! ## Parser combinators
+//!
+//! Parser combinators are an approach to parsers that is very different from
+//! software like [lex](https://en.wikipedia.org/wiki/Lex_(software)) and
+//! [yacc](https://en.wikipedia.org/wiki/Yacc). Instead of writing the grammar
+//! in a separate syntax and generating the corresponding code, you use very small
+//! functions with very specific purposes, like "take 5 bytes", or "recognize the
+//! word 'HTTP'", and assemble them in meaningful patterns like "recognize
+//! 'HTTP', then a space, then a version".
+//! The resulting code is small, and looks like the grammar you would have
+//! written with other parser approaches.
+//!
+//! This gives us a few advantages:
+//!
+//! - The parsers are small and easy to write
+//! - The parsers components are easy to reuse (if they're general enough, please add them to nom!)
+//! - The parsers components are easy to test separately (unit tests and property-based tests)
+//! - The parser combination code looks close to the grammar you would have written
+//! - You can build partial parsers, specific to the data you need at the moment, and ignore the rest
+//!
+//! Here is an example of one such parser, to recognize text between parentheses:
+//!
+//! ```rust
+//! use nom8::{
+//! IResult,
+//! sequence::delimited,
+//! bytes::take_till1
+//! };
+//!
+//! fn parens(input: &str) -> IResult<&str, &str> {
+//! delimited('(', take_till1(")"), ')')(input)
+//! }
+//! ```
+//!
+//! It defines a function named `parens` which will recognize a sequence of the
+//! character `(`, the longest byte array not containing `)`, then the character
+//! `)`, and will return the byte array in the middle.
+//!
+//! Here is another parser, written without using nom's combinators this time:
+//!
+//! ```rust
+//! use nom8::{IResult, Err, Needed};
+//!
+//! # fn main() {
+//! fn take4(i: &[u8]) -> IResult<&[u8], &[u8]>{
+//! if i.len() < 4 {
+//! Err(Err::Incomplete(Needed::new(4)))
+//! } else {
+//! Ok((&i[4..], &i[0..4]))
+//! }
+//! }
+//! # }
+//! ```
+//!
+//! This function takes a byte array as input, and tries to consume 4 bytes.
+//! Writing all the parsers manually, like this, is dangerous, despite Rust's
+//! safety features. There are still a lot of mistakes one can make. That's why
+//! nom provides a list of functions to help in developing parsers.
+//!
+//! With functions, you would write it like this:
+//!
+//! ```rust
+//! use nom8::{IResult, bytes::take, input::Streaming};
+//! fn take4(input: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+//! take(4u8)(input)
+//! }
+//! ```
+//!
+//! A parser in nom is a function which, for an input type `I`, an output type `O`
+//! and an optional error type `E`, will have the following signature:
+//!
+//! ```rust,compile_fail
+//! fn parser(input: I) -> IResult<I, O, E>;
+//! ```
+//!
+//! Or like this, if you don't want to specify a custom error type (it will be `(I, ErrorKind)` by default):
+//!
+//! ```rust,compile_fail
+//! fn parser(input: I) -> IResult<I, O>;
+//! ```
+//!
+//! `IResult` is an alias for the `Result` type:
+//!
+//! ```rust
+//! use nom8::{Needed, error::Error};
+//!
+//! type IResult<I, O, E = Error<I>> = Result<(I, O), Err<E>>;
+//!
+//! enum Err<E> {
+//! Incomplete(Needed),
+//! Error(E),
+//! Failure(E),
+//! }
+//! ```
+//!
+//! It can have the following values:
+//!
+//! - A correct result `Ok((I,O))` with the first element being the remaining of the input (not parsed yet), and the second the output value;
+//! - An error `Err(Err::Error(c))` with `c` an error that can be built from the input position and a parser specific error
+//! - An error `Err(Err::Incomplete(Needed))` indicating that more input is necessary. `Needed` can indicate how much data is needed
+//! - An error `Err(Err::Failure(c))`. It works like the `Error` case, except it indicates an unrecoverable error: We cannot backtrack and test another parser
+//!
+//! Please refer to the ["choose a combinator" guide][combinator] for an exhaustive list of parsers.
+//! See also the rest of the documentation [here](https://github.com/Geal/nom/blob/main/doc).
+//!
+//! ## Making new parsers with function combinators
+//!
+//! nom is based on functions that generate parsers, with a signature like
+//! this: `(arguments) -> impl Fn(Input) -> IResult<Input, Output, Error>`.
+//! The arguments of a combinator can be direct values (like `take` which uses
+//! a number of bytes or character as argument) or even other parsers (like
+//! `delimited` which takes as argument 3 parsers, and returns the result of
+//! the second one if all are successful).
+//!
+//! Here are some examples:
+//!
+//! ```rust
+//! use nom8::IResult;
+//! use nom8::bytes::{tag, take};
+//! fn abcd_parser(i: &str) -> IResult<&str, &str> {
+//! tag("abcd")(i) // will consume bytes if the input begins with "abcd"
+//! }
+//!
+//! fn take_10(i: &[u8]) -> IResult<&[u8], &[u8]> {
+//! take(10u8)(i) // will consume and return 10 bytes of input
+//! }
+//! ```
+//!
+//! ## Combining parsers
+//!
+//! There are higher level patterns, like the **`alt`** combinator, which
+//! provides a choice between multiple parsers. If one branch fails, it tries
+//! the next, and returns the result of the first parser that succeeds:
+//!
+//! ```rust
+//! use nom8::IResult;
+//! use nom8::branch::alt;
+//! use nom8::bytes::tag;
+//!
+//! let mut alt_tags = alt((tag("abcd"), tag("efgh")));
+//!
+//! assert_eq!(alt_tags(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..])));
+//! assert_eq!(alt_tags(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..])));
+//! assert_eq!(alt_tags(&b"ijklxxx"[..]), Err(nom8::Err::Error((&b"ijklxxx"[..], nom8::error::ErrorKind::Tag))));
+//! ```
+//!
+//! The **`opt`** combinator makes a parser optional. If the child parser returns
+//! an error, **`opt`** will still succeed and return None:
+//!
+//! ```rust
+//! use nom8::{IResult, combinator::opt, bytes::tag};
+//! fn abcd_opt(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> {
+//! opt(tag("abcd"))(i)
+//! }
+//!
+//! assert_eq!(abcd_opt(&b"abcdxxx"[..]), Ok((&b"xxx"[..], Some(&b"abcd"[..]))));
+//! assert_eq!(abcd_opt(&b"efghxxx"[..]), Ok((&b"efghxxx"[..], None)));
+//! ```
+//!
+//! **`many0`** applies a parser 0 or more times, and returns a vector of the aggregated results:
+//!
+//! ```rust
+//! # #[cfg(feature = "alloc")]
+//! # fn main() {
+//! use nom8::{IResult, multi::many0, bytes::tag};
+//! use std::str;
+//!
+//! fn multi(i: &str) -> IResult<&str, Vec<&str>> {
+//! many0(tag("abcd"))(i)
+//! }
+//!
+//! let a = "abcdef";
+//! let b = "abcdabcdef";
+//! let c = "azerty";
+//! assert_eq!(multi(a), Ok(("ef", vec!["abcd"])));
+//! assert_eq!(multi(b), Ok(("ef", vec!["abcd", "abcd"])));
+//! assert_eq!(multi(c), Ok(("azerty", Vec::new())));
+//! # }
+//! # #[cfg(not(feature = "alloc"))]
+//! # fn main() {}
+//! ```
+//!
+//! Here are some basic combinators available:
+//!
+//! - **`opt`**: Will make the parser optional (if it returns the `O` type, the new parser returns `Option<O>`)
+//! - **`many0`**: Will apply the parser 0 or more times (if it returns the `O` type, the new parser returns `Vec<O>`)
+//! - **`many1`**: Will apply the parser 1 or more times
+//!
+//! There are more complex (and more useful) parsers like tuples, which is
+//! used to apply a series of parsers then assemble their results.
+//!
+//! Example with tuples:
+//!
+//! ```rust
+//! # fn main() {
+//! use nom8::prelude::*;
+//! use nom8::{
+//! error::ErrorKind, Needed,
+//! number::be_u16,
+//! bytes::{tag, take},
+//! input::Streaming,
+//! };
+//!
+//! let mut tpl = (be_u16, take(3u8), tag("fg"));
+//!
+//! assert_eq!(
+//! tpl.parse(Streaming(&b"abcdefgh"[..])),
+//! Ok((
+//! Streaming(&b"h"[..]),
+//! (0x6162u16, &b"cde"[..], &b"fg"[..])
+//! ))
+//! );
+//! assert_eq!(tpl.parse(Streaming(&b"abcde"[..])), Err(nom8::Err::Incomplete(Needed::new(2))));
+//! let input = &b"abcdejk"[..];
+//! assert_eq!(tpl.parse(Streaming(input)), Err(nom8::Err::Error((Streaming(&input[5..]), ErrorKind::Tag))));
+//! # }
+//! ```
+//!
+//! But you can also use a sequence of combinators written in imperative style,
+//! thanks to the `?` operator:
+//!
+//! ```rust
+//! # fn main() {
+//! use nom8::{IResult, bytes::tag};
+//!
+//! #[derive(Debug, PartialEq)]
+//! struct A {
+//! a: u8,
+//! b: u8
+//! }
+//!
+//! fn ret_int1(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,1)) }
+//! fn ret_int2(i:&[u8]) -> IResult<&[u8], u8> { Ok((i,2)) }
+//!
+//! fn f(i: &[u8]) -> IResult<&[u8], A> {
+//! // if successful, the parser returns `Ok((remaining_input, output_value))` that we can destructure
+//! let (i, _) = tag("abcd")(i)?;
+//! let (i, a) = ret_int1(i)?;
+//! let (i, _) = tag("efgh")(i)?;
+//! let (i, b) = ret_int2(i)?;
+//!
+//! Ok((i, A { a, b }))
+//! }
+//!
+//! let r = f(b"abcdefghX");
+//! assert_eq!(r, Ok((&b"X"[..], A{a: 1, b: 2})));
+//! # }
+//! ```
+#![cfg_attr(docsrs, feature(doc_auto_cfg))]
+#![cfg_attr(docsrs, feature(doc_cfg))]
+#![cfg_attr(docsrs, feature(extended_key_value_attributes))]
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(feature = "cargo-clippy", allow(clippy::doc_markdown))]
+#![deny(missing_docs)]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+#[cfg(feature = "alloc")]
+#[macro_use]
+extern crate alloc;
+#[cfg(doctest)]
+extern crate doc_comment;
+
+#[cfg(doctest)]
+doc_comment::doctest!("../README.md");
+
+/// Lib module to re-export everything needed from `std` or `core`/`alloc`. This is how `serde` does
+/// it, albeit there it is not public.
+#[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
+pub mod lib {
+ /// `std` facade allowing `std`/`core` to be interchangeable. Reexports `alloc` crate optionally,
+ /// as well as `core` or `std`
+ #[cfg(not(feature = "std"))]
+ #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
+ /// internal std exports for no_std compatibility
+ pub mod std {
+ #[doc(hidden)]
+ #[cfg(not(feature = "alloc"))]
+ pub use core::borrow;
+
+ #[cfg(feature = "alloc")]
+ #[doc(hidden)]
+ pub use alloc::{borrow, boxed, string, vec};
+
+ #[doc(hidden)]
+ pub use core::{cmp, convert, fmt, iter, mem, ops, option, result, slice, str};
+
+ /// internal reproduction of std prelude
+ #[doc(hidden)]
+ pub mod prelude {
+ pub use core::prelude as v1;
+ }
+ }
+
+ #[cfg(feature = "std")]
+ #[cfg_attr(nightly, allow(rustdoc::missing_doc_code_examples))]
+ /// internal std exports for no_std compatibility
+ pub mod std {
+ #[doc(hidden)]
+ pub use std::{
+ alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option, result,
+ slice, str, string, vec,
+ };
+
+ /// internal reproduction of std prelude
+ #[doc(hidden)]
+ pub mod prelude {
+ pub use std::prelude as v1;
+ }
+ }
+}
+
+pub use self::parser::*;
+
+#[macro_use]
+mod macros;
+#[macro_use]
+pub mod error;
+
+pub mod branch;
+pub mod combinator;
+pub mod input;
+pub mod multi;
+mod parser;
+pub mod sequence;
+
+pub mod bits;
+pub mod bytes;
+
+pub mod character;
+
+mod str;
+
+pub mod number;
+
+#[cfg(feature = "unstable-doc")]
+pub mod _cookbook;
+#[cfg(feature = "unstable-doc")]
+pub mod _tutorial;
+
+/// Core concepts available for glob import
+///
+/// Including
+/// - [`FinishIResult`]
+/// - [`Parser`]
+///
+/// ## Example
+///
+/// ```rust
+/// use nom8::prelude::*;
+///
+/// fn parse_data(input: &str) -> IResult<&str, u64> {
+/// // ...
+/// # nom8::character::u64(input)
+/// }
+///
+/// fn main() {
+/// let result = parse_data.parse("100").finish();
+/// assert_eq!(result, Ok(100));
+/// }
+/// ```
+pub mod prelude {
+ pub use crate::input::InputIsStreaming as _;
+ pub use crate::FinishIResult as _;
+ pub use crate::IResult;
+ pub use crate::IntoOutputIResult as _;
+ pub use crate::Parser as _;
+}
diff --git a/vendor/nom8/src/macros.rs b/vendor/nom8/src/macros.rs
new file mode 100644
index 000000000..980d2d90e
--- /dev/null
+++ b/vendor/nom8/src/macros.rs
@@ -0,0 +1,23 @@
+macro_rules! succ (
+ (0, $submac:ident ! ($($rest:tt)*)) => ($submac!(1, $($rest)*));
+ (1, $submac:ident ! ($($rest:tt)*)) => ($submac!(2, $($rest)*));
+ (2, $submac:ident ! ($($rest:tt)*)) => ($submac!(3, $($rest)*));
+ (3, $submac:ident ! ($($rest:tt)*)) => ($submac!(4, $($rest)*));
+ (4, $submac:ident ! ($($rest:tt)*)) => ($submac!(5, $($rest)*));
+ (5, $submac:ident ! ($($rest:tt)*)) => ($submac!(6, $($rest)*));
+ (6, $submac:ident ! ($($rest:tt)*)) => ($submac!(7, $($rest)*));
+ (7, $submac:ident ! ($($rest:tt)*)) => ($submac!(8, $($rest)*));
+ (8, $submac:ident ! ($($rest:tt)*)) => ($submac!(9, $($rest)*));
+ (9, $submac:ident ! ($($rest:tt)*)) => ($submac!(10, $($rest)*));
+ (10, $submac:ident ! ($($rest:tt)*)) => ($submac!(11, $($rest)*));
+ (11, $submac:ident ! ($($rest:tt)*)) => ($submac!(12, $($rest)*));
+ (12, $submac:ident ! ($($rest:tt)*)) => ($submac!(13, $($rest)*));
+ (13, $submac:ident ! ($($rest:tt)*)) => ($submac!(14, $($rest)*));
+ (14, $submac:ident ! ($($rest:tt)*)) => ($submac!(15, $($rest)*));
+ (15, $submac:ident ! ($($rest:tt)*)) => ($submac!(16, $($rest)*));
+ (16, $submac:ident ! ($($rest:tt)*)) => ($submac!(17, $($rest)*));
+ (17, $submac:ident ! ($($rest:tt)*)) => ($submac!(18, $($rest)*));
+ (18, $submac:ident ! ($($rest:tt)*)) => ($submac!(19, $($rest)*));
+ (19, $submac:ident ! ($($rest:tt)*)) => ($submac!(20, $($rest)*));
+ (20, $submac:ident ! ($($rest:tt)*)) => ($submac!(21, $($rest)*));
+);
diff --git a/vendor/nom8/src/multi/mod.rs b/vendor/nom8/src/multi/mod.rs
new file mode 100644
index 000000000..8d654d55d
--- /dev/null
+++ b/vendor/nom8/src/multi/mod.rs
@@ -0,0 +1,1029 @@
+//! Combinators applying their child parser multiple times
+
+#[cfg(test)]
+mod tests;
+
+use crate::error::ErrorKind;
+use crate::error::ParseError;
+use crate::input::{InputIsStreaming, InputIter, InputLength, InputTake, IntoOutput, ToUsize};
+#[cfg(feature = "alloc")]
+use crate::lib::std::vec::Vec;
+use crate::{Err, IResult, Parser};
+
+/// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`.
+///
+/// Pre-allocating memory is a nice optimization but count fields can't
+/// always be trusted. We should clamp initial capacities to some reasonable
+/// amount. This reduces the risk of a bogus count value triggering a panic
+/// due to an OOM error.
+///
+/// This does not affect correctness. Nom will always read the full number
+/// of elements regardless of the capacity cap.
+const MAX_INITIAL_CAPACITY: usize = 65536;
+
+/// Repeats the embedded parser, gathering the results in a `Vec`.
+///
+/// This stops on [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+///
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::many0;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// many0(tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Ok(("123123", vec![])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn many0<I, O, E, F>(mut f: F) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |mut i: I| {
+ let mut acc = crate::lib::std::vec::Vec::with_capacity(4);
+ loop {
+ let len = i.input_len();
+ match f.parse(i.clone()) {
+ Err(Err::Error(_)) => return Ok((i, acc)),
+ Err(e) => return Err(e),
+ Ok((i1, o)) => {
+ // infinite loop check: the parser must always consume
+ if i1.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many0)));
+ }
+
+ i = i1;
+ acc.push(o);
+ }
+ }
+ }
+ }
+}
+
+/// Runs the embedded parser, gathering the results in a `Vec`.
+///
+/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::many1;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// many1(tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn many1<I, O, E, F>(mut f: F) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |mut i: I| match f.parse(i.clone()) {
+ Err(Err::Error(err)) => Err(Err::Error(E::append(i, ErrorKind::Many1, err))),
+ Err(e) => Err(e),
+ Ok((i1, o)) => {
+ let mut acc = crate::lib::std::vec::Vec::with_capacity(4);
+ acc.push(o);
+ i = i1;
+
+ loop {
+ let len = i.input_len();
+ match f.parse(i.clone()) {
+ Err(Err::Error(_)) => return Ok((i, acc)),
+ Err(e) => return Err(e),
+ Ok((i1, o)) => {
+ // infinite loop check: the parser must always consume
+ if i1.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1)));
+ }
+
+ i = i1;
+ acc.push(o);
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Applies the parser `f` until the parser `g` produces a result.
+///
+/// Returns a tuple of the results of `f` in a `Vec` and the result of `g`.
+///
+/// `f` keeps going so long as `g` produces [`Err::Error`]. To instead chain an error up, see [`cut`][crate::combinator::cut].
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::many_till;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, (Vec<&str>, &str)> {
+/// many_till(tag("abc"), tag("end"))(s)
+/// };
+///
+/// assert_eq!(parser("abcabcend"), Ok(("", (vec!["abc", "abc"], "end"))));
+/// assert_eq!(parser("abc123end"), Err(Err::Error(Error::new("123end", ErrorKind::Tag))));
+/// assert_eq!(parser("123123end"), Err(Err::Error(Error::new("123123end", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("abcendefg"), Ok(("efg", (vec!["abc"], "end"))));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn many_till<I, O, P, E, F, G>(
+ mut f: F,
+ mut g: G,
+) -> impl FnMut(I) -> IResult<I, (Vec<O>, P), E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: Parser<I, P, E>,
+ E: ParseError<I>,
+{
+ move |mut i: I| {
+ let mut res = crate::lib::std::vec::Vec::new();
+ loop {
+ let len = i.input_len();
+ match g.parse(i.clone()) {
+ Ok((i1, o)) => return Ok((i1, (res, o))),
+ Err(Err::Error(_)) => {
+ match f.parse(i.clone()) {
+ Err(Err::Error(err)) => return Err(Err::Error(E::append(i, ErrorKind::ManyTill, err))),
+ Err(e) => return Err(e),
+ Ok((i1, o)) => {
+ // infinite loop check: the parser must always consume
+ if i1.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i1, ErrorKind::ManyTill)));
+ }
+
+ res.push(o);
+ i = i1;
+ }
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+ }
+}
+
+/// Alternates between two parsers to produce a list of elements.
+///
+/// This stops when either parser returns [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `sep` Parses the separator between list elements.
+/// * `f` Parses the elements of the list.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::separated_list0;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated_list0(tag("|"), tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
+/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![])));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn separated_list0<I, O, O2, E, F, G>(
+ mut sep: G,
+ mut f: F,
+) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: Parser<I, O2, E>,
+ E: ParseError<I>,
+{
+ move |mut i: I| {
+ let mut res = Vec::new();
+
+ match f.parse(i.clone()) {
+ Err(Err::Error(_)) => return Ok((i, res)),
+ Err(e) => return Err(e),
+ Ok((i1, o)) => {
+ res.push(o);
+ i = i1;
+ }
+ }
+
+ loop {
+ let len = i.input_len();
+ match sep.parse(i.clone()) {
+ Err(Err::Error(_)) => return Ok((i, res)),
+ Err(e) => return Err(e),
+ Ok((i1, _)) => {
+ // infinite loop check: the parser must always consume
+ if i1.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList)));
+ }
+
+ match f.parse(i1.clone()) {
+ Err(Err::Error(_)) => return Ok((i, res)),
+ Err(e) => return Err(e),
+ Ok((i2, o)) => {
+ res.push(o);
+ i = i2;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Alternates between two parsers to produce a list of elements until [`Err::Error`].
+///
+/// Fails if the element parser does not produce at least one element.$
+///
+/// This stops when either parser returns [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `sep` Parses the separator between list elements.
+/// * `f` Parses the elements of the list.
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::separated_list1;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated_list1(tag("|"), tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
+/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("def|abc"), Err(Err::Error(Error::new("def|abc", ErrorKind::Tag))));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn separated_list1<I, O, O2, E, F, G>(
+ mut sep: G,
+ mut f: F,
+) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: Parser<I, O2, E>,
+ E: ParseError<I>,
+{
+ move |mut i: I| {
+ let mut res = Vec::new();
+
+ // Parse the first element
+ match f.parse(i.clone()) {
+ Err(e) => return Err(e),
+ Ok((i1, o)) => {
+ res.push(o);
+ i = i1;
+ }
+ }
+
+ loop {
+ let len = i.input_len();
+ match sep.parse(i.clone()) {
+ Err(Err::Error(_)) => return Ok((i, res)),
+ Err(e) => return Err(e),
+ Ok((i1, _)) => {
+ // infinite loop check: the parser must always consume
+ if i1.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i1, ErrorKind::SeparatedList)));
+ }
+
+ match f.parse(i1.clone()) {
+ Err(Err::Error(_)) => return Ok((i, res)),
+ Err(e) => return Err(e),
+ Ok((i2, o)) => {
+ res.push(o);
+ i = i2;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Repeats the embedded parser `m..=n` times
+///
+/// This stops before `n` when the parser returns [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `m` The minimum number of iterations.
+/// * `n` The maximum number of iterations.
+/// * `f` The parser to apply.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::many_m_n;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// many_m_n(0, 2, tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Ok(("123123", vec![])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn many_m_n<I, O, E, F>(
+ min: usize,
+ max: usize,
+ mut parse: F,
+) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |mut input: I| {
+ if min > max {
+ return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN)));
+ }
+
+ let mut res = crate::lib::std::vec::Vec::with_capacity(min.clamp(0, MAX_INITIAL_CAPACITY));
+ for count in 0..max {
+ let len = input.input_len();
+ match parse.parse(input.clone()) {
+ Ok((tail, value)) => {
+ // infinite loop check: the parser must always consume
+ if tail.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::ManyMN)));
+ }
+
+ res.push(value);
+ input = tail;
+ }
+ Err(Err::Error(e)) => {
+ if count < min {
+ return Err(Err::Error(E::append(input, ErrorKind::ManyMN, e)));
+ } else {
+ return Ok((input, res));
+ }
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok((input, res))
+ }
+}
+
+/// Repeats the embedded parser, counting the results
+///
+/// This stops on [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+///
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::many0_count;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, usize> {
+/// many0_count(tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", 2)));
+/// assert_eq!(parser("abc123"), Ok(("123", 1)));
+/// assert_eq!(parser("123123"), Ok(("123123", 0)));
+/// assert_eq!(parser(""), Ok(("", 0)));
+/// ```
+pub fn many0_count<I, O, E, F>(mut f: F) -> impl FnMut(I) -> IResult<I, usize, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let mut input = i;
+ let mut count = 0;
+
+ loop {
+ let input_ = input.clone();
+ let len = input.input_len();
+ match f.parse(input_) {
+ Ok((i, _)) => {
+ // infinite loop check: the parser must always consume
+ if i.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0Count)));
+ }
+
+ input = i;
+ count += 1;
+ }
+
+ Err(Err::Error(_)) => return Ok((input, count)),
+
+ Err(e) => return Err(e),
+ }
+ }
+ }
+}
+
+/// Runs the embedded parser, counting the results.
+///
+/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::many1_count;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, usize> {
+/// many1_count(tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", 2)));
+/// assert_eq!(parser("abc123"), Ok(("123", 1)));
+/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1Count))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1Count))));
+/// ```
+pub fn many1_count<I, O, E, F>(mut f: F) -> impl FnMut(I) -> IResult<I, usize, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let i_ = i.clone();
+ match f.parse(i_) {
+ Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count))),
+ Err(i) => Err(i),
+ Ok((i1, _)) => {
+ let mut count = 1;
+ let mut input = i1;
+
+ loop {
+ let len = input.input_len();
+ let input_ = input.clone();
+ match f.parse(input_) {
+ Err(Err::Error(_)) => return Ok((input, count)),
+ Err(e) => return Err(e),
+ Ok((i, _)) => {
+ // infinite loop check: the parser must always consume
+ if i.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1Count)));
+ }
+
+ count += 1;
+ input = i;
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/// Runs the embedded parser `count` times, gathering the results in a `Vec`
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// * `count` How often to apply the parser.
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::count;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// count(tag("abc"), 2)(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Err(Err::Error(Error::new("123", ErrorKind::Tag))));
+/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn count<I, O, E, F>(mut f: F, count: usize) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone + PartialEq,
+ F: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let mut input = i.clone();
+ let mut res = crate::lib::std::vec::Vec::with_capacity(count.clamp(0, MAX_INITIAL_CAPACITY));
+
+ for _ in 0..count {
+ let input_ = input.clone();
+ match f.parse(input_) {
+ Ok((i, o)) => {
+ res.push(o);
+ input = i;
+ }
+ Err(Err::Error(e)) => {
+ return Err(Err::Error(E::append(i, ErrorKind::Count, e)));
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok((input, res))
+ }
+}
+
+/// Runs the embedded parser repeatedly, filling the given slice with results.
+///
+/// This parser fails if the input runs out before the given slice is full.
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// * `buf` The slice to fill
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::fill;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, [&str; 2]> {
+/// let mut buf = ["", ""];
+/// let (rest, ()) = fill(tag("abc"), &mut buf)(s)?;
+/// Ok((rest, buf))
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", ["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Err(Err::Error(Error::new("123", ErrorKind::Tag))));
+/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("abcabcabc"), Ok(("abc", ["abc", "abc"])));
+/// ```
+pub fn fill<'a, I, O, E, F>(mut f: F, buf: &'a mut [O]) -> impl FnMut(I) -> IResult<I, (), E> + 'a
+where
+ I: Clone + PartialEq,
+ F: Parser<I, O, E> + 'a,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let mut input = i.clone();
+
+ for elem in buf.iter_mut() {
+ let input_ = input.clone();
+ match f.parse(input_) {
+ Ok((i, o)) => {
+ *elem = o;
+ input = i;
+ }
+ Err(Err::Error(e)) => {
+ return Err(Err::Error(E::append(i, ErrorKind::Count, e)));
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok((input, ()))
+ }
+}
+
+/// Repeats the embedded parser, calling `g` to gather the results.
+///
+/// This stops on [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// * `init` A function returning the initial value.
+/// * `g` The function that combines a result of `f` with
+/// the current accumulator.
+///
+/// *Note*: if the parser passed in accepts empty inputs (like `alpha0` or `digit0`), `many0` will
+/// return an error, to prevent going into an infinite loop
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::fold_many0;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// fold_many0(
+/// tag("abc"),
+/// Vec::new,
+/// |mut acc: Vec<_>, item| {
+/// acc.push(item);
+/// acc
+/// }
+/// )(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Ok(("123123", vec![])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// ```
+pub fn fold_many0<I, O, E, F, G, H, R>(
+ mut f: F,
+ mut init: H,
+ mut g: G,
+) -> impl FnMut(I) -> IResult<I, R, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: FnMut(R, O) -> R,
+ H: FnMut() -> R,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let mut res = init();
+ let mut input = i;
+
+ loop {
+ let i_ = input.clone();
+ let len = input.input_len();
+ match f.parse(i_) {
+ Ok((i, o)) => {
+ // infinite loop check: the parser must always consume
+ if i.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Many0)));
+ }
+
+ res = g(res, o);
+ input = i;
+ }
+ Err(Err::Error(_)) => {
+ return Ok((input, res));
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+ }
+}
+
+/// Repeats the embedded parser, calling `g` to gather the results.
+///
+/// This stops on [`Err::Error`] if there is at least one result. To instead chain an error up,
+/// see [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// * `init` A function returning the initial value.
+/// * `g` The function that combines a result of `f` with
+/// the current accumulator.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::multi::fold_many1;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// fold_many1(
+/// tag("abc"),
+/// Vec::new,
+/// |mut acc: Vec<_>, item| {
+/// acc.push(item);
+/// acc
+/// }
+/// )(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Err(Err::Error(Error::new("123123", ErrorKind::Many1))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Many1))));
+/// ```
+pub fn fold_many1<I, O, E, F, G, H, R>(
+ mut f: F,
+ mut init: H,
+ mut g: G,
+) -> impl FnMut(I) -> IResult<I, R, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: FnMut(R, O) -> R,
+ H: FnMut() -> R,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let _i = i.clone();
+ let init = init();
+ match f.parse(_i) {
+ Err(Err::Error(_)) => Err(Err::Error(E::from_error_kind(i, ErrorKind::Many1))),
+ Err(e) => Err(e),
+ Ok((i1, o1)) => {
+ let mut acc = g(init, o1);
+ let mut input = i1;
+
+ loop {
+ let _input = input.clone();
+ let len = input.input_len();
+ match f.parse(_input) {
+ Err(Err::Error(_)) => {
+ break;
+ }
+ Err(e) => return Err(e),
+ Ok((i, o)) => {
+ // infinite loop check: the parser must always consume
+ if i.input_len() == len {
+ return Err(Err::Failure(E::from_error_kind(i, ErrorKind::Many1)));
+ }
+
+ acc = g(acc, o);
+ input = i;
+ }
+ }
+ }
+
+ Ok((input, acc))
+ }
+ }
+ }
+}
+
+/// Repeats the embedded parser `m..=n` times, calling `g` to gather the results
+///
+/// This stops before `n` when the parser returns [`Err::Error`]. To instead chain an error up, see
+/// [`cut`][crate::combinator::cut].
+///
+/// # Arguments
+/// * `m` The minimum number of iterations.
+/// * `n` The maximum number of iterations.
+/// * `f` The parser to apply.
+/// * `init` A function returning the initial value.
+/// * `g` The function that combines a result of `f` with
+/// the current accumulator.
+///
+/// *Note*: If the parser passed to `many1` accepts empty inputs
+/// (like `alpha0` or `digit0`), `many1` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult};
+/// use nom8::multi::fold_many_m_n;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// fold_many_m_n(
+/// 0,
+/// 2,
+/// tag("abc"),
+/// Vec::new,
+/// |mut acc: Vec<_>, item| {
+/// acc.push(item);
+/// acc
+/// }
+/// )(s)
+/// }
+///
+/// assert_eq!(parser("abcabc"), Ok(("", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123"), Ok(("123", vec!["abc"])));
+/// assert_eq!(parser("123123"), Ok(("123123", vec![])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// assert_eq!(parser("abcabcabc"), Ok(("abc", vec!["abc", "abc"])));
+/// ```
+pub fn fold_many_m_n<I, O, E, F, G, H, R>(
+ min: usize,
+ max: usize,
+ mut parse: F,
+ mut init: H,
+ mut fold: G,
+) -> impl FnMut(I) -> IResult<I, R, E>
+where
+ I: Clone + InputLength,
+ F: Parser<I, O, E>,
+ G: FnMut(R, O) -> R,
+ H: FnMut() -> R,
+ E: ParseError<I>,
+{
+ move |mut input: I| {
+ if min > max {
+ return Err(Err::Failure(E::from_error_kind(input, ErrorKind::ManyMN)));
+ }
+
+ let mut acc = init();
+ for count in 0..max {
+ let len = input.input_len();
+ match parse.parse(input.clone()) {
+ Ok((tail, value)) => {
+ // infinite loop check: the parser must always consume
+ if tail.input_len() == len {
+ return Err(Err::Error(E::from_error_kind(tail, ErrorKind::ManyMN)));
+ }
+
+ acc = fold(acc, value);
+ input = tail;
+ }
+ //FInputXMError: handle failure properly
+ Err(Err::Error(err)) => {
+ if count < min {
+ return Err(Err::Error(E::append(input, ErrorKind::ManyMN, err)));
+ } else {
+ break;
+ }
+ }
+ Err(e) => return Err(e),
+ }
+ }
+
+ Ok((input, acc))
+ }
+}
+
+/// Gets a number from the parser and returns a
+/// subslice of the input of that size.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed, IResult, input::Streaming};
+/// use nom8::number::be_u16;
+/// use nom8::multi::length_data;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// length_data(be_u16)(s)
+/// }
+///
+/// assert_eq!(parser(Streaming(b"\x00\x03abcefg")), Ok((Streaming(&b"efg"[..]), &b"abc"[..])));
+/// assert_eq!(parser(Streaming(b"\x00\x03a")), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+pub fn length_data<I, N, E, F, const STREAMING: bool>(
+ mut f: F,
+) -> impl FnMut(I) -> IResult<I, <I as IntoOutput>::Output, E>
+where
+ I: InputLength + InputTake + InputIter + IntoOutput + InputIsStreaming<STREAMING>,
+ N: ToUsize,
+ F: Parser<I, N, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let (i, length) = f.parse(i)?;
+
+ crate::bytes::take(length).parse(i)
+ }
+}
+
+/// Gets a number from the first parser,
+/// takes a subslice of the input of that size,
+/// then applies the second parser on that subslice.
+/// If the second parser returns `Incomplete`,
+/// `length_value` will return an error.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Arguments
+/// * `f` The parser to apply.
+/// * `g` The parser to apply on the subslice.
+/// ```rust
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult, input::Streaming};
+/// use nom8::number::be_u16;
+/// use nom8::multi::length_value;
+/// use nom8::bytes::tag;
+///
+/// fn parser(s: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+/// length_value(be_u16, tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser(Streaming(b"\x00\x03abcefg")), Ok((Streaming(&b"efg"[..]), &b"abc"[..])));
+/// assert_eq!(parser(Streaming(b"\x00\x03123123")), Err(Err::Error(Error::new(Streaming(&b"123"[..]), ErrorKind::Tag))));
+/// assert_eq!(parser(Streaming(b"\x00\x03a")), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+pub fn length_value<I, O, N, E, F, G, const STREAMING: bool>(
+ mut f: F,
+ mut g: G,
+) -> impl FnMut(I) -> IResult<I, O, E>
+where
+ I: InputLength + InputTake + InputIter + IntoOutput + InputIsStreaming<STREAMING>,
+ I: Clone,
+ N: ToUsize,
+ F: Parser<I, N, E>,
+ G: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let (i, data) = length_data(f.by_ref()).parse(i)?;
+ let data = I::merge_output(i.clone(), data);
+ let (_, o) = g.by_ref().complete().parse(data)?;
+ Ok((i, o))
+ }
+}
+
+/// Gets a number from the first parser,
+/// then applies the second parser that many times.
+/// # Arguments
+/// * `f` The parser to apply to obtain the count.
+/// * `g` The parser to apply repeatedly.
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed, IResult};
+/// use nom8::number::u8;
+/// use nom8::multi::length_count;
+/// use nom8::bytes::tag;
+/// use nom8::combinator::map;
+///
+/// fn parser(s: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+/// length_count(u8.map(|i| {
+/// println!("got number: {}", i);
+/// i
+/// }), tag("abc"))(s)
+/// }
+///
+/// assert_eq!(parser(&b"\x02abcabcabc"[..]), Ok(((&b"abc"[..], vec![&b"abc"[..], &b"abc"[..]]))));
+/// assert_eq!(parser(b"\x03123123123"), Err(Err::Error(Error::new(&b"123123123"[..], ErrorKind::Tag))));
+/// ```
+#[cfg(feature = "alloc")]
+pub fn length_count<I, O, N, E, F, G>(mut f: F, mut g: G) -> impl FnMut(I) -> IResult<I, Vec<O>, E>
+where
+ I: Clone,
+ N: ToUsize,
+ F: Parser<I, N, E>,
+ G: Parser<I, O, E>,
+ E: ParseError<I>,
+{
+ move |i: I| {
+ let (i, count) = f.parse(i)?;
+ let mut input = i.clone();
+ let mut res = Vec::new();
+
+ for _ in 0..count.to_usize() {
+ let input_ = input.clone();
+ match g.parse(input_) {
+ Ok((i, o)) => {
+ res.push(o);
+ input = i;
+ }
+ Err(Err::Error(e)) => {
+ return Err(Err::Error(E::append(i, ErrorKind::Count, e)));
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok((input, res))
+ }
+}
diff --git a/vendor/nom8/src/multi/tests.rs b/vendor/nom8/src/multi/tests.rs
new file mode 100644
index 000000000..f4fa66c8f
--- /dev/null
+++ b/vendor/nom8/src/multi/tests.rs
@@ -0,0 +1,645 @@
+use super::{length_data, length_value, many0_count, many1_count};
+use crate::input::Streaming;
+use crate::Parser;
+use crate::{
+ bytes::tag,
+ character::digit1 as digit,
+ error::{ErrorKind, ParseError},
+ lib::std::str::{self, FromStr},
+ number::{be_u16, be_u8},
+ {Err, IResult, Needed},
+};
+#[cfg(feature = "alloc")]
+use crate::{
+ lib::std::vec::Vec,
+ multi::{
+ count, fold_many0, fold_many1, fold_many_m_n, length_count, many0, many1, many_m_n, many_till,
+ separated_list0, separated_list1,
+ },
+};
+
+#[test]
+#[cfg(feature = "alloc")]
+fn separated_list0_test() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list0(tag(","), tag("abcd"))(i)
+ }
+ fn multi_empty(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list0(tag(","), tag(""))(i)
+ }
+ fn empty_sep(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list0(tag(""), tag("abc"))(i)
+ }
+ fn multi_longsep(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list0(tag(".."), tag("abcd"))(i)
+ }
+
+ let a = &b"abcdef"[..];
+ let b = &b"abcd,abcdef"[..];
+ let c = &b"azerty"[..];
+ let d = &b",,abc"[..];
+ let e = &b"abcd,abcd,ef"[..];
+ let f = &b"abc"[..];
+ let g = &b"abcd."[..];
+ let h = &b"abcd,abc"[..];
+ let i = &b"abcabc"[..];
+
+ let res1 = vec![&b"abcd"[..]];
+ assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1)));
+ let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2)));
+ assert_eq!(
+ multi(Streaming(c)),
+ Ok((Streaming(&b"azerty"[..]), Vec::new()))
+ );
+ let res3 = vec![&b""[..], &b""[..], &b""[..]];
+ assert_eq!(
+ multi_empty(Streaming(d)),
+ Ok((Streaming(&b"abc"[..]), res3))
+ );
+ let i_err_pos = &i[3..];
+ assert_eq!(
+ empty_sep(Streaming(i)),
+ Err(Err::Error(error_position!(
+ Streaming(i_err_pos),
+ ErrorKind::SeparatedList
+ )))
+ );
+ let res4 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(e)), Ok((Streaming(&b",ef"[..]), res4)));
+
+ assert_eq!(multi(Streaming(f)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(
+ multi_longsep(Streaming(g)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(multi(Streaming(h)), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn separated_list1_test() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list1(tag(","), tag("abcd"))(i)
+ }
+ fn multi_longsep(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ separated_list1(tag(".."), tag("abcd"))(i)
+ }
+
+ let a = &b"abcdef"[..];
+ let b = &b"abcd,abcdef"[..];
+ let c = &b"azerty"[..];
+ let d = &b"abcd,abcd,ef"[..];
+
+ let f = &b"abc"[..];
+ let g = &b"abcd."[..];
+ let h = &b"abcd,abc"[..];
+
+ let res1 = vec![&b"abcd"[..]];
+ assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1)));
+ let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"ef"[..]), res2)));
+ assert_eq!(
+ multi(Streaming(c)),
+ Err(Err::Error(error_position!(Streaming(c), ErrorKind::Tag)))
+ );
+ let res3 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(d)), Ok((Streaming(&b",ef"[..]), res3)));
+
+ assert_eq!(multi(Streaming(f)), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(
+ multi_longsep(Streaming(g)),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(multi(Streaming(h)), Err(Err::Incomplete(Needed::new(1))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many0_test() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many0(tag("abcd"))(i)
+ }
+ fn multi_empty(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many0(tag(""))(i)
+ }
+
+ assert_eq!(
+ multi(Streaming(&b"abcdef"[..])),
+ Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]]))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcdabcdefgh"[..])),
+ Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]]))
+ );
+ assert_eq!(
+ multi(Streaming(&b"azerty"[..])),
+ Ok((Streaming(&b"azerty"[..]), Vec::new()))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcdab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcd"[..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_eq!(
+ multi(Streaming(&b""[..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_eq!(
+ multi_empty(Streaming(&b"abcdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"abcdef"[..]),
+ ErrorKind::Many0
+ )))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many1_test() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many1(tag("abcd"))(i)
+ }
+
+ let a = &b"abcdef"[..];
+ let b = &b"abcdabcdefgh"[..];
+ let c = &b"azerty"[..];
+ let d = &b"abcdab"[..];
+
+ let res1 = vec![&b"abcd"[..]];
+ assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1)));
+ let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2)));
+ assert_eq!(
+ multi(Streaming(c)),
+ Err(Err::Error(error_position!(Streaming(c), ErrorKind::Tag)))
+ );
+ assert_eq!(multi(Streaming(d)), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many_till_test() {
+ fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
+ many_till(tag("abcd"), tag("efgh"))(i)
+ }
+
+ let a = b"abcdabcdefghabcd";
+ let b = b"efghabcd";
+ let c = b"azerty";
+
+ let res_a = (vec![&b"abcd"[..], &b"abcd"[..]], &b"efgh"[..]);
+ let res_b: (Vec<&[u8]>, &[u8]) = (Vec::new(), &b"efgh"[..]);
+ assert_eq!(multi(&a[..]), Ok((&b"abcd"[..], res_a)));
+ assert_eq!(multi(&b[..]), Ok((&b"abcd"[..], res_b)));
+ assert_eq!(
+ multi(&c[..]),
+ Err(Err::Error(error_node_position!(
+ &c[..],
+ ErrorKind::ManyTill,
+ error_position!(&c[..], ErrorKind::Tag)
+ )))
+ );
+}
+
+#[test]
+#[cfg(feature = "std")]
+fn infinite_many() {
+ fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
+ println!("input: {:?}", input);
+ Err(Err::Error(error_position!(input, ErrorKind::Tag)))
+ }
+
+ // should not go into an infinite loop
+ fn multi0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+ many0(tst)(i)
+ }
+ let a = &b"abcdef"[..];
+ assert_eq!(multi0(a), Ok((a, Vec::new())));
+
+ fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+ many1(tst)(i)
+ }
+ let a = &b"abcdef"[..];
+ assert_eq!(
+ multi1(a),
+ Err(Err::Error(error_position!(a, ErrorKind::Tag)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn many_m_n_test() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many_m_n(2, 4, tag("Abcd"))(i)
+ }
+
+ let a = &b"Abcdef"[..];
+ let b = &b"AbcdAbcdefgh"[..];
+ let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
+ let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
+ let e = &b"AbcdAb"[..];
+
+ assert_eq!(
+ multi(Streaming(a)),
+ Err(Err::Error(error_position!(
+ Streaming(&b"ef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1)));
+ let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2)));
+ let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3)));
+ assert_eq!(multi(Streaming(e)), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn count_test() {
+ const TIMES: usize = 2;
+ fn cnt_2(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ count(tag("abc"), TIMES)(i)
+ }
+
+ assert_eq!(
+ cnt_2(Streaming(&b"abcabcabcdef"[..])),
+ Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]]))
+ );
+ assert_eq!(
+ cnt_2(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ cnt_2(Streaming(&b"abcab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ cnt_2(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ cnt_2(Streaming(&b"xxxabcabcdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxabcabcdef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ cnt_2(Streaming(&b"abcxxxabcdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxabcdef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn count_zero() {
+ const TIMES: usize = 0;
+ fn counter_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+ count(tag("abc"), TIMES)(i)
+ }
+
+ let done = &b"abcabcabcdef"[..];
+ let parsed_done = Vec::new();
+ let rest = done;
+ let incomplete_1 = &b"ab"[..];
+ let parsed_incompl_1 = Vec::new();
+ let incomplete_2 = &b"abcab"[..];
+ let parsed_incompl_2 = Vec::new();
+ let error = &b"xxx"[..];
+ let error_remain = &b"xxx"[..];
+ let parsed_err = Vec::new();
+ let error_1 = &b"xxxabcabcdef"[..];
+ let parsed_err_1 = Vec::new();
+ let error_1_remain = &b"xxxabcabcdef"[..];
+ let error_2 = &b"abcxxxabcdef"[..];
+ let parsed_err_2 = Vec::new();
+ let error_2_remain = &b"abcxxxabcdef"[..];
+
+ assert_eq!(counter_2(done), Ok((rest, parsed_done)));
+ assert_eq!(
+ counter_2(incomplete_1),
+ Ok((incomplete_1, parsed_incompl_1))
+ );
+ assert_eq!(
+ counter_2(incomplete_2),
+ Ok((incomplete_2, parsed_incompl_2))
+ );
+ assert_eq!(counter_2(error), Ok((error_remain, parsed_err)));
+ assert_eq!(counter_2(error_1), Ok((error_1_remain, parsed_err_1)));
+ assert_eq!(counter_2(error_2), Ok((error_2_remain, parsed_err_2)));
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub struct NilError;
+
+impl<I> From<(I, ErrorKind)> for NilError {
+ fn from(_: (I, ErrorKind)) -> Self {
+ NilError
+ }
+}
+
+impl<I> ParseError<I> for NilError {
+ fn from_error_kind(_: I, _: ErrorKind) -> NilError {
+ NilError
+ }
+ fn append(_: I, _: ErrorKind, _: NilError) -> NilError {
+ NilError
+ }
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn length_count_test() {
+ fn number(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u32> {
+ digit
+ .map_res(str::from_utf8)
+ .map_res(FromStr::from_str)
+ .parse(i)
+ }
+
+ fn cnt(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ length_count(number, tag("abc"))(i)
+ }
+
+ assert_eq!(
+ cnt(Streaming(&b"2abcabcabcdef"[..])),
+ Ok((Streaming(&b"abcdef"[..]), vec![&b"abc"[..], &b"abc"[..]]))
+ );
+ assert_eq!(
+ cnt(Streaming(&b"2ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ cnt(Streaming(&b"3abcab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ cnt(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Digit
+ )))
+ );
+ assert_eq!(
+ cnt(Streaming(&b"2abcxxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn length_data_test() {
+ fn number(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u32> {
+ digit
+ .map_res(str::from_utf8)
+ .map_res(FromStr::from_str)
+ .parse(i)
+ }
+
+ fn take(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ length_data(number)(i)
+ }
+
+ assert_eq!(
+ take(Streaming(&b"6abcabcabcdef"[..])),
+ Ok((Streaming(&b"abcdef"[..]), &b"abcabc"[..]))
+ );
+ assert_eq!(
+ take(Streaming(&b"3ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ take(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Digit
+ )))
+ );
+ assert_eq!(
+ take(Streaming(&b"2abcxxx"[..])),
+ Ok((Streaming(&b"cxxx"[..]), &b"ab"[..]))
+ );
+}
+
+#[test]
+fn length_value_test() {
+ fn length_value_1(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u16> {
+ length_value(be_u8, be_u16)(i)
+ }
+ fn length_value_2(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (u8, u8)> {
+ length_value(be_u8, (be_u8, be_u8))(i)
+ }
+
+ let i1 = [0, 5, 6];
+ assert_eq!(
+ length_value_1(Streaming(&i1)),
+ Err(Err::Error(error_position!(
+ Streaming(&b""[..]),
+ ErrorKind::Complete
+ )))
+ );
+ assert_eq!(
+ length_value_2(Streaming(&i1)),
+ Err(Err::Error(error_position!(
+ Streaming(&b""[..]),
+ ErrorKind::Complete
+ )))
+ );
+
+ let i2 = [1, 5, 6, 3];
+ assert_eq!(
+ length_value_1(Streaming(&i2)),
+ Err(Err::Error(error_position!(
+ Streaming(&i2[1..2]),
+ ErrorKind::Complete
+ )))
+ );
+ assert_eq!(
+ length_value_2(Streaming(&i2)),
+ Err(Err::Error(error_position!(
+ Streaming(&i2[1..2]),
+ ErrorKind::Complete
+ )))
+ );
+
+ let i3 = [2, 5, 6, 3, 4, 5, 7];
+ assert_eq!(
+ length_value_1(Streaming(&i3)),
+ Ok((Streaming(&i3[3..]), 1286))
+ );
+ assert_eq!(
+ length_value_2(Streaming(&i3)),
+ Ok((Streaming(&i3[3..]), (5, 6)))
+ );
+
+ let i4 = [3, 5, 6, 3, 4, 5];
+ assert_eq!(
+ length_value_1(Streaming(&i4)),
+ Ok((Streaming(&i4[4..]), 1286))
+ );
+ assert_eq!(
+ length_value_2(Streaming(&i4)),
+ Ok((Streaming(&i4[4..]), (5, 6)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many0_test() {
+ fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+ acc.push(item);
+ acc
+ }
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ fold_many0(tag("abcd"), Vec::new, fold_into_vec)(i)
+ }
+ fn multi_empty(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ fold_many0(tag(""), Vec::new, fold_into_vec)(i)
+ }
+
+ assert_eq!(
+ multi(Streaming(&b"abcdef"[..])),
+ Ok((Streaming(&b"ef"[..]), vec![&b"abcd"[..]]))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcdabcdefgh"[..])),
+ Ok((Streaming(&b"efgh"[..]), vec![&b"abcd"[..], &b"abcd"[..]]))
+ );
+ assert_eq!(
+ multi(Streaming(&b"azerty"[..])),
+ Ok((Streaming(&b"azerty"[..]), Vec::new()))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcdab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ multi(Streaming(&b"abcd"[..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_eq!(
+ multi(Streaming(&b""[..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_eq!(
+ multi_empty(Streaming(&b"abcdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"abcdef"[..]),
+ ErrorKind::Many0
+ )))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many1_test() {
+ fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+ acc.push(item);
+ acc
+ }
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ fold_many1(tag("abcd"), Vec::new, fold_into_vec)(i)
+ }
+
+ let a = &b"abcdef"[..];
+ let b = &b"abcdabcdefgh"[..];
+ let c = &b"azerty"[..];
+ let d = &b"abcdab"[..];
+
+ let res1 = vec![&b"abcd"[..]];
+ assert_eq!(multi(Streaming(a)), Ok((Streaming(&b"ef"[..]), res1)));
+ let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res2)));
+ assert_eq!(
+ multi(Streaming(c)),
+ Err(Err::Error(error_position!(Streaming(c), ErrorKind::Many1)))
+ );
+ assert_eq!(multi(Streaming(d)), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn fold_many_m_n_test() {
+ fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
+ acc.push(item);
+ acc
+ }
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec)(i)
+ }
+
+ let a = &b"Abcdef"[..];
+ let b = &b"AbcdAbcdefgh"[..];
+ let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
+ let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
+ let e = &b"AbcdAb"[..];
+
+ assert_eq!(
+ multi(Streaming(a)),
+ Err(Err::Error(error_position!(
+ Streaming(&b"ef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(b)), Ok((Streaming(&b"efgh"[..]), res1)));
+ let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(c)), Ok((Streaming(&b"efgh"[..]), res2)));
+ let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
+ assert_eq!(multi(Streaming(d)), Ok((Streaming(&b"Abcdefgh"[..]), res3)));
+ assert_eq!(multi(Streaming(e)), Err(Err::Incomplete(Needed::new(2))));
+}
+
+#[test]
+fn many0_count_test() {
+ fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> {
+ many0_count((digit, tag(",")))(i)
+ }
+
+ assert_eq!(count0_nums(&b"123,junk"[..]), Ok((&b"junk"[..], 1)));
+
+ assert_eq!(count0_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
+
+ assert_eq!(
+ count0_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
+ Ok((&b"junk"[..], 10))
+ );
+
+ assert_eq!(count0_nums(&b"hello"[..]), Ok((&b"hello"[..], 0)));
+}
+
+#[test]
+fn many1_count_test() {
+ fn count1_nums(i: &[u8]) -> IResult<&[u8], usize> {
+ many1_count((digit, tag(",")))(i)
+ }
+
+ assert_eq!(count1_nums(&b"123,45,junk"[..]), Ok((&b"junk"[..], 2)));
+
+ assert_eq!(
+ count1_nums(&b"1,2,3,4,5,6,7,8,9,0,junk"[..]),
+ Ok((&b"junk"[..], 10))
+ );
+
+ assert_eq!(
+ count1_nums(&b"hello"[..]),
+ Err(Err::Error(error_position!(
+ &b"hello"[..],
+ ErrorKind::Many1Count
+ )))
+ );
+}
diff --git a/vendor/nom8/src/number/complete.rs b/vendor/nom8/src/number/complete.rs
new file mode 100644
index 000000000..dd45b2a52
--- /dev/null
+++ b/vendor/nom8/src/number/complete.rs
@@ -0,0 +1,2289 @@
+//! Parsers recognizing numbers, complete input version
+
+#![allow(deprecated)]
+
+use crate::branch::alt;
+use crate::bytes::complete::tag;
+use crate::character::complete::{char, digit1, sign};
+use crate::combinator::{cut, map, opt, recognize};
+use crate::error::ParseError;
+use crate::error::{make_error, ErrorKind};
+use crate::input::{
+ AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, IntoOutput,
+ Offset, Slice,
+};
+use crate::lib::std::ops::{Range, RangeFrom, RangeTo};
+use crate::sequence::{pair, tuple};
+use crate::*;
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u8;
+///
+/// let parser = |s| {
+/// be_u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u8`][crate::number::be_u8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u8`")]
+pub fn be_u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u16;
+///
+/// let parser = |s| {
+/// be_u16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u16`][crate::number::be_u16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u16`")]
+pub fn be_u16<I, E: ParseError<I>>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 2;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u16;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u16;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 3 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u24;
+///
+/// let parser = |s| {
+/// be_u24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u24`][crate::number::be_u24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u24`")]
+pub fn be_u24<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 3;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u32;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u32;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u32;
+///
+/// let parser = |s| {
+/// be_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u32`][crate::number::be_u32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u32`")]
+pub fn be_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 4;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u32;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u32;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u64;
+///
+/// let parser = |s| {
+/// be_u64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u64`][crate::number::be_u64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u64`")]
+pub fn be_u64<I, E: ParseError<I>>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 8;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u64;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u64;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_u128;
+///
+/// let parser = |s| {
+/// be_u128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u128`][crate::number::be_u128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_u128`")]
+pub fn be_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 16;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u128;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u128;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i8;
+///
+/// let parser = |s| {
+/// be_i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i8`][crate::number::be_i8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i8`")]
+pub fn be_i8<I, E: ParseError<I>>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u8.map(|x| x as i8).parse(input)
+}
+
+/// Recognizes a big endian signed 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i16;
+///
+/// let parser = |s| {
+/// be_i16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i16`][crate::number::be_i16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i16`")]
+pub fn be_i16<I, E: ParseError<I>>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u16.map(|x| x as i16).parse(input)
+}
+
+/// Recognizes a big endian signed 3 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i24;
+///
+/// let parser = |s| {
+/// be_i24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i24`][crate::number::be_i24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i24`")]
+pub fn be_i24<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ // Same as the unsigned version but we need to sign-extend manually here
+ be_u24
+ .map(|x| {
+ if x & 0x80_00_00 != 0 {
+ (x | 0xff_00_00_00) as i32
+ } else {
+ x as i32
+ }
+ })
+ .parse(input)
+}
+
+/// Recognizes a big endian signed 4 bytes integer.
+///
+/// *Complete version*: Teturns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i32;
+///
+/// let parser = |s| {
+/// be_i32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i32`][crate::number::be_i32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i32`")]
+pub fn be_i32<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u32.map(|x| x as i32).parse(input)
+}
+
+/// Recognizes a big endian signed 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i64;
+///
+/// let parser = |s| {
+/// be_i64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i64`][crate::number::be_i64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i64`")]
+pub fn be_i64<I, E: ParseError<I>>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u64.map(|x| x as i64).parse(input)
+}
+
+/// Recognizes a big endian signed 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_i128;
+///
+/// let parser = |s| {
+/// be_i128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i128`][crate::number::be_i128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_i128`")]
+pub fn be_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u128.map(|x| x as i128).parse(input)
+}
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u8;
+///
+/// let parser = |s| {
+/// le_u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u8`][crate::number::le_u8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u8`")]
+pub fn le_u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u16;
+///
+/// let parser = |s| {
+/// le_u16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u16`][crate::number::le_u16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u16`")]
+pub fn le_u16<I, E: ParseError<I>>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 2;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u16;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u16) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 3 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u24;
+///
+/// let parser = |s| {
+/// le_u24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u24`][crate::number::le_u24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u24`")]
+pub fn le_u24<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 3;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u32;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u32) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u32;
+///
+/// let parser = |s| {
+/// le_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u32`][crate::number::le_u32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u32`")]
+pub fn le_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 4;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u32;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u32) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u64;
+///
+/// let parser = |s| {
+/// le_u64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u64`][crate::number::le_u64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u64`")]
+pub fn le_u64<I, E: ParseError<I>>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 8;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u64;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u64) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_u128;
+///
+/// let parser = |s| {
+/// le_u128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u128`][crate::number::le_u128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_u128`")]
+pub fn le_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 16;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let mut res = 0u128;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u128) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i8;
+///
+/// let parser = |s| {
+/// le_i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i8`][crate::number::le_i8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i8`")]
+pub fn le_i8<I, E: ParseError<I>>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u8.map(|x| x as i8).parse(input)
+}
+
+/// Recognizes a little endian signed 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i16;
+///
+/// let parser = |s| {
+/// le_i16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i16`][crate::number::le_i16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i16`")]
+pub fn le_i16<I, E: ParseError<I>>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u16.map(|x| x as i16).parse(input)
+}
+
+/// Recognizes a little endian signed 3 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i24;
+///
+/// let parser = |s| {
+/// le_i24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i24`][crate::number::le_i24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i24`")]
+pub fn le_i24<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ // Same as the unsigned version but we need to sign-extend manually here
+ le_u24
+ .map(|x| {
+ if x & 0x80_00_00 != 0 {
+ (x | 0xff_00_00_00) as i32
+ } else {
+ x as i32
+ }
+ })
+ .parse(input)
+}
+
+/// Recognizes a little endian signed 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i32;
+///
+/// let parser = |s| {
+/// le_i32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i32`][crate::number::le_i32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i32`")]
+pub fn le_i32<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u32.map(|x| x as i32).parse(input)
+}
+
+/// Recognizes a little endian signed 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i64;
+///
+/// let parser = |s| {
+/// le_i64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i64`][crate::number::le_i64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i64`")]
+pub fn le_i64<I, E: ParseError<I>>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u64.map(|x| x as i64).parse(input)
+}
+
+/// Recognizes a little endian signed 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_i128;
+///
+/// let parser = |s| {
+/// le_i128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i128`][crate::number::le_i128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_i128`")]
+pub fn le_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u128.map(|x| x as i128).parse(input)
+}
+
+/// Recognizes an unsigned 1 byte integer
+///
+/// Note that endianness does not apply to 1 byte numbers.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u8;
+///
+/// let parser = |s| {
+/// u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u8`][crate::number::u8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u8`")]
+pub fn u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Error(make_error(input, ErrorKind::Eof)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes an unsigned 2 bytes integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u16 integer.
+/// *complete version*: returns an error if there is not enough input data
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u16;
+///
+/// let be_u16 = |s| {
+/// u16(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u16 = |s| {
+/// u16(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u16`][crate::number::u16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u16`")]
+pub fn u16<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u16,
+ crate::number::Endianness::Little => le_u16,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u16,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u16,
+ }
+}
+
+/// Recognizes an unsigned 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u24 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u24;
+///
+/// let be_u24 = |s| {
+/// u24(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u24 = |s| {
+/// u24(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u24`][crate::number::u24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u24`")]
+pub fn u24<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u24,
+ crate::number::Endianness::Little => le_u24,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u24,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u24,
+ }
+}
+
+/// Recognizes an unsigned 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u32 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u32;
+///
+/// let be_u32 = |s| {
+/// u32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u32 = |s| {
+/// u32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u32`][crate::number::u32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u32`")]
+pub fn u32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u32,
+ crate::number::Endianness::Little => le_u32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u32,
+ }
+}
+
+/// Recognizes an unsigned 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u64 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u64;
+///
+/// let be_u64 = |s| {
+/// u64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u64 = |s| {
+/// u64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u64`][crate::number::u64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u64`")]
+pub fn u64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u64,
+ crate::number::Endianness::Little => le_u64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u64,
+ }
+}
+
+/// Recognizes an unsigned 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u128 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::u128;
+///
+/// let be_u128 = |s| {
+/// u128(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u128 = |s| {
+/// u128(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u128`][crate::number::u128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::u128`")]
+pub fn u128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u128,
+ crate::number::Endianness::Little => le_u128,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u128,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u128,
+ }
+}
+
+/// Recognizes a signed 1 byte integer
+///
+/// Note that endianness does not apply to 1 byte numbers.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i8;
+///
+/// let parser = |s| {
+/// i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i8`][crate::number::i8]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i8`")]
+pub fn i8<I, E: ParseError<I>>(i: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ u8.map(|x| x as i8).parse(i)
+}
+
+/// Recognizes a signed 2 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i16 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i16;
+///
+/// let be_i16 = |s| {
+/// i16(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i16 = |s| {
+/// i16(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i16`][crate::number::i16]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i16`")]
+pub fn i16<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i16,
+ crate::number::Endianness::Little => le_i16,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i16,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i16,
+ }
+}
+
+/// Recognizes a signed 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i24 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i24;
+///
+/// let be_i24 = |s| {
+/// i24(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i24 = |s| {
+/// i24(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i24`][crate::number::i24]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i24`")]
+pub fn i24<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i24,
+ crate::number::Endianness::Little => le_i24,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i24,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i24,
+ }
+}
+
+/// Recognizes a signed 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i32 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i32;
+///
+/// let be_i32 = |s| {
+/// i32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i32 = |s| {
+/// i32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i32`][crate::number::i32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i32`")]
+pub fn i32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i32,
+ crate::number::Endianness::Little => le_i32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i32,
+ }
+}
+
+/// Recognizes a signed 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i64 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i64;
+///
+/// let be_i64 = |s| {
+/// i64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i64 = |s| {
+/// i64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i64`][crate::number::i64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i64`")]
+pub fn i64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i64,
+ crate::number::Endianness::Little => le_i64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i64,
+ }
+}
+
+/// Recognizes a signed 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i128 integer.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::i128;
+///
+/// let be_i128 = |s| {
+/// i128(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i128 = |s| {
+/// i128(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i128`][crate::number::i128]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::i128`")]
+pub fn i128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i128,
+ crate::number::Endianness::Little => le_i128,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i128,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i128,
+ }
+}
+
+/// Recognizes a big endian 4 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_f32;
+///
+/// let parser = |s| {
+/// be_f32(s)
+/// };
+///
+/// assert_eq!(parser(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_f32`][crate::number::be_f32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_f32`")]
+pub fn be_f32<I, E: ParseError<I>>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match be_u32(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f32::from_bits(o))),
+ }
+}
+
+/// Recognizes a big endian 8 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::be_f64;
+///
+/// let parser = |s| {
+/// be_f64(s)
+/// };
+///
+/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_f64`][crate::number::be_f64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::be_f64`")]
+pub fn be_f64<I, E: ParseError<I>>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match be_u64(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f64::from_bits(o))),
+ }
+}
+
+/// Recognizes a little endian 4 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_f32;
+///
+/// let parser = |s| {
+/// le_f32(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_f32`][crate::number::le_f32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_f32`")]
+pub fn le_f32<I, E: ParseError<I>>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match le_u32(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f32::from_bits(o))),
+ }
+}
+
+/// Recognizes a little endian 8 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::le_f64;
+///
+/// let parser = |s| {
+/// le_f64(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_f64`][crate::number::le_f64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::le_f64`")]
+pub fn le_f64<I, E: ParseError<I>>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match le_u64(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f64::from_bits(o))),
+ }
+}
+
+/// Recognizes a 4 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f32 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f32 float.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::f32;
+///
+/// let be_f32 = |s| {
+/// f32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+///
+/// let le_f32 = |s| {
+/// f32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::f32`][crate::number::f32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::f32`")]
+pub fn f32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_f32,
+ crate::number::Endianness::Little => le_f32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_f32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_f32,
+ }
+}
+
+/// Recognizes an 8 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f64 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f64 float.
+/// *complete version*: returns an error if there is not enough input data
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::f64;
+///
+/// let be_f64 = |s| {
+/// f64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+///
+/// let le_f64 = |s| {
+/// f64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::f64`][crate::number::f64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::f64`")]
+pub fn f64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_f64,
+ crate::number::Endianness::Little => le_f64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_f64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_f64,
+ }
+}
+
+/// Recognizes a hex-encoded integer.
+///
+/// *Complete version*: Will parse until the end of input if it has less than 8 bytes.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::hex_u32;
+///
+/// let parser = |s| {
+/// hex_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"01AE"[..]), Ok((&b""[..], 0x01AE)));
+/// assert_eq!(parser(&b"abc"[..]), Ok((&b""[..], 0x0ABC)));
+/// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::hex_u32`][crate::number::hex_u32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::number::hex_u32`")]
+pub fn hex_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: InputTakeAtPosition,
+ I: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ <I as InputTakeAtPosition>::Item: AsChar,
+ I: AsBytes,
+ I: InputLength,
+{
+ let e: ErrorKind = ErrorKind::IsA;
+ let (i, o) = input.split_at_position1_complete(
+ |c| {
+ let c = c.as_char();
+ !"0123456789abcdefABCDEF".contains(c)
+ },
+ e,
+ )?;
+
+ // Do not parse more than 8 characters for a u32
+ let (parsed, remaining) = if o.input_len() <= 8 {
+ (o, i)
+ } else {
+ (input.slice(..8), input.slice(8..))
+ };
+
+ let res = parsed
+ .as_bytes()
+ .iter()
+ .rev()
+ .enumerate()
+ .map(|(k, &v)| {
+ let digit = v as char;
+ digit.to_digit(16).unwrap_or(0) << (k * 4)
+ })
+ .sum();
+
+ Ok((remaining, res))
+}
+
+/// Recognizes floating point number in a byte string and returns the corresponding slice.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::recognize_float;
+///
+/// let parser = |s| {
+/// recognize_float(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", "11e-1")));
+/// assert_eq!(parser("123E-02"), Ok(("", "123E-02")));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", "123")));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char))));
+/// ```
+#[rustfmt::skip]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float`][crate::character::recognize_float]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::recognize_float`")]
+pub fn recognize_float<T, E:ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ recognize(
+ tuple((
+ opt(alt((char('+'), char('-')))),
+ alt((
+ map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()),
+ map(tuple((char('.'), digit1)), |_| ())
+ )),
+ opt(tuple((
+ alt((char('e'), char('E'))),
+ opt(alt((char('+'), char('-')))),
+ cut(digit1)
+ )))
+ ))
+ )(input)
+}
+
+// workaround until issues with minimal-lexical are fixed
+#[doc(hidden)]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float_or_exceptions`][crate::character::recognize_float_or_exceptions]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::recognize_float_or_exceptions`"
+)]
+pub fn recognize_float_or_exceptions<T, E: ParseError<T>>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputTake + Compare<&'static str>,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition,
+ T: IntoOutput,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ alt((
+ |i: T| {
+ recognize_float::<_, E>(i.clone()).map_err(|e| match e {
+ crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)),
+ crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)),
+ crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed),
+ })
+ },
+ |i: T| {
+ crate::bytes::complete::tag_no_case::<_, _, E>("nan")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ |i: T| {
+ crate::bytes::complete::tag_no_case::<_, _, E>("inf")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ |i: T| {
+ crate::bytes::complete::tag_no_case::<_, _, E>("infinity")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ ))(input)
+}
+
+/// Recognizes a floating point number in text format
+///
+/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
+/// data.
+///
+/// *Complete version*: Can parse until the end of input.
+///
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float_parts`][crate::character::recognize_float_parts]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::recognize_float_parts`"
+)]
+pub fn recognize_float_parts<T, E: ParseError<T>>(
+ input: T,
+) -> IResult<
+ T,
+ (
+ bool,
+ <T as IntoOutput>::Output,
+ <T as IntoOutput>::Output,
+ i32,
+ ),
+ E,
+>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputTake,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar + Copy,
+ T: InputTakeAtPosition + InputLength,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: for<'a> Compare<&'a [u8]>,
+ T: AsBytes,
+{
+ let (i, sign) = sign(input.clone())?;
+
+ let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') {
+ Some(index) => i.take_split(index),
+ None => i.take_split(i.input_len()),
+ };
+ //let (i, mut integer) = digit0(i)?;
+ let (i, mut integer) = match i
+ .as_bytes()
+ .iter()
+ .position(|c| !(*c >= b'0' && *c <= b'9'))
+ {
+ Some(index) => i.take_split(index),
+ None => i.take_split(i.input_len()),
+ };
+
+ if integer.input_len() == 0 && zeroes.input_len() > 0 {
+ // keep the last zero if integer is empty
+ integer = zeroes.slice(zeroes.input_len() - 1..);
+ }
+
+ let (i, opt_dot) = opt(tag(&b"."[..]))(i)?;
+ let (i, fraction) = if opt_dot.is_none() {
+ let i2 = i.clone();
+ (i2, i.slice(..0))
+ } else {
+ // match number, trim right zeroes
+ let mut zero_count = 0usize;
+ let mut position = None;
+ for (pos, c) in i.as_bytes().iter().enumerate() {
+ if *c >= b'0' && *c <= b'9' {
+ if *c == b'0' {
+ zero_count += 1;
+ } else {
+ zero_count = 0;
+ }
+ } else {
+ position = Some(pos);
+ break;
+ }
+ }
+
+ let position = position.unwrap_or(i.input_len());
+
+ let index = if zero_count == 0 {
+ position
+ } else if zero_count == position {
+ position - zero_count + 1
+ } else {
+ position - zero_count
+ };
+
+ (i.slice(position..), i.slice(..index))
+ };
+
+ if integer.input_len() == 0 && fraction.input_len() == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Float)));
+ }
+
+ let i2 = i.clone();
+ let (i, e) = match i.as_bytes().iter().next() {
+ Some(b'e') => (i.slice(1..), true),
+ Some(b'E') => (i.slice(1..), true),
+ _ => (i, false),
+ };
+
+ let (i, exp) = if e {
+ cut(crate::character::complete::i32)(i)?
+ } else {
+ (i2, 0)
+ };
+
+ Ok((
+ i,
+ (sign, integer.into_output(), fraction.into_output(), exp),
+ ))
+}
+
+use crate::input::ParseTo;
+
+/// Recognizes floating point number in text format and returns a f32.
+///
+/// *Complete version*: Can parse until the end of input.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::float;
+///
+/// let parser = |s| {
+/// float(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::f32`][crate::character::f32]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::f32`")]
+pub fn float<T, E: ParseError<T>>(input: T) -> IResult<T, f32, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset + Compare<&'static str>,
+ T: InputIter + InputLength + InputTake,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: ParseTo<f32>,
+ <T as InputIter>::Item: AsChar + Copy,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ let (i, s) = recognize_float_or_exceptions(input)?;
+ match s.parse_to() {
+ Some(f) => Ok((i, f)),
+ None => Err(crate::Err::Error(E::from_error_kind(
+ i,
+ crate::error::ErrorKind::Float,
+ ))),
+ }
+}
+
+/// Recognizes floating point number in text format and returns a f64.
+///
+/// *Complete version*: Can parse until the end of input.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::double;
+///
+/// let parser = |s| {
+/// double(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::f64`][crate::character::f64]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::f64`")]
+pub fn double<T, E: ParseError<T>>(input: T) -> IResult<T, f64, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>> + Slice<Range<usize>>,
+ T: Clone + Offset + Compare<&'static str>,
+ T: InputIter + InputLength + InputTake,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: ParseTo<f64>,
+ <T as InputIter>::Item: AsChar + Copy,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ let (i, s) = recognize_float_or_exceptions(input)?;
+ match s.parse_to() {
+ Some(f) => Ok((i, f)),
+ None => Err(crate::Err::Error(E::from_error_kind(
+ i,
+ crate::error::ErrorKind::Float,
+ ))),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::error::ErrorKind;
+ use crate::Err;
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn i8_tests() {
+ assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn be_i8_tests() {
+ assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn be_i16_tests() {
+ assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16)));
+ }
+
+ #[test]
+ fn be_u24_tests() {
+ assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ be_u24(&[0x12, 0x34, 0x56][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn be_i24_tests() {
+ assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ be_i24(&[0xED, 0xCB, 0xAA][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn be_i32_tests() {
+ assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ be_i32(&[0x7f, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ be_i32(&[0x80, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn be_i64_tests() {
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn be_i128_tests() {
+ assert_parse!(
+ be_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn le_i8_tests() {
+ assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn le_i16_tests() {
+ assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16)));
+ }
+
+ #[test]
+ fn le_u24_tests() {
+ assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ le_u24(&[0x56, 0x34, 0x12][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn le_i24_tests() {
+ assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ le_i24(&[0xAA, 0xCB, 0xED][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn le_i32_tests() {
+ assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ le_i32(&[0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ le_i32(&[0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn le_i64_tests() {
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn le_i128_tests() {
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn be_f32_tests() {
+ assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn be_f64_tests() {
+ assert_parse!(
+ be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn le_f32_tests() {
+ assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn le_f64_tests() {
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn hex_u32_tests() {
+ assert_parse!(
+ hex_u32(&b";"[..]),
+ Err(Err::Error(error_position!(&b";"[..], ErrorKind::IsA)))
+ );
+ assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255)));
+ assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138)));
+ assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347)));
+ assert_parse!(
+ hex_u32(&b"c5a31be201;"[..]),
+ Ok((&b"01;"[..], 3_315_801_058))
+ );
+ assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295)));
+ assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0)));
+ assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af)));
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn float_test() {
+ let mut test_cases = vec![
+ "+3.14",
+ "3.14",
+ "-3.14",
+ "0",
+ "0.0",
+ "1.",
+ ".789",
+ "-.5",
+ "1e7",
+ "-1E-7",
+ ".3e-2",
+ "1.e4",
+ "1.2e4",
+ "12.34",
+ "-1.234E-12",
+ "-1.234e-12",
+ "0.00000000000000000087",
+ ];
+
+ for test in test_cases.drain(..) {
+ let expected32 = str::parse::<f32>(test).unwrap();
+ let expected64 = str::parse::<f64>(test).unwrap();
+
+ println!("now parsing: {} -> {}", test, expected32);
+
+ let larger = format!("{}", test);
+ assert_parse!(recognize_float(&larger[..]), Ok(("", test)));
+
+ assert_parse!(float(larger.as_bytes()), Ok((&b""[..], expected32)));
+ assert_parse!(float(&larger[..]), Ok(("", expected32)));
+
+ assert_parse!(double(larger.as_bytes()), Ok((&b""[..], expected64)));
+ assert_parse!(double(&larger[..]), Ok(("", expected64)));
+ }
+
+ let remaining_exponent = "-1.234E-";
+ assert_parse!(
+ recognize_float(remaining_exponent),
+ Err(Err::Failure(("", ErrorKind::Digit)))
+ );
+
+ let (_i, nan) = float::<_, ()>("NaN").unwrap();
+ assert!(nan.is_nan());
+
+ let (_i, inf) = float::<_, ()>("inf").unwrap();
+ assert!(inf.is_infinite());
+ let (_i, inf) = float::<_, ()>("infinite").unwrap();
+ assert!(inf.is_infinite());
+ }
+
+ #[test]
+ fn configurable_endianness() {
+ use crate::number::Endianness;
+
+ fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Big)(i)
+ }
+ fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
+ assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
+
+ fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Big)(i)
+ }
+ fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 302_014_464_u32))
+ );
+ assert_eq!(
+ le_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 6_291_474_u32))
+ );
+
+ fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Big)(i)
+ }
+ fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 1_297_142_246_100_992_000_u64))
+ );
+ assert_eq!(
+ le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_666_770_u64))
+ );
+
+ fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Big)(i)
+ }
+ fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
+ assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
+
+ fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Big)(i)
+ }
+ fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 1_204_224_i32))
+ );
+ assert_eq!(
+ le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 6_296_064_i32))
+ );
+
+ fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Big)(i)
+ }
+ fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 71_881_672_479_506_432_i64))
+ );
+ assert_eq!(
+ le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_732_032_i64))
+ );
+ }
+
+ #[cfg(feature = "std")]
+ fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
+ match recognize_float_or_exceptions(i) {
+ Err(e) => Err(e),
+ Ok((i, s)) => {
+ if s.is_empty() {
+ return Err(Err::Error(()));
+ }
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(())),
+ }
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg(feature = "std")]
+ fn floats(s in "\\PC*") {
+ println!("testing {}", s);
+ let res1 = parse_f64(&s);
+ let res2 = double::<_, ()>(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+}
diff --git a/vendor/nom8/src/number/mod.rs b/vendor/nom8/src/number/mod.rs
new file mode 100644
index 000000000..4937ae24e
--- /dev/null
+++ b/vendor/nom8/src/number/mod.rs
@@ -0,0 +1,2197 @@
+//! Parsers recognizing numbers
+
+#![allow(deprecated)] // will just become `pub(crate)` later
+
+pub mod complete;
+pub mod streaming;
+#[cfg(test)]
+mod tests;
+
+use crate::error::ParseError;
+use crate::input::{
+ AsBytes, AsChar, InputIsStreaming, InputIter, InputLength, InputTakeAtPosition, Slice,
+};
+use crate::lib::std::ops::{RangeFrom, RangeTo};
+use crate::IResult;
+
+/// Configurable endianness
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+pub enum Endianness {
+ /// Big endian
+ Big,
+ /// Little endian
+ Little,
+ /// Will match the host's endianness
+ Native,
+}
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u8;
+///
+/// let parser = |s| {
+/// be_u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u8;
+///
+/// let parser = |s| {
+/// be_u8::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"\x01abcd"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn be_u8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u8(input)
+ } else {
+ complete::be_u8(input)
+ }
+}
+
+/// Recognizes a big endian unsigned 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u16;
+///
+/// let parser = |s| {
+/// be_u16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u16;
+///
+/// let parser = |s| {
+/// be_u16::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0001)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn be_u16<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u16(input)
+ } else {
+ complete::be_u16(input)
+ }
+}
+
+/// Recognizes a big endian unsigned 3 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u24;
+///
+/// let parser = |s| {
+/// be_u24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u24;
+///
+/// let parser = |s| {
+/// be_u24::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x000102)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn be_u24<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u24(input)
+ } else {
+ complete::be_u24(input)
+ }
+}
+
+/// Recognizes a big endian unsigned 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u32;
+///
+/// let parser = |s| {
+/// be_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u32;
+///
+/// let parser = |s| {
+/// be_u32::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x00010203)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn be_u32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u32(input)
+ } else {
+ complete::be_u32(input)
+ }
+}
+
+/// Recognizes a big endian unsigned 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u64;
+///
+/// let parser = |s| {
+/// be_u64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u64;
+///
+/// let parser = |s| {
+/// be_u64::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0001020304050607)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn be_u64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u64(input)
+ } else {
+ complete::be_u64(input)
+ }
+}
+
+/// Recognizes a big endian unsigned 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_u128;
+///
+/// let parser = |s| {
+/// be_u128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_u128;
+///
+/// let parser = |s| {
+/// be_u128::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x00010203040506070809101112131415)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn be_u128<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_u128(input)
+ } else {
+ complete::be_u128(input)
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i8;
+///
+/// let parser = |s| {
+/// be_i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i8;
+///
+/// let parser = be_i8::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"\x01abcd"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn be_i8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i8(input)
+ } else {
+ complete::be_i8(input)
+ }
+}
+
+/// Recognizes a big endian signed 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i16;
+///
+/// let parser = |s| {
+/// be_i16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i16;
+///
+/// let parser = be_i16::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0001)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn be_i16<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i16(input)
+ } else {
+ complete::be_i16(input)
+ }
+}
+
+/// Recognizes a big endian signed 3 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i24;
+///
+/// let parser = |s| {
+/// be_i24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i24;
+///
+/// let parser = be_i24::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x000102)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn be_i24<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i24(input)
+ } else {
+ complete::be_i24(input)
+ }
+}
+
+/// Recognizes a big endian signed 4 bytes integer.
+///
+/// *Complete version*: Teturns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i32;
+///
+/// let parser = |s| {
+/// be_i32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i32;
+///
+/// let parser = be_i32::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x00010203)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(4))));
+/// ```
+#[inline(always)]
+pub fn be_i32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i32(input)
+ } else {
+ complete::be_i32(input)
+ }
+}
+
+/// Recognizes a big endian signed 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i64;
+///
+/// let parser = |s| {
+/// be_i64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i64;
+///
+/// let parser = be_i64::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0001020304050607)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn be_i64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i64(input)
+ } else {
+ complete::be_i64(input)
+ }
+}
+
+/// Recognizes a big endian signed 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_i128;
+///
+/// let parser = |s| {
+/// be_i128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_i128;
+///
+/// let parser = be_i128::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x00010203040506070809101112131415)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn be_i128<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_i128(input)
+ } else {
+ complete::be_i128(input)
+ }
+}
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u8;
+///
+/// let parser = |s| {
+/// le_u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u8;
+///
+/// let parser = le_u8::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"\x01abcd"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn le_u8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u8(input)
+ } else {
+ complete::le_u8(input)
+ }
+}
+
+/// Recognizes a little endian unsigned 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u16;
+///
+/// let parser = |s| {
+/// le_u16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u16;
+///
+/// let parser = |s| {
+/// le_u16::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn le_u16<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u16(input)
+ } else {
+ complete::le_u16(input)
+ }
+}
+
+/// Recognizes a little endian unsigned 3 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u24;
+///
+/// let parser = |s| {
+/// le_u24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u24;
+///
+/// let parser = |s| {
+/// le_u24::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn le_u24<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u24(input)
+ } else {
+ complete::le_u24(input)
+ }
+}
+
+/// Recognizes a little endian unsigned 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u32;
+///
+/// let parser = |s| {
+/// le_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u32;
+///
+/// let parser = |s| {
+/// le_u32::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x03020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn le_u32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u32(input)
+ } else {
+ complete::le_u32(input)
+ }
+}
+
+/// Recognizes a little endian unsigned 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u64;
+///
+/// let parser = |s| {
+/// le_u64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u64;
+///
+/// let parser = |s| {
+/// le_u64::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0706050403020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn le_u64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u64(input)
+ } else {
+ complete::le_u64(input)
+ }
+}
+
+/// Recognizes a little endian unsigned 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_u128;
+///
+/// let parser = |s| {
+/// le_u128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_u128;
+///
+/// let parser = |s| {
+/// le_u128::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x15141312111009080706050403020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn le_u128<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_u128(input)
+ } else {
+ complete::le_u128(input)
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i8;
+///
+/// let parser = |s| {
+/// le_i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i8;
+///
+/// let parser = le_i8::<_, (_, ErrorKind), true>;
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"\x01abcd"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn le_i8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i8(input)
+ } else {
+ complete::le_i8(input)
+ }
+}
+
+/// Recognizes a little endian signed 2 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i16;
+///
+/// let parser = |s| {
+/// le_i16(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i16;
+///
+/// let parser = |s| {
+/// le_i16::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn le_i16<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i16(input)
+ } else {
+ complete::le_i16(input)
+ }
+}
+
+/// Recognizes a little endian signed 3 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i24;
+///
+/// let parser = |s| {
+/// le_i24(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i24;
+///
+/// let parser = |s| {
+/// le_i24::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn le_i24<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i24(input)
+ } else {
+ complete::le_i24(input)
+ }
+}
+
+/// Recognizes a little endian signed 4 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i32;
+///
+/// let parser = |s| {
+/// le_i32(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i32;
+///
+/// let parser = |s| {
+/// le_i32::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x03020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn le_i32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i32(input)
+ } else {
+ complete::le_i32(input)
+ }
+}
+
+/// Recognizes a little endian signed 8 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i64;
+///
+/// let parser = |s| {
+/// le_i64(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i64;
+///
+/// let parser = |s| {
+/// le_i64::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x0706050403020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn le_i64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i64(input)
+ } else {
+ complete::le_i64(input)
+ }
+}
+
+/// Recognizes a little endian signed 16 bytes integer.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_i128;
+///
+/// let parser = |s| {
+/// le_i128(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_i128;
+///
+/// let parser = |s| {
+/// le_i128::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..])), Ok((Streaming(&b"abcd"[..]), 0x15141312111009080706050403020100)));
+/// assert_eq!(parser(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn le_i128<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_i128(input)
+ } else {
+ complete::le_i128(input)
+ }
+}
+
+/// Recognizes an unsigned 1 byte integer
+///
+/// **Note:** that endianness does not apply to 1 byte numbers.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u8;
+///
+/// let parser = |s| {
+/// u8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u8;
+///
+/// let parser = |s| {
+/// u8::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"\x03abcefg"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn u8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u8(input)
+ } else {
+ complete::u8(input)
+ }
+}
+
+/// Recognizes an unsigned 2 bytes integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u16 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u16;
+///
+/// let be_u16 = |s| {
+/// u16(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u16 = |s| {
+/// u16(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u16;
+///
+/// let be_u16 = |s| {
+/// u16::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u16(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0003)));
+/// assert_eq!(be_u16(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_u16 = |s| {
+/// u16::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u16(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0300)));
+/// assert_eq!(le_u16(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn u16<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u16(endian)
+ } else {
+ complete::u16(endian)
+ }
+}
+
+/// Recognizes an unsigned 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u24 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u24;
+///
+/// let be_u24 = |s| {
+/// u24(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u24 = |s| {
+/// u24(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u24;
+///
+/// let be_u24 = |s| {
+/// u24::<_,(_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u24(Streaming(&b"\x00\x03\x05abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x000305)));
+/// assert_eq!(be_u24(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+///
+/// let le_u24 = |s| {
+/// u24::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u24(Streaming(&b"\x00\x03\x05abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x050300)));
+/// assert_eq!(le_u24(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn u24<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u24(endian)
+ } else {
+ complete::u24(endian)
+ }
+}
+
+/// Recognizes an unsigned 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u32 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u32;
+///
+/// let be_u32 = |s| {
+/// u32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u32 = |s| {
+/// u32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u32;
+///
+/// let be_u32 = |s| {
+/// u32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u32(Streaming(&b"\x00\x03\x05\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x00030507)));
+/// assert_eq!(be_u32(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+///
+/// let le_u32 = |s| {
+/// u32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u32(Streaming(&b"\x00\x03\x05\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x07050300)));
+/// assert_eq!(le_u32(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn u32<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u32(endian)
+ } else {
+ complete::u32(endian)
+ }
+}
+
+/// Recognizes an unsigned 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u64 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u64;
+///
+/// let be_u64 = |s| {
+/// u64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u64 = |s| {
+/// u64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u64;
+///
+/// let be_u64 = |s| {
+/// u64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u64(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0001020304050607)));
+/// assert_eq!(be_u64(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+///
+/// let le_u64 = |s| {
+/// u64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u64(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0706050403020100)));
+/// assert_eq!(le_u64(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn u64<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u64(endian)
+ } else {
+ complete::u64(endian)
+ }
+}
+
+/// Recognizes an unsigned 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u128 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::u128;
+///
+/// let be_u128 = |s| {
+/// u128(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_u128 = |s| {
+/// u128(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::u128;
+///
+/// let be_u128 = |s| {
+/// u128::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u128(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x00010203040506070001020304050607)));
+/// assert_eq!(be_u128(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+///
+/// let le_u128 = |s| {
+/// u128::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u128(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x07060504030201000706050403020100)));
+/// assert_eq!(le_u128(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn u128<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::u128(endian)
+ } else {
+ complete::u128(endian)
+ }
+}
+
+/// Recognizes a signed 1 byte integer
+///
+/// **Note:** that endianness does not apply to 1 byte numbers.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i8;
+///
+/// let parser = |s| {
+/// i8(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error((&[][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i8;
+///
+/// let parser = |s| {
+/// i8::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"\x03abcefg"[..]), 0x00)));
+/// assert_eq!(parser(Streaming(&b""[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn i8<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i8(input)
+ } else {
+ complete::i8(input)
+ }
+}
+
+/// Recognizes a signed 2 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i16 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i16;
+///
+/// let be_i16 = |s| {
+/// i16(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i16 = |s| {
+/// i16(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i16;
+///
+/// let be_i16 = |s| {
+/// i16::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i16(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0003)));
+/// assert_eq!(be_i16(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_i16 = |s| {
+/// i16::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i16(Streaming(&b"\x00\x03abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0300)));
+/// assert_eq!(le_i16(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn i16<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i16(endian)
+ } else {
+ complete::i16(endian)
+ }
+}
+
+/// Recognizes a signed 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i24 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i24;
+///
+/// let be_i24 = |s| {
+/// i24(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i24 = |s| {
+/// i24(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i24;
+///
+/// let be_i24 = |s| {
+/// i24::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i24(Streaming(&b"\x00\x03\x05abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x000305)));
+/// assert_eq!(be_i24(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+///
+/// let le_i24 = |s| {
+/// i24::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i24(Streaming(&b"\x00\x03\x05abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x050300)));
+/// assert_eq!(le_i24(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline(always)]
+pub fn i24<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i24(endian)
+ } else {
+ complete::i24(endian)
+ }
+}
+
+/// Recognizes a signed 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i32 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i32;
+///
+/// let be_i32 = |s| {
+/// i32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i32 = |s| {
+/// i32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i32;
+///
+/// let be_i32 = |s| {
+/// i32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i32(Streaming(&b"\x00\x03\x05\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x00030507)));
+/// assert_eq!(be_i32(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+///
+/// let le_i32 = |s| {
+/// i32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i32(Streaming(&b"\x00\x03\x05\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x07050300)));
+/// assert_eq!(le_i32(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn i32<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i32(endian)
+ } else {
+ complete::i32(endian)
+ }
+}
+
+/// Recognizes a signed 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i64 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i64;
+///
+/// let be_i64 = |s| {
+/// i64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i64 = |s| {
+/// i64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i64;
+///
+/// let be_i64 = |s| {
+/// i64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i64(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0001020304050607)));
+/// assert_eq!(be_i64(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+///
+/// let le_i64 = |s| {
+/// i64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i64(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x0706050403020100)));
+/// assert_eq!(le_i64(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn i64<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i64(endian)
+ } else {
+ complete::i64(endian)
+ }
+}
+
+/// Recognizes a signed 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i128 integer.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::i128;
+///
+/// let be_i128 = |s| {
+/// i128(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+///
+/// let le_i128 = |s| {
+/// i128(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Error((&[0x01][..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::i128;
+///
+/// let be_i128 = |s| {
+/// i128::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i128(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x00010203040506070001020304050607)));
+/// assert_eq!(be_i128(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+///
+/// let le_i128 = |s| {
+/// i128::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i128(Streaming(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..])), Ok((Streaming(&b"abcefg"[..]), 0x07060504030201000706050403020100)));
+/// assert_eq!(le_i128(Streaming(&b"\x01"[..])), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline(always)]
+pub fn i128<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::i128(endian)
+ } else {
+ complete::i128(endian)
+ }
+}
+
+/// Recognizes a big endian 4 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_f32;
+///
+/// let parser = |s| {
+/// be_f32(s)
+/// };
+///
+/// assert_eq!(parser(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_f32;
+///
+/// let parser = |s| {
+/// be_f32::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&[0x40, 0x29, 0x00, 0x00][..])), Ok((Streaming(&b""[..]), 2.640625)));
+/// assert_eq!(parser(Streaming(&[0x01][..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn be_f32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_f32(input)
+ } else {
+ complete::be_f32(input)
+ }
+}
+
+/// Recognizes a big endian 8 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::be_f64;
+///
+/// let parser = |s| {
+/// be_f64(s)
+/// };
+///
+/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::be_f64;
+///
+/// let parser = |s| {
+/// be_f64::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(parser(Streaming(&[0x01][..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn be_f64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::be_f64(input)
+ } else {
+ complete::be_f64(input)
+ }
+}
+
+/// Recognizes a little endian 4 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_f32;
+///
+/// let parser = |s| {
+/// le_f32(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_f32;
+///
+/// let parser = |s| {
+/// le_f32::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&[0x00, 0x00, 0x48, 0x41][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(parser(Streaming(&[0x01][..])), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline(always)]
+pub fn le_f32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_f32(input)
+ } else {
+ complete::le_f32(input)
+ }
+}
+
+/// Recognizes a little endian 8 bytes floating point number.
+///
+/// *Complete version*: Returns an error if there is not enough input data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::le_f64;
+///
+/// let parser = |s| {
+/// le_f64(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::le_f64;
+///
+/// let parser = |s| {
+/// le_f64::<_, (_, ErrorKind), true>(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41][..])), Ok((Streaming(&b""[..]), 3145728.0)));
+/// assert_eq!(parser(Streaming(&[0x01][..])), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline(always)]
+pub fn le_f64<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::le_f64(input)
+ } else {
+ complete::le_f64(input)
+ }
+}
+
+/// Recognizes a 4 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f32 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f32 float.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::f32;
+///
+/// let be_f32 = |s| {
+/// f32(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+///
+/// let le_f32 = |s| {
+/// f32(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::f32;
+///
+/// let be_f32 = |s| {
+/// f32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f32(Streaming(&[0x41, 0x48, 0x00, 0x00][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(be_f32(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_f32 = |s| {
+/// f32::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f32(Streaming(&[0x00, 0x00, 0x48, 0x41][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(le_f32(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+pub fn f32<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::f32(endian)
+ } else {
+ complete::f32(endian)
+ }
+}
+
+/// Recognizes an 8 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f64 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f64 float.
+///
+/// *Complete version*: returns an error if there is not enough input data
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::f64;
+///
+/// let be_f64 = |s| {
+/// f64(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+///
+/// let le_f64 = |s| {
+/// f64(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Error((&b"abc"[..], ErrorKind::Eof))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// # use nom8::input::Streaming;
+/// use nom8::number::f64;
+///
+/// let be_f64 = |s| {
+/// f64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f64(Streaming(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(be_f64(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(5))));
+///
+/// let le_f64 = |s| {
+/// f64::<_, (_, ErrorKind), true>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..])), Ok((Streaming(&b""[..]), 12.5)));
+/// assert_eq!(le_f64(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(5))));
+/// ```
+#[inline(always)]
+pub fn f64<I, E: ParseError<I>, const STREAMING: bool>(
+ endian: crate::number::Endianness,
+) -> fn(I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<STREAMING>,
+{
+ if STREAMING {
+ streaming::f64(endian)
+ } else {
+ complete::f64(endian)
+ }
+}
+
+/// Recognizes a hex-encoded integer.
+///
+/// *Complete version*: Will parse until the end of input if it has less than 8 bytes.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// # Example
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::hex_u32;
+///
+/// let parser = |s| {
+/// hex_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"01AE"[..]), Ok((&b""[..], 0x01AE)));
+/// assert_eq!(parser(&b"abc"[..]), Ok((&b""[..], 0x0ABC)));
+/// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA))));
+/// ```
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::input::Streaming;
+/// use nom8::number::hex_u32;
+///
+/// let parser = |s| {
+/// hex_u32(s)
+/// };
+///
+/// assert_eq!(parser(Streaming(&b"01AE;"[..])), Ok((Streaming(&b";"[..]), 0x01AE)));
+/// assert_eq!(parser(Streaming(&b"abc"[..])), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(Streaming(&b"ggg"[..])), Err(Err::Error((Streaming(&b"ggg"[..]), ErrorKind::IsA))));
+/// ```
+#[inline(always)]
+pub fn hex_u32<I, E: ParseError<I>, const STREAMING: bool>(input: I) -> IResult<I, u32, E>
+where
+ I: InputTakeAtPosition + InputIsStreaming<STREAMING>,
+ I: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ <I as InputTakeAtPosition>::Item: AsChar,
+ I: AsBytes,
+ I: InputLength,
+{
+ if STREAMING {
+ streaming::hex_u32(input)
+ } else {
+ complete::hex_u32(input)
+ }
+}
diff --git a/vendor/nom8/src/number/streaming.rs b/vendor/nom8/src/number/streaming.rs
new file mode 100644
index 000000000..9d752aead
--- /dev/null
+++ b/vendor/nom8/src/number/streaming.rs
@@ -0,0 +1,2508 @@
+//! Parsers recognizing numbers, streaming version
+
+#![allow(deprecated)]
+
+use crate::branch::alt;
+use crate::bytes::streaming::tag;
+use crate::character::streaming::{char, digit1, sign};
+use crate::combinator::{cut, map, opt, recognize};
+use crate::error::{ErrorKind, ParseError};
+use crate::input::{
+ AsBytes, AsChar, Compare, InputIter, InputLength, InputTake, InputTakeAtPosition, IntoOutput,
+ Offset, Slice,
+};
+use crate::lib::std::ops::{RangeFrom, RangeTo};
+use crate::sequence::{pair, tuple};
+use crate::*;
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u8;
+///
+/// let parser = |s| {
+/// be_u8::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u8`][crate::number::be_u8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(1)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 2 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u16;
+///
+/// let parser = |s| {
+/// be_u16::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u16`][crate::number::be_u16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u16<I, E: ParseError<I>>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 2;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u16;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u16;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 3 byte integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u24;
+///
+/// let parser = |s| {
+/// be_u24::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u24`][crate::number::be_u24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u24<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 3;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u32;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u32;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 4 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u32;
+///
+/// let parser = |s| {
+/// be_u32::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u32`][crate::number::be_u32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 4;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u32;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u32;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 8 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u64;
+///
+/// let parser = |s| {
+/// be_u64::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u64`][crate::number::be_u64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u64<I, E: ParseError<I>>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 8;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u64;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u64;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a big endian unsigned 16 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_u128;
+///
+/// let parser = |s| {
+/// be_u128::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_u128`][crate::number::be_u128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_u128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 16;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u128;
+ for byte in input.iter_elements().take(bound) {
+ res = (res << 8) + byte as u128;
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i8;
+///
+/// let parser = be_i8::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i8`][crate::number::be_i8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i8<I, E: ParseError<I>>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u8.map(|x| x as i8).parse(input)
+}
+
+/// Recognizes a big endian signed 2 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i16;
+///
+/// let parser = be_i16::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0001)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i16`][crate::number::be_i16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i16<I, E: ParseError<I>>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u16.map(|x| x as i16).parse(input)
+}
+
+/// Recognizes a big endian signed 3 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i24;
+///
+/// let parser = be_i24::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x000102)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i24`][crate::number::be_i24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i24<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ // Same as the unsigned version but we need to sign-extend manually here
+ be_u24
+ .map(|x| {
+ if x & 0x80_00_00 != 0 {
+ (x | 0xff_00_00_00) as i32
+ } else {
+ x as i32
+ }
+ })
+ .parse(input)
+}
+
+/// Recognizes a big endian signed 4 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i32;
+///
+/// let parser = be_i32::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x00010203)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i32`][crate::number::be_i32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i32<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u32.map(|x| x as i32).parse(input)
+}
+
+/// Recognizes a big endian signed 8 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i64;
+///
+/// let parser = be_i64::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0001020304050607)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i64`][crate::number::be_i64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i64<I, E: ParseError<I>>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u64.map(|x| x as i64).parse(input)
+}
+
+/// Recognizes a big endian signed 16 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_i128;
+///
+/// let parser = be_i128::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x00010203040506070809101112131415)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_i128`][crate::number::be_i128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_i128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ be_u128.map(|x| x as i128).parse(input)
+}
+
+/// Recognizes an unsigned 1 byte integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u8;
+///
+/// let parser = le_u8::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u8`][crate::number::le_u8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(1)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 2 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u16;
+///
+/// let parser = |s| {
+/// le_u16::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u16`][crate::number::le_u16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u16<I, E: ParseError<I>>(input: I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 2;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u16;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u16) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 3 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u24;
+///
+/// let parser = |s| {
+/// le_u24::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u24`][crate::number::le_u24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u24<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 3;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u32;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u32) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 4 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u32;
+///
+/// let parser = |s| {
+/// le_u32::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u32`][crate::number::le_u32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 4;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u32;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u32) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 8 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u64;
+///
+/// let parser = |s| {
+/// le_u64::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u64`][crate::number::le_u64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u64<I, E: ParseError<I>>(input: I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 8;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u64;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u64) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a little endian unsigned 16 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_u128;
+///
+/// let parser = |s| {
+/// le_u128::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_u128`][crate::number::le_u128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_u128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_u128<I, E: ParseError<I>>(input: I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 16;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(bound - input.input_len())))
+ } else {
+ let mut res = 0u128;
+ for (index, byte) in input.iter_indices().take(bound) {
+ res += (byte as u128) << (8 * index);
+ }
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes a signed 1 byte integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i8;
+///
+/// let parser = le_i8::<_, (_, ErrorKind)>;
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"\x01abcd"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i8`][crate::number::le_i8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i8<I, E: ParseError<I>>(input: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u8.map(|x| x as i8).parse(input)
+}
+
+/// Recognizes a little endian signed 2 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i16;
+///
+/// let parser = |s| {
+/// le_i16::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01abcd"[..]), Ok((&b"abcd"[..], 0x0100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i16`][crate::number::le_i16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i16<I, E: ParseError<I>>(input: I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u16.map(|x| x as i16).parse(input)
+}
+
+/// Recognizes a little endian signed 3 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i24;
+///
+/// let parser = |s| {
+/// le_i24::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02abcd"[..]), Ok((&b"abcd"[..], 0x020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i24`][crate::number::le_i24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i24<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ // Same as the unsigned version but we need to sign-extend manually here
+ le_u24
+ .map(|x| {
+ if x & 0x80_00_00 != 0 {
+ (x | 0xff_00_00_00) as i32
+ } else {
+ x as i32
+ }
+ })
+ .parse(input)
+}
+
+/// Recognizes a little endian signed 4 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i32;
+///
+/// let parser = |s| {
+/// le_i32::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03abcd"[..]), Ok((&b"abcd"[..], 0x03020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i32`][crate::number::le_i32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i32<I, E: ParseError<I>>(input: I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u32.map(|x| x as i32).parse(input)
+}
+
+/// Recognizes a little endian signed 8 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i64;
+///
+/// let parser = |s| {
+/// le_i64::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcd"[..]), Ok((&b"abcd"[..], 0x0706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i64`][crate::number::le_i64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i64<I, E: ParseError<I>>(input: I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u64.map(|x| x as i64).parse(input)
+}
+
+/// Recognizes a little endian signed 16 bytes integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_i128;
+///
+/// let parser = |s| {
+/// le_i128::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x10\x11\x12\x13\x14\x15abcd"[..]), Ok((&b"abcd"[..], 0x15141312111009080706050403020100)));
+/// assert_eq!(parser(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_i128`][crate::number::le_i128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_i128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_i128<I, E: ParseError<I>>(input: I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ le_u128.map(|x| x as i128).parse(input)
+}
+
+/// Recognizes an unsigned 1 byte integer
+///
+/// Note that endianness does not apply to 1 byte numbers.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u8;
+///
+/// let parser = |s| {
+/// u8::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u8`][crate::number::u8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u8<I, E: ParseError<I>>(input: I) -> IResult<I, u8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ let bound: usize = 1;
+ if input.input_len() < bound {
+ Err(Err::Incomplete(Needed::new(1)))
+ } else {
+ let res = input.iter_elements().next().unwrap();
+
+ Ok((input.slice(bound..), res))
+ }
+}
+
+/// Recognizes an unsigned 2 bytes integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u16 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u16;
+///
+/// let be_u16 = |s| {
+/// u16::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_u16 = |s| {
+/// u16::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_u16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u16`][crate::number::u16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u16<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u16,
+ crate::number::Endianness::Little => le_u16,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u16,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u16,
+ }
+}
+
+/// Recognizes an unsigned 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u24 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u24;
+///
+/// let be_u24 = |s| {
+/// u24::<_,(_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+///
+/// let le_u24 = |s| {
+/// u24::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_u24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u24`][crate::number::u24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u24<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u24,
+ crate::number::Endianness::Little => le_u24,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u24,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u24,
+ }
+}
+
+/// Recognizes an unsigned 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u32 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u32;
+///
+/// let be_u32 = |s| {
+/// u32::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+///
+/// let le_u32 = |s| {
+/// u32::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_u32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u32`][crate::number::u32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u32,
+ crate::number::Endianness::Little => le_u32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u32,
+ }
+}
+
+/// Recognizes an unsigned 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u64 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u64;
+///
+/// let be_u64 = |s| {
+/// u64::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+///
+/// let le_u64 = |s| {
+/// u64::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_u64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u64`][crate::number::u64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u64,
+ crate::number::Endianness::Little => le_u64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u64,
+ }
+}
+
+/// Recognizes an unsigned 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian u128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian u128 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::u128;
+///
+/// let be_u128 = |s| {
+/// u128::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+///
+/// let le_u128 = |s| {
+/// u128::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_u128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_u128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::u128`][crate::number::u128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::u128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn u128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, u128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_u128,
+ crate::number::Endianness::Little => le_u128,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_u128,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_u128,
+ }
+}
+
+/// Recognizes a signed 1 byte integer
+///
+/// Note that endianness does not apply to 1 byte numbers.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i8;
+///
+/// let parser = |s| {
+/// i8::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&b"\x00\x03abcefg"[..]), Ok((&b"\x03abcefg"[..], 0x00)));
+/// assert_eq!(parser(&b""[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i8`][crate::number::i8] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i8` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i8<I, E: ParseError<I>>(i: I) -> IResult<I, i8, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ u8.map(|x| x as i8).parse(i)
+}
+
+/// Recognizes a signed 2 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i16 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i16 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i16;
+///
+/// let be_i16 = |s| {
+/// i16::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0003)));
+/// assert_eq!(be_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_i16 = |s| {
+/// i16::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i16(&b"\x00\x03abcefg"[..]), Ok((&b"abcefg"[..], 0x0300)));
+/// assert_eq!(le_i16(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i16`][crate::number::i16] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i16` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i16<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i16, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i16,
+ crate::number::Endianness::Little => le_i16,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i16,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i16,
+ }
+}
+
+/// Recognizes a signed 3 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i24 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i24 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i24;
+///
+/// let be_i24 = |s| {
+/// i24::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x000305)));
+/// assert_eq!(be_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+///
+/// let le_i24 = |s| {
+/// i24::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i24(&b"\x00\x03\x05abcefg"[..]), Ok((&b"abcefg"[..], 0x050300)));
+/// assert_eq!(le_i24(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(2))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i24`][crate::number::i24] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i24` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i24<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i24,
+ crate::number::Endianness::Little => le_i24,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i24,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i24,
+ }
+}
+
+/// Recognizes a signed 4 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i32 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i32 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i32;
+///
+/// let be_i32 = |s| {
+/// i32::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00030507)));
+/// assert_eq!(be_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+///
+/// let le_i32 = |s| {
+/// i32::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i32(&b"\x00\x03\x05\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07050300)));
+/// assert_eq!(le_i32(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i32`][crate::number::i32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i32,
+ crate::number::Endianness::Little => le_i32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i32,
+ }
+}
+
+/// Recognizes a signed 8 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i64 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i64 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i64;
+///
+/// let be_i64 = |s| {
+/// i64::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0001020304050607)));
+/// assert_eq!(be_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+///
+/// let le_i64 = |s| {
+/// i64::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i64(&b"\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x0706050403020100)));
+/// assert_eq!(le_i64(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i64`][crate::number::i64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i64,
+ crate::number::Endianness::Little => le_i64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i64,
+ }
+}
+
+/// Recognizes a signed 16 byte integer
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian i128 integer,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian i128 integer.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::i128;
+///
+/// let be_i128 = |s| {
+/// i128::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x00010203040506070001020304050607)));
+/// assert_eq!(be_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+///
+/// let le_i128 = |s| {
+/// i128::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_i128(&b"\x00\x01\x02\x03\x04\x05\x06\x07\x00\x01\x02\x03\x04\x05\x06\x07abcefg"[..]), Ok((&b"abcefg"[..], 0x07060504030201000706050403020100)));
+/// assert_eq!(le_i128(&b"\x01"[..]), Err(Err::Incomplete(Needed::new(15))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::i128`][crate::number::i128] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::i128` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn i128<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, i128, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_i128,
+ crate::number::Endianness::Little => le_i128,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_i128,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_i128,
+ }
+}
+
+/// Recognizes a big endian 4 bytes floating point number.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_f32;
+///
+/// let parser = |s| {
+/// be_f32::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00][..]), Ok((&b""[..], 2.640625)));
+/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_f32`][crate::number::be_f32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_f32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_f32<I, E: ParseError<I>>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match be_u32(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f32::from_bits(o))),
+ }
+}
+
+/// Recognizes a big endian 8 bytes floating point number.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::be_f64;
+///
+/// let parser = |s| {
+/// be_f64::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::be_f64`][crate::number::be_f64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::be_f64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn be_f64<I, E: ParseError<I>>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match be_u64(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f64::from_bits(o))),
+ }
+}
+
+/// Recognizes a little endian 4 bytes floating point number.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_f32;
+///
+/// let parser = |s| {
+/// le_f32::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(3))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_f32`][crate::number::le_f32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_f32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_f32<I, E: ParseError<I>>(input: I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match le_u32(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f32::from_bits(o))),
+ }
+}
+
+/// Recognizes a little endian 8 bytes floating point number.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::le_f64;
+///
+/// let parser = |s| {
+/// le_f64::<_, (_, ErrorKind)>(s)
+/// };
+///
+/// assert_eq!(parser(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 3145728.0)));
+/// assert_eq!(parser(&[0x01][..]), Err(Err::Incomplete(Needed::new(7))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::le_f64`][crate::number::le_f64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::le_f64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn le_f64<I, E: ParseError<I>>(input: I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match le_u64(input) {
+ Err(e) => Err(e),
+ Ok((i, o)) => Ok((i, f64::from_bits(o))),
+ }
+}
+
+/// Recognizes a 4 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f32 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f32 float.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::f32;
+///
+/// let be_f32 = |s| {
+/// f32::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f32(&[0x41, 0x48, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1))));
+///
+/// let le_f32 = |s| {
+/// f32::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f32(&[0x00, 0x00, 0x48, 0x41][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f32(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::f32`][crate::number::f32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::f32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn f32<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, f32, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_f32,
+ crate::number::Endianness::Little => le_f32,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_f32,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_f32,
+ }
+}
+
+/// Recognizes an 8 byte floating point number
+///
+/// If the parameter is `nom8::number::Endianness::Big`, parse a big endian f64 float,
+/// otherwise if `nom8::number::Endianness::Little` parse a little endian f64 float.
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::streaming::f64;
+///
+/// let be_f64 = |s| {
+/// f64::<_, (_, ErrorKind)>(nom8::number::Endianness::Big)(s)
+/// };
+///
+/// assert_eq!(be_f64(&[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(be_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5))));
+///
+/// let le_f64 = |s| {
+/// f64::<_, (_, ErrorKind)>(nom8::number::Endianness::Little)(s)
+/// };
+///
+/// assert_eq!(le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..]), Ok((&b""[..], 12.5)));
+/// assert_eq!(le_f64(&b"abc"[..]), Err(Err::Incomplete(Needed::new(5))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::f64`][crate::number::f64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::f64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn f64<I, E: ParseError<I>>(endian: crate::number::Endianness) -> fn(I) -> IResult<I, f64, E>
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength,
+{
+ match endian {
+ crate::number::Endianness::Big => be_f64,
+ crate::number::Endianness::Little => le_f64,
+ #[cfg(target_endian = "big")]
+ crate::number::Endianness::Native => be_f64,
+ #[cfg(target_endian = "little")]
+ crate::number::Endianness::Native => le_f64,
+ }
+}
+
+/// Recognizes a hex-encoded integer.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::hex_u32;
+///
+/// let parser = |s| {
+/// hex_u32(s)
+/// };
+///
+/// assert_eq!(parser(&b"01AE;"[..]), Ok((&b";"[..], 0x01AE)));
+/// assert_eq!(parser(&b"abc"[..]), Err(Err::Incomplete(Needed::new(1))));
+/// assert_eq!(parser(&b"ggg"[..]), Err(Err::Error((&b"ggg"[..], ErrorKind::IsA))));
+/// ```
+#[inline]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::number::hex_u32`][crate::number::hex_u32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::number::hex_u32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn hex_u32<I, E: ParseError<I>>(input: I) -> IResult<I, u32, E>
+where
+ I: InputTakeAtPosition,
+ I: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ <I as InputTakeAtPosition>::Item: AsChar,
+ I: AsBytes,
+ I: InputLength,
+{
+ let e: ErrorKind = ErrorKind::IsA;
+ let (i, o) = input.split_at_position1_streaming(
+ |c| {
+ let c = c.as_char();
+ !"0123456789abcdefABCDEF".contains(c)
+ },
+ e,
+ )?;
+
+ // Do not parse more than 8 characters for a u32
+ let (parsed, remaining) = if o.input_len() <= 8 {
+ (o, i)
+ } else {
+ (input.slice(..8), input.slice(8..))
+ };
+
+ let res = parsed
+ .as_bytes()
+ .iter()
+ .rev()
+ .enumerate()
+ .map(|(k, &v)| {
+ let digit = v as char;
+ digit.to_digit(16).unwrap_or(0) << (k * 4)
+ })
+ .sum();
+
+ Ok((remaining, res))
+}
+
+/// Recognizes a floating point number in text format and returns the corresponding part of the input.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if it reaches the end of input.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// use nom8::number::streaming::recognize_float;
+///
+/// let parser = |s| {
+/// recognize_float(s)
+/// };
+///
+/// assert_eq!(parser("11e-1;"), Ok((";", "11e-1")));
+/// assert_eq!(parser("123E-02;"), Ok((";", "123E-02")));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", "123")));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Char))));
+/// ```
+#[rustfmt::skip]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float`][crate::character::recognize_float] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(since = "8.0.0", note = "Replaced with `nom8::character::recognize_float` with input wrapped in `nom8::input::Streaming`")]
+pub fn recognize_float<T, E:ParseError<T>>(input: T) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition + InputLength,
+ <T as InputTakeAtPosition>::Item: AsChar
+{
+ recognize(
+ tuple((
+ opt(alt((char('+'), char('-')))),
+ alt((
+ map(tuple((digit1, opt(pair(char('.'), opt(digit1))))), |_| ()),
+ map(tuple((char('.'), digit1)), |_| ())
+ )),
+ opt(tuple((
+ alt((char('e'), char('E'))),
+ opt(alt((char('+'), char('-')))),
+ cut(digit1)
+ )))
+ ))
+ )(input)
+}
+
+// workaround until issues with minimal-lexical are fixed
+#[doc(hidden)]
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float_or_exceptions`][character::number::recognize_float_or_exceptions] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::recognize_float_or_exceptions` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn recognize_float_or_exceptions<T, E: ParseError<T>>(
+ input: T,
+) -> IResult<T, <T as IntoOutput>::Output, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputTake + InputLength + Compare<&'static str>,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+{
+ alt((
+ |i: T| {
+ recognize_float::<_, E>(i.clone()).map_err(|e| match e {
+ crate::Err::Error(_) => crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)),
+ crate::Err::Failure(_) => crate::Err::Failure(E::from_error_kind(i, ErrorKind::Float)),
+ crate::Err::Incomplete(needed) => crate::Err::Incomplete(needed),
+ })
+ },
+ |i: T| {
+ crate::bytes::streaming::tag_no_case::<_, _, E>("nan")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ |i: T| {
+ crate::bytes::streaming::tag_no_case::<_, _, E>("inf")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ |i: T| {
+ crate::bytes::streaming::tag_no_case::<_, _, E>("infinity")(i.clone())
+ .map_err(|_| crate::Err::Error(E::from_error_kind(i, ErrorKind::Float)))
+ },
+ ))(input)
+}
+
+/// Recognizes a floating point number in text format
+///
+/// It returns a tuple of (`sign`, `integer part`, `fraction part` and `exponent`) of the input
+/// data.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::recognize_float_parts`][crate::character::recognize_float_parts] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::recognize_float_parts` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn recognize_float_parts<T, E: ParseError<T>>(
+ input: T,
+) -> IResult<
+ T,
+ (
+ bool,
+ <T as IntoOutput>::Output,
+ <T as IntoOutput>::Output,
+ i32,
+ ),
+ E,
+>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter,
+ T: IntoOutput,
+ <T as InputIter>::Item: AsChar,
+ T: InputTakeAtPosition + InputTake + InputLength,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: for<'a> Compare<&'a [u8]>,
+ T: AsBytes,
+{
+ let (i, sign) = sign(input.clone())?;
+
+ //let (i, zeroes) = take_while(|c: <T as InputTakeAtPosition>::Item| c.as_char() == '0')(i)?;
+ let (i, zeroes) = match i.as_bytes().iter().position(|c| *c != b'0') {
+ Some(index) => i.take_split(index),
+ None => i.take_split(i.input_len()),
+ };
+
+ //let (i, mut integer) = digit0(i)?;
+ let (i, mut integer) = match i
+ .as_bytes()
+ .iter()
+ .position(|c| !(*c >= b'0' && *c <= b'9'))
+ {
+ Some(index) => i.take_split(index),
+ None => i.take_split(i.input_len()),
+ };
+
+ if integer.input_len() == 0 && zeroes.input_len() > 0 {
+ // keep the last zero if integer is empty
+ integer = zeroes.slice(zeroes.input_len() - 1..);
+ }
+
+ let (i, opt_dot) = opt(tag(&b"."[..]))(i)?;
+ let (i, fraction) = if opt_dot.is_none() {
+ let i2 = i.clone();
+ (i2, i.slice(..0))
+ } else {
+ // match number, trim right zeroes
+ let mut zero_count = 0usize;
+ let mut position = None;
+ for (pos, c) in i.as_bytes().iter().enumerate() {
+ if *c >= b'0' && *c <= b'9' {
+ if *c == b'0' {
+ zero_count += 1;
+ } else {
+ zero_count = 0;
+ }
+ } else {
+ position = Some(pos);
+ break;
+ }
+ }
+
+ let position = match position {
+ Some(p) => p,
+ None => return Err(Err::Incomplete(Needed::new(1))),
+ };
+
+ let index = if zero_count == 0 {
+ position
+ } else if zero_count == position {
+ position - zero_count + 1
+ } else {
+ position - zero_count
+ };
+
+ (i.slice(position..), i.slice(..index))
+ };
+
+ if integer.input_len() == 0 && fraction.input_len() == 0 {
+ return Err(Err::Error(E::from_error_kind(input, ErrorKind::Float)));
+ }
+
+ let i2 = i.clone();
+ let (i, e) = match i.as_bytes().iter().next() {
+ Some(b'e') => (i.slice(1..), true),
+ Some(b'E') => (i.slice(1..), true),
+ _ => (i, false),
+ };
+
+ let (i, exp) = if e {
+ cut(crate::character::streaming::i32)(i)?
+ } else {
+ (i2, 0)
+ };
+
+ Ok((
+ i,
+ (sign, integer.into_output(), fraction.into_output(), exp),
+ ))
+}
+
+/// Recognizes floating point number in text format and returns a f32.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::float;
+///
+/// let parser = |s| {
+/// float(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::f32`][crate::character::f32] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::f32` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn float<T, E: ParseError<T>>(input: T) -> IResult<T, f32, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputLength + InputTake + Compare<&'static str>,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: crate::input::ParseTo<f32>,
+ <T as InputIter>::Item: AsChar,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ use crate::input::ParseTo;
+
+ let (i, s) = recognize_float_or_exceptions(input)?;
+ match s.parse_to() {
+ Some(f) => Ok((i, f)),
+ None => Err(crate::Err::Error(E::from_error_kind(
+ i,
+ crate::error::ErrorKind::Float,
+ ))),
+ }
+}
+
+/// Recognizes floating point number in text format and returns a f64.
+///
+/// *Streaming version*: Will return `Err(nom8::Err::Incomplete(_))` if there is not enough data.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::number::complete::double;
+///
+/// let parser = |s| {
+/// double(s)
+/// };
+///
+/// assert_eq!(parser("11e-1"), Ok(("", 1.1)));
+/// assert_eq!(parser("123E-02"), Ok(("", 1.23)));
+/// assert_eq!(parser("123K-01"), Ok(("K-01", 123.0)));
+/// assert_eq!(parser("abc"), Err(Err::Error(("abc", ErrorKind::Float))));
+/// ```
+///
+/// **WARNING:** Deprecated, replaced with [`nom8::character::f64`][crate::character::f64] with input wrapped in [`nom8::input::Streaming`][crate::input::Streaming]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `nom8::character::f64` with input wrapped in `nom8::input::Streaming`"
+)]
+pub fn double<T, E: ParseError<T>>(input: T) -> IResult<T, f64, E>
+where
+ T: Slice<RangeFrom<usize>> + Slice<RangeTo<usize>>,
+ T: Clone + Offset,
+ T: InputIter + InputLength + InputTake + Compare<&'static str>,
+ T: IntoOutput,
+ <T as IntoOutput>::Output: crate::input::ParseTo<f64>,
+ <T as InputIter>::Item: AsChar,
+ <T as InputIter>::IterElem: Clone,
+ T: InputTakeAtPosition,
+ <T as InputTakeAtPosition>::Item: AsChar,
+ T: AsBytes,
+ T: for<'a> Compare<&'a [u8]>,
+{
+ use crate::input::ParseTo;
+
+ let (i, s) = recognize_float_or_exceptions(input)?;
+ match s.parse_to() {
+ Some(f) => Ok((i, f)),
+ None => Err(crate::Err::Error(E::from_error_kind(
+ i,
+ crate::error::ErrorKind::Float,
+ ))),
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::error::ErrorKind;
+ use crate::{Err, Needed};
+ use proptest::prelude::*;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn i8_tests() {
+ assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ assert_parse!(be_i8(&[][..]), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ fn i16_tests() {
+ assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16)));
+ assert_parse!(be_i16(&[][..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(be_i16(&[0x00][..]), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ fn u24_tests() {
+ assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ be_u24(&[0x12, 0x34, 0x56][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ assert_parse!(be_u24(&[][..]), Err(Err::Incomplete(Needed::new(3))));
+ assert_parse!(be_u24(&[0x00][..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ be_u24(&[0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i24_tests() {
+ assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ be_i24(&[0xED, 0xCB, 0xAA][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ assert_parse!(be_i24(&[][..]), Err(Err::Incomplete(Needed::new(3))));
+ assert_parse!(be_i24(&[0x00][..]), Err(Err::Incomplete(Needed::new(2))));
+ assert_parse!(
+ be_i24(&[0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i32_tests() {
+ assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ be_i32(&[0x7f, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ be_i32(&[0x80, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ assert_parse!(be_i32(&[][..]), Err(Err::Incomplete(Needed::new(4))));
+ assert_parse!(be_i32(&[0x00][..]), Err(Err::Incomplete(Needed::new(3))));
+ assert_parse!(
+ be_i32(&[0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i32(&[0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i64_tests() {
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ assert_parse!(be_i64(&[][..]), Err(Err::Incomplete(Needed::new(8))));
+ assert_parse!(be_i64(&[0x00][..]), Err(Err::Incomplete(Needed::new(7))));
+ assert_parse!(
+ be_i64(&[0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(6)))
+ );
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(5)))
+ );
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i128_tests() {
+ assert_parse!(
+ be_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ assert_parse!(be_i128(&[][..]), Err(Err::Incomplete(Needed::new(16))));
+ assert_parse!(be_i128(&[0x00][..]), Err(Err::Incomplete(Needed::new(15))));
+ assert_parse!(
+ be_i128(&[0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(14)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(13)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(12)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(11)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(10)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(9)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(8)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(7)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(6)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(5)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_parse!(
+ be_i128(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i128(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ ),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i128(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ [..]
+ ),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn le_i8_tests() {
+ assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn le_i16_tests() {
+ assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16)));
+ }
+
+ #[test]
+ fn le_u24_tests() {
+ assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ le_u24(&[0x56, 0x34, 0x12][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn le_i24_tests() {
+ assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ le_i24(&[0xAA, 0xCB, 0xED][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn le_i32_tests() {
+ assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ le_i32(&[0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ le_i32(&[0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn le_i64_tests() {
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn le_i128_tests() {
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn be_f32_tests() {
+ assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn be_f64_tests() {
+ assert_parse!(
+ be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn le_f32_tests() {
+ assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn le_f64_tests() {
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn hex_u32_tests() {
+ assert_parse!(
+ hex_u32(&b";"[..]),
+ Err(Err::Error(error_position!(&b";"[..], ErrorKind::IsA)))
+ );
+ assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255)));
+ assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138)));
+ assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347)));
+ assert_parse!(
+ hex_u32(&b"c5a31be201;"[..]),
+ Ok((&b"01;"[..], 3_315_801_058))
+ );
+ assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295)));
+ assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0)));
+ assert_parse!(hex_u32(&b"12af"[..]), Err(Err::Incomplete(Needed::new(1))));
+ }
+
+ #[test]
+ #[cfg(feature = "std")]
+ fn float_test() {
+ let mut test_cases = vec![
+ "+3.14",
+ "3.14",
+ "-3.14",
+ "0",
+ "0.0",
+ "1.",
+ ".789",
+ "-.5",
+ "1e7",
+ "-1E-7",
+ ".3e-2",
+ "1.e4",
+ "1.2e4",
+ "12.34",
+ "-1.234E-12",
+ "-1.234e-12",
+ "0.00000000000000000087",
+ ];
+
+ for test in test_cases.drain(..) {
+ let expected32 = str::parse::<f32>(test).unwrap();
+ let expected64 = str::parse::<f64>(test).unwrap();
+
+ println!("now parsing: {} -> {}", test, expected32);
+
+ let larger = format!("{};", test);
+ assert_parse!(recognize_float(&larger[..]), Ok((";", test)));
+
+ assert_parse!(float(larger.as_bytes()), Ok((&b";"[..], expected32)));
+ assert_parse!(float(&larger[..]), Ok((";", expected32)));
+
+ assert_parse!(double(larger.as_bytes()), Ok((&b";"[..], expected64)));
+ assert_parse!(double(&larger[..]), Ok((";", expected64)));
+ }
+
+ let remaining_exponent = "-1.234E-";
+ assert_parse!(
+ recognize_float(remaining_exponent),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+
+ let (_i, nan) = float::<_, ()>("NaN").unwrap();
+ assert!(nan.is_nan());
+
+ let (_i, inf) = float::<_, ()>("inf").unwrap();
+ assert!(inf.is_infinite());
+ let (_i, inf) = float::<_, ()>("infinite").unwrap();
+ assert!(inf.is_infinite());
+ }
+
+ #[test]
+ fn configurable_endianness() {
+ use crate::number::Endianness;
+
+ fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Big)(i)
+ }
+ fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
+ assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
+
+ fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Big)(i)
+ }
+ fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 302_014_464_u32))
+ );
+ assert_eq!(
+ le_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 6_291_474_u32))
+ );
+
+ fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Big)(i)
+ }
+ fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 1_297_142_246_100_992_000_u64))
+ );
+ assert_eq!(
+ le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_666_770_u64))
+ );
+
+ fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Big)(i)
+ }
+ fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
+ assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
+
+ fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Big)(i)
+ }
+ fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 1_204_224_i32))
+ );
+ assert_eq!(
+ le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 6_296_064_i32))
+ );
+
+ fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Big)(i)
+ }
+ fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 71_881_672_479_506_432_i64))
+ );
+ assert_eq!(
+ le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_732_032_i64))
+ );
+ }
+
+ #[cfg(feature = "std")]
+ fn parse_f64(i: &str) -> IResult<&str, f64, ()> {
+ use crate::input::ParseTo;
+ match recognize_float_or_exceptions(i) {
+ Err(e) => Err(e),
+ Ok((i, s)) => {
+ if s.is_empty() {
+ return Err(Err::Error(()));
+ }
+ match s.parse_to() {
+ Some(n) => Ok((i, n)),
+ None => Err(Err::Error(())),
+ }
+ }
+ }
+ }
+
+ proptest! {
+ #[test]
+ #[cfg(feature = "std")]
+ fn floats(s in "\\PC*") {
+ println!("testing {}", s);
+ let res1 = parse_f64(&s);
+ let res2 = double::<_, ()>(s.as_str());
+ assert_eq!(res1, res2);
+ }
+ }
+}
diff --git a/vendor/nom8/src/number/tests.rs b/vendor/nom8/src/number/tests.rs
new file mode 100644
index 000000000..bbcc3bd01
--- /dev/null
+++ b/vendor/nom8/src/number/tests.rs
@@ -0,0 +1,1096 @@
+use super::*;
+
+mod complete {
+ use super::*;
+ use crate::error::ErrorKind;
+ use crate::Err;
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn i8_tests() {
+ assert_parse!(i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn be_i8_tests() {
+ assert_parse!(be_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(be_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn be_i16_tests() {
+ assert_parse!(be_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_i16(&[0x7f, 0xff][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(be_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(be_i16(&[0x80, 0x00][..]), Ok((&b""[..], -32_768_i16)));
+ }
+
+ #[test]
+ fn be_u24_tests() {
+ assert_parse!(be_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(be_u24(&[0x00, 0xFF, 0xFF][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ be_u24(&[0x12, 0x34, 0x56][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn be_i24_tests() {
+ assert_parse!(be_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(be_i24(&[0xFF, 0x00, 0x00][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ be_i24(&[0xED, 0xCB, 0xAA][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn be_i32_tests() {
+ assert_parse!(be_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ be_i32(&[0x7f, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(be_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ be_i32(&[0x80, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn be_i64_tests() {
+ assert_parse!(
+ be_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i64(&[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ be_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i64(&[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn be_i128_tests() {
+ assert_parse!(
+ be_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ be_i128(
+ &[
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn le_i8_tests() {
+ assert_parse!(le_i8(&[0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i8(&[0x7f][..]), Ok((&b""[..], 127)));
+ assert_parse!(le_i8(&[0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i8(&[0x80][..]), Ok((&b""[..], -128)));
+ }
+
+ #[test]
+ fn le_i16_tests() {
+ assert_parse!(le_i16(&[0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_i16(&[0xff, 0x7f][..]), Ok((&b""[..], 32_767_i16)));
+ assert_parse!(le_i16(&[0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(le_i16(&[0x00, 0x80][..]), Ok((&b""[..], -32_768_i16)));
+ }
+
+ #[test]
+ fn le_u24_tests() {
+ assert_parse!(le_u24(&[0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(le_u24(&[0xFF, 0xFF, 0x00][..]), Ok((&b""[..], 65_535_u32)));
+ assert_parse!(
+ le_u24(&[0x56, 0x34, 0x12][..]),
+ Ok((&b""[..], 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn le_i24_tests() {
+ assert_parse!(le_i24(&[0xFF, 0xFF, 0xFF][..]), Ok((&b""[..], -1_i32)));
+ assert_parse!(le_i24(&[0x00, 0x00, 0xFF][..]), Ok((&b""[..], -65_536_i32)));
+ assert_parse!(
+ le_i24(&[0xAA, 0xCB, 0xED][..]),
+ Ok((&b""[..], -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn le_i32_tests() {
+ assert_parse!(le_i32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0)));
+ assert_parse!(
+ le_i32(&[0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 2_147_483_647_i32))
+ );
+ assert_parse!(le_i32(&[0xff, 0xff, 0xff, 0xff][..]), Ok((&b""[..], -1)));
+ assert_parse!(
+ le_i32(&[0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn le_i64_tests() {
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]),
+ Ok((&b""[..], 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ le_i64(&[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]),
+ Ok((&b""[..], -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn le_i128_tests() {
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ ),
+ Ok((&b""[..], 0))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ ),
+ Ok((&b""[..], -1))
+ );
+ assert_parse!(
+ le_i128(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80
+ ][..]
+ ),
+ Ok((
+ &b""[..],
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn be_f32_tests() {
+ assert_parse!(be_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ be_f32(&[0x4d, 0x31, 0x1f, 0xd8][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn be_f64_tests() {
+ assert_parse!(
+ be_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ be_f64(&[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn le_f32_tests() {
+ assert_parse!(le_f32(&[0x00, 0x00, 0x00, 0x00][..]), Ok((&b""[..], 0_f32)));
+ assert_parse!(
+ le_f32(&[0xd8, 0x1f, 0x31, 0x4d][..]),
+ Ok((&b""[..], 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn le_f64_tests() {
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]),
+ Ok((&b""[..], 0_f64))
+ );
+ assert_parse!(
+ le_f64(&[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]),
+ Ok((&b""[..], 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn hex_u32_tests() {
+ assert_parse!(
+ hex_u32(&b";"[..]),
+ Err(Err::Error(error_position!(&b";"[..], ErrorKind::IsA)))
+ );
+ assert_parse!(hex_u32(&b"ff;"[..]), Ok((&b";"[..], 255)));
+ assert_parse!(hex_u32(&b"1be2;"[..]), Ok((&b";"[..], 7138)));
+ assert_parse!(hex_u32(&b"c5a31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"C5A31be2;"[..]), Ok((&b";"[..], 3_315_801_058)));
+ assert_parse!(hex_u32(&b"00c5a31be2;"[..]), Ok((&b"e2;"[..], 12_952_347)));
+ assert_parse!(
+ hex_u32(&b"c5a31be201;"[..]),
+ Ok((&b"01;"[..], 3_315_801_058))
+ );
+ assert_parse!(hex_u32(&b"ffffffff;"[..]), Ok((&b";"[..], 4_294_967_295)));
+ assert_parse!(hex_u32(&b"0x1be2;"[..]), Ok((&b"x1be2;"[..], 0)));
+ assert_parse!(hex_u32(&b"12af"[..]), Ok((&b""[..], 0x12af)));
+ }
+
+ #[test]
+ fn configurable_endianness() {
+ use crate::number::Endianness;
+
+ fn be_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Big)(i)
+ }
+ fn le_tst16(i: &[u8]) -> IResult<&[u8], u16> {
+ u16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tst16(&[0x80, 0x00]), Ok((&b""[..], 32_768_u16)));
+ assert_eq!(le_tst16(&[0x80, 0x00]), Ok((&b""[..], 128_u16)));
+
+ fn be_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Big)(i)
+ }
+ fn le_tst32(i: &[u8]) -> IResult<&[u8], u32> {
+ u32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 302_014_464_u32))
+ );
+ assert_eq!(
+ le_tst32(&[0x12, 0x00, 0x60, 0x00]),
+ Ok((&b""[..], 6_291_474_u32))
+ );
+
+ fn be_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Big)(i)
+ }
+ fn le_tst64(i: &[u8]) -> IResult<&[u8], u64> {
+ u64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 1_297_142_246_100_992_000_u64))
+ );
+ assert_eq!(
+ le_tst64(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_666_770_u64))
+ );
+
+ fn be_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Big)(i)
+ }
+ fn le_tsti16(i: &[u8]) -> IResult<&[u8], i16> {
+ i16(Endianness::Little)(i)
+ }
+ assert_eq!(be_tsti16(&[0x00, 0x80]), Ok((&b""[..], 128_i16)));
+ assert_eq!(le_tsti16(&[0x00, 0x80]), Ok((&b""[..], -32_768_i16)));
+
+ fn be_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Big)(i)
+ }
+ fn le_tsti32(i: &[u8]) -> IResult<&[u8], i32> {
+ i32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 1_204_224_i32))
+ );
+ assert_eq!(
+ le_tsti32(&[0x00, 0x12, 0x60, 0x00]),
+ Ok((&b""[..], 6_296_064_i32))
+ );
+
+ fn be_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Big)(i)
+ }
+ fn le_tsti64(i: &[u8]) -> IResult<&[u8], i64> {
+ i64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 71_881_672_479_506_432_i64))
+ );
+ assert_eq!(
+ le_tsti64(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00]),
+ Ok((&b""[..], 36_028_874_334_732_032_i64))
+ );
+ }
+}
+
+mod streaming {
+ use super::*;
+ use crate::error::ErrorKind;
+ use crate::input::Streaming;
+ use crate::{Err, Needed};
+
+ macro_rules! assert_parse(
+ ($left: expr, $right: expr) => {
+ let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
+ assert_eq!(res, $right);
+ };
+ );
+
+ #[test]
+ fn i8_tests() {
+ assert_parse!(be_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0)));
+ assert_parse!(
+ be_i8(Streaming(&[0x7f][..])),
+ Ok((Streaming(&b""[..]), 127))
+ );
+ assert_parse!(be_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1)));
+ assert_parse!(
+ be_i8(Streaming(&[0x80][..])),
+ Ok((Streaming(&b""[..]), -128))
+ );
+ assert_parse!(
+ be_i8(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i16_tests() {
+ assert_parse!(
+ be_i16(Streaming(&[0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ be_i16(Streaming(&[0x7f, 0xff][..])),
+ Ok((Streaming(&b""[..]), 32_767_i16))
+ );
+ assert_parse!(
+ be_i16(Streaming(&[0xff, 0xff][..])),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ be_i16(Streaming(&[0x80, 0x00][..])),
+ Ok((Streaming(&b""[..]), -32_768_i16))
+ );
+ assert_parse!(
+ be_i16(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i16(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn u24_tests() {
+ assert_parse!(
+ be_u24(Streaming(&[0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ be_u24(Streaming(&[0x00, 0xFF, 0xFF][..])),
+ Ok((Streaming(&b""[..]), 65_535_u32))
+ );
+ assert_parse!(
+ be_u24(Streaming(&[0x12, 0x34, 0x56][..])),
+ Ok((Streaming(&b""[..]), 1_193_046_u32))
+ );
+ assert_parse!(
+ be_u24(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_u24(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_u24(Streaming(&[0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i24_tests() {
+ assert_parse!(
+ be_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])),
+ Ok((Streaming(&b""[..]), -1_i32))
+ );
+ assert_parse!(
+ be_i24(Streaming(&[0xFF, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), -65_536_i32))
+ );
+ assert_parse!(
+ be_i24(Streaming(&[0xED, 0xCB, 0xAA][..])),
+ Ok((Streaming(&b""[..]), -1_193_046_i32))
+ );
+ assert_parse!(
+ be_i24(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i24(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i24(Streaming(&[0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i32_tests() {
+ assert_parse!(
+ be_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0x7f, 0xff, 0xff, 0xff][..])),
+ Ok((Streaming(&b""[..]), 2_147_483_647_i32))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0x80, 0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), -2_147_483_648_i32))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i32(Streaming(&[0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i64_tests() {
+ assert_parse!(
+ be_i64(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ be_i64(Streaming(
+ &[0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]
+ )),
+ Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ be_i64(Streaming(
+ &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]
+ )),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ be_i64(Streaming(
+ &[0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(8)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(7)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(6)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(5)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i64(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn i128_tests() {
+ assert_parse!(
+ be_i128(Streaming(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ )),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[
+ 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ )),
+ Ok((
+ Streaming(&b""[..]),
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ )),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ )),
+ Ok((
+ Streaming(&b""[..]),
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[][..])),
+ Err(Err::Incomplete(Needed::new(16)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00][..])),
+ Err(Err::Incomplete(Needed::new(15)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(14)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(13)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(12)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(11)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(10)))
+ );
+ assert_parse!(
+ be_i128(Streaming(&[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..])),
+ Err(Err::Incomplete(Needed::new(9)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(8)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(7)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(6)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(5)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(4)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_parse!(
+ be_i128(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
+ [..]
+ )),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn le_i8_tests() {
+ assert_parse!(le_i8(Streaming(&[0x00][..])), Ok((Streaming(&b""[..]), 0)));
+ assert_parse!(
+ le_i8(Streaming(&[0x7f][..])),
+ Ok((Streaming(&b""[..]), 127))
+ );
+ assert_parse!(le_i8(Streaming(&[0xff][..])), Ok((Streaming(&b""[..]), -1)));
+ assert_parse!(
+ le_i8(Streaming(&[0x80][..])),
+ Ok((Streaming(&b""[..]), -128))
+ );
+ }
+
+ #[test]
+ fn le_i16_tests() {
+ assert_parse!(
+ le_i16(Streaming(&[0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ le_i16(Streaming(&[0xff, 0x7f][..])),
+ Ok((Streaming(&b""[..]), 32_767_i16))
+ );
+ assert_parse!(
+ le_i16(Streaming(&[0xff, 0xff][..])),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ le_i16(Streaming(&[0x00, 0x80][..])),
+ Ok((Streaming(&b""[..]), -32_768_i16))
+ );
+ }
+
+ #[test]
+ fn le_u24_tests() {
+ assert_parse!(
+ le_u24(Streaming(&[0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ le_u24(Streaming(&[0xFF, 0xFF, 0x00][..])),
+ Ok((Streaming(&b""[..]), 65_535_u32))
+ );
+ assert_parse!(
+ le_u24(Streaming(&[0x56, 0x34, 0x12][..])),
+ Ok((Streaming(&b""[..]), 1_193_046_u32))
+ );
+ }
+
+ #[test]
+ fn le_i24_tests() {
+ assert_parse!(
+ le_i24(Streaming(&[0xFF, 0xFF, 0xFF][..])),
+ Ok((Streaming(&b""[..]), -1_i32))
+ );
+ assert_parse!(
+ le_i24(Streaming(&[0x00, 0x00, 0xFF][..])),
+ Ok((Streaming(&b""[..]), -65_536_i32))
+ );
+ assert_parse!(
+ le_i24(Streaming(&[0xAA, 0xCB, 0xED][..])),
+ Ok((Streaming(&b""[..]), -1_193_046_i32))
+ );
+ }
+
+ #[test]
+ fn le_i32_tests() {
+ assert_parse!(
+ le_i32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ le_i32(Streaming(&[0xff, 0xff, 0xff, 0x7f][..])),
+ Ok((Streaming(&b""[..]), 2_147_483_647_i32))
+ );
+ assert_parse!(
+ le_i32(Streaming(&[0xff, 0xff, 0xff, 0xff][..])),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ le_i32(Streaming(&[0x00, 0x00, 0x00, 0x80][..])),
+ Ok((Streaming(&b""[..]), -2_147_483_648_i32))
+ );
+ }
+
+ #[test]
+ fn le_i64_tests() {
+ assert_parse!(
+ le_i64(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ le_i64(Streaming(
+ &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f][..]
+ )),
+ Ok((Streaming(&b""[..]), 9_223_372_036_854_775_807_i64))
+ );
+ assert_parse!(
+ le_i64(Streaming(
+ &[0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff][..]
+ )),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ le_i64(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80][..]
+ )),
+ Ok((Streaming(&b""[..]), -9_223_372_036_854_775_808_i64))
+ );
+ }
+
+ #[test]
+ fn le_i128_tests() {
+ assert_parse!(
+ le_i128(Streaming(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00
+ ][..]
+ )),
+ Ok((Streaming(&b""[..]), 0))
+ );
+ assert_parse!(
+ le_i128(Streaming(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x7f
+ ][..]
+ )),
+ Ok((
+ Streaming(&b""[..]),
+ 170_141_183_460_469_231_731_687_303_715_884_105_727_i128
+ ))
+ );
+ assert_parse!(
+ le_i128(Streaming(
+ &[
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff
+ ][..]
+ )),
+ Ok((Streaming(&b""[..]), -1))
+ );
+ assert_parse!(
+ le_i128(Streaming(
+ &[
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x80
+ ][..]
+ )),
+ Ok((
+ Streaming(&b""[..]),
+ -170_141_183_460_469_231_731_687_303_715_884_105_728_i128
+ ))
+ );
+ }
+
+ #[test]
+ fn be_f32_tests() {
+ assert_parse!(
+ be_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0_f32))
+ );
+ assert_parse!(
+ be_f32(Streaming(&[0x4d, 0x31, 0x1f, 0xd8][..])),
+ Ok((Streaming(&b""[..]), 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn be_f64_tests() {
+ assert_parse!(
+ be_f64(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), 0_f64))
+ );
+ assert_parse!(
+ be_f64(Streaming(
+ &[0x41, 0xa6, 0x23, 0xfb, 0x10, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn le_f32_tests() {
+ assert_parse!(
+ le_f32(Streaming(&[0x00, 0x00, 0x00, 0x00][..])),
+ Ok((Streaming(&b""[..]), 0_f32))
+ );
+ assert_parse!(
+ le_f32(Streaming(&[0xd8, 0x1f, 0x31, 0x4d][..])),
+ Ok((Streaming(&b""[..]), 185_728_392_f32))
+ );
+ }
+
+ #[test]
+ fn le_f64_tests() {
+ assert_parse!(
+ le_f64(Streaming(
+ &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..]
+ )),
+ Ok((Streaming(&b""[..]), 0_f64))
+ );
+ assert_parse!(
+ le_f64(Streaming(
+ &[0x00, 0x00, 0x00, 0x10, 0xfb, 0x23, 0xa6, 0x41][..]
+ )),
+ Ok((Streaming(&b""[..]), 185_728_392_f64))
+ );
+ }
+
+ #[test]
+ fn hex_u32_tests() {
+ assert_parse!(
+ hex_u32(Streaming(&b";"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b";"[..]),
+ ErrorKind::IsA
+ )))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"ff;"[..])),
+ Ok((Streaming(&b";"[..]), 255))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"1be2;"[..])),
+ Ok((Streaming(&b";"[..]), 7138))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"c5a31be2;"[..])),
+ Ok((Streaming(&b";"[..]), 3_315_801_058))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"C5A31be2;"[..])),
+ Ok((Streaming(&b";"[..]), 3_315_801_058))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"00c5a31be2;"[..])),
+ Ok((Streaming(&b"e2;"[..]), 12_952_347))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"c5a31be201;"[..])),
+ Ok((Streaming(&b"01;"[..]), 3_315_801_058))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"ffffffff;"[..])),
+ Ok((Streaming(&b";"[..]), 4_294_967_295))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"0x1be2;"[..])),
+ Ok((Streaming(&b"x1be2;"[..]), 0))
+ );
+ assert_parse!(
+ hex_u32(Streaming(&b"12af"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ }
+
+ #[test]
+ fn configurable_endianness() {
+ use crate::number::Endianness;
+
+ fn be_tst16(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u16> {
+ u16(Endianness::Big)(i)
+ }
+ fn le_tst16(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u16> {
+ u16(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst16(Streaming(&[0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 32_768_u16))
+ );
+ assert_eq!(
+ le_tst16(Streaming(&[0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 128_u16))
+ );
+
+ fn be_tst32(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u32> {
+ u32(Endianness::Big)(i)
+ }
+ fn le_tst32(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u32> {
+ u32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])),
+ Ok((Streaming(&b""[..]), 302_014_464_u32))
+ );
+ assert_eq!(
+ le_tst32(Streaming(&[0x12, 0x00, 0x60, 0x00])),
+ Ok((Streaming(&b""[..]), 6_291_474_u32))
+ );
+
+ fn be_tst64(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u64> {
+ u64(Endianness::Big)(i)
+ }
+ fn le_tst64(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, u64> {
+ u64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 1_297_142_246_100_992_000_u64))
+ );
+ assert_eq!(
+ le_tst64(Streaming(&[0x12, 0x00, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 36_028_874_334_666_770_u64))
+ );
+
+ fn be_tsti16(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i16> {
+ i16(Endianness::Big)(i)
+ }
+ fn le_tsti16(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i16> {
+ i16(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti16(Streaming(&[0x00, 0x80])),
+ Ok((Streaming(&b""[..]), 128_i16))
+ );
+ assert_eq!(
+ le_tsti16(Streaming(&[0x00, 0x80])),
+ Ok((Streaming(&b""[..]), -32_768_i16))
+ );
+
+ fn be_tsti32(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i32> {
+ i32(Endianness::Big)(i)
+ }
+ fn le_tsti32(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i32> {
+ i32(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])),
+ Ok((Streaming(&b""[..]), 1_204_224_i32))
+ );
+ assert_eq!(
+ le_tsti32(Streaming(&[0x00, 0x12, 0x60, 0x00])),
+ Ok((Streaming(&b""[..]), 6_296_064_i32))
+ );
+
+ fn be_tsti64(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i64> {
+ i64(Endianness::Big)(i)
+ }
+ fn le_tsti64(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i64> {
+ i64(Endianness::Little)(i)
+ }
+ assert_eq!(
+ be_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 71_881_672_479_506_432_i64))
+ );
+ assert_eq!(
+ le_tsti64(Streaming(&[0x00, 0xFF, 0x60, 0x00, 0x12, 0x00, 0x80, 0x00])),
+ Ok((Streaming(&b""[..]), 36_028_874_334_732_032_i64))
+ );
+ }
+}
diff --git a/vendor/nom8/src/parser.rs b/vendor/nom8/src/parser.rs
new file mode 100644
index 000000000..e6a197228
--- /dev/null
+++ b/vendor/nom8/src/parser.rs
@@ -0,0 +1,1159 @@
+//! Basic types to build the parsers
+
+use self::Needed::*;
+use crate::combinator::*;
+#[cfg(feature = "std")]
+use crate::error::DbgErr;
+use crate::error::{self, Context, ContextError, ErrorKind, ParseError};
+use crate::input::InputIsStreaming;
+use crate::input::*;
+use crate::lib::std::fmt;
+use crate::lib::std::ops::RangeFrom;
+use core::num::NonZeroUsize;
+
+/// Holds the result of parsing functions
+///
+/// It depends on the input type `I`, the output type `O`, and the error type `E`
+/// (by default `(I, nom8::ErrorKind)`)
+///
+/// The `Ok` side is a pair containing the remainder of the input (the part of the data that
+/// was not parsed) and the produced value. The `Err` side contains an instance of `nom8::Err`.
+///
+/// Outside of the parsing code, you can use the [`FinishIResult::finish`] method to convert
+/// it to a more common result type
+pub type IResult<I, O, E = error::Error<I>> = Result<(I, O), Err<E>>;
+
+/// Extension trait to convert a parser's [`IResult`] to a more manageable type
+pub trait FinishIResult<I, O, E> {
+ /// Converts the parser's [`IResult`] to a type that is more consumable by callers.
+ ///
+ /// Errors if the parser is not at the [end of input][crate::combinator::eof]. See
+ /// [`FinishIResult::finish_err`] if the remaining input is needed.
+ ///
+ /// # Panic
+ ///
+ /// If the result is `Err(Err::Incomplete(_))`, this method will panic.
+ /// - "complete" parsers: It will not be an issue, `Incomplete` is never used
+ /// - "streaming" parsers: `Incomplete` will be returned if there's not enough data
+ /// for the parser to decide, and you should gather more data before parsing again.
+ /// Once the parser returns either `Ok(_)`, `Err(Err::Error(_))` or `Err(Err::Failure(_))`,
+ /// you can get out of the parsing loop and call `finish_err()` on the parser's result
+ fn finish(self) -> Result<O, E>;
+
+ /// Converts the parser's [`IResult`] to a type that is more consumable by errors.
+ ///
+ /// It keeps the same `Ok` branch, and merges `Err::Error` and `Err::Failure` into the `Err`
+ /// side.
+ ///
+ /// # Panic
+ ///
+ /// If the result is `Err(Err::Incomplete(_))`, this method will panic as [`Err::Incomplete`]
+ /// should only be set when the input is [`InputIsStreaming<false>`] which this isn't implemented
+ /// for.
+ fn finish_err(self) -> Result<(I, O), E>;
+}
+
+impl<I, O, E> FinishIResult<I, O, E> for IResult<I, O, E>
+where
+ I: crate::input::InputLength,
+ I: crate::input::IntoOutput,
+ // Force users to deal with `Incomplete` when `InputIsStreaming<true>`
+ I: InputIsStreaming<false>,
+ I: Clone,
+ E: crate::error::ParseError<I>,
+{
+ fn finish(self) -> Result<O, E> {
+ let (i, o) = self.finish_err()?;
+ crate::combinator::eof(i).finish_err()?;
+ Ok(o)
+ }
+
+ fn finish_err(self) -> Result<(I, O), E> {
+ match self {
+ Ok(res) => Ok(res),
+ Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
+ Err(Err::Incomplete(_)) => {
+ panic!("`InputIsStreaming<false>` conflicts with `Err(Err::Incomplete(_))`")
+ }
+ }
+ }
+}
+
+#[doc(hidden)]
+#[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `FinishIResult` which is available via `nom8::prelude`"
+)]
+pub trait Finish<I, O, E> {
+ #[deprecated(
+ since = "8.0.0",
+ note = "Replaced with `FinishIResult::finish_err` which is available via `nom8::prelude`"
+ )]
+ fn finish(self) -> Result<(I, O), E>;
+}
+
+#[allow(deprecated)]
+impl<I, O, E> Finish<I, O, E> for IResult<I, O, E> {
+ fn finish(self) -> Result<(I, O), E> {
+ match self {
+ Ok(res) => Ok(res),
+ Err(Err::Error(e)) | Err(Err::Failure(e)) => Err(e),
+ Err(Err::Incomplete(_)) => {
+ panic!("Cannot call `finish()` on `Err(Err::Incomplete(_))`: this result means that the parser does not have enough data to decide, you should gather more data and try to reapply the parser instead")
+ }
+ }
+ }
+}
+
+/// Convert an `Input` into an appropriate `Output` type
+pub trait IntoOutputIResult<I, O, E> {
+ /// Convert an `Input` into an appropriate `Output` type
+ fn into_output(self) -> IResult<I, O, E>;
+}
+
+impl<I, E> IntoOutputIResult<I, <I as crate::input::IntoOutput>::Output, E> for IResult<I, I, E>
+where
+ I: crate::input::IntoOutput,
+{
+ fn into_output(self) -> IResult<I, <I as crate::input::IntoOutput>::Output, E> {
+ self.map(|(i, o)| (i, o.into_output()))
+ }
+}
+
+/// Contains information on needed data if a parser returned `Incomplete`
+///
+/// **Note:** This is only possible for `Input` types that implement [`InputIsStreaming<true>`],
+/// like [`Streaming`][crate::input::Streaming].
+#[derive(Debug, PartialEq, Eq, Clone, Copy)]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub enum Needed {
+ /// Needs more data, but we do not know how much
+ Unknown,
+ /// Contains the required data size in bytes
+ Size(NonZeroUsize),
+}
+
+impl Needed {
+ /// Creates `Needed` instance, returns `Needed::Unknown` if the argument is zero
+ pub fn new(s: usize) -> Self {
+ match NonZeroUsize::new(s) {
+ Some(sz) => Needed::Size(sz),
+ None => Needed::Unknown,
+ }
+ }
+
+ /// Indicates if we know how many bytes we need
+ pub fn is_known(&self) -> bool {
+ *self != Unknown
+ }
+
+ /// Maps a `Needed` to `Needed` by applying a function to a contained `Size` value.
+ #[inline]
+ pub fn map<F: Fn(NonZeroUsize) -> usize>(self, f: F) -> Needed {
+ match self {
+ Unknown => Unknown,
+ Size(n) => Needed::new(f(n)),
+ }
+ }
+}
+
+/// The `Err` enum indicates the parser was not successful
+///
+/// It has three cases:
+///
+/// * `Incomplete` indicates that more data is needed to decide. The [`Needed`] enum
+/// can contain how many additional bytes are necessary. If you are sure your parser
+/// is working on full data, you can wrap your parser with the `complete` combinator
+/// to transform that case in `Error`
+/// * `Error` means some parser did not succeed, but another one might (as an example,
+/// when testing different branches of an `alt` combinator)
+/// * `Failure` indicates an unrecoverable error. As an example, if you recognize a prefix
+/// to decide on the next parser to apply, and that parser fails, you know there's no need
+/// to try other parsers, you were already in the right branch, so the data is invalid
+///
+#[derive(Debug, Clone, PartialEq)]
+#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
+pub enum Err<E> {
+ /// There was not enough data
+ ///
+ /// This must only be set when the `Input` is [`InputIsStreaming<true>`], like with
+ /// [`Streaming`][crate::input::Streaming]
+ ///
+ /// Convert this into an `Error` with [`Parser::complete`][Parser::complete]
+ Incomplete(Needed),
+ /// The parser had an error (recoverable)
+ Error(E),
+ /// The parser had an unrecoverable error: we got to the right
+ /// branch and we know other branches won't work, so backtrack
+ /// as fast as possible
+ Failure(E),
+}
+
+impl<E> Err<E> {
+ /// Tests if the result is Incomplete
+ pub fn is_incomplete(&self) -> bool {
+ if let Err::Incomplete(_) = self {
+ true
+ } else {
+ false
+ }
+ }
+
+ /// Applies the given function to the inner error
+ pub fn map<E2, F>(self, f: F) -> Err<E2>
+ where
+ F: FnOnce(E) -> E2,
+ {
+ match self {
+ Err::Incomplete(n) => Err::Incomplete(n),
+ Err::Failure(t) => Err::Failure(f(t)),
+ Err::Error(t) => Err::Error(f(t)),
+ }
+ }
+
+ /// Automatically converts between errors if the underlying type supports it
+ pub fn convert<F>(e: Err<F>) -> Self
+ where
+ E: From<F>,
+ {
+ e.map(crate::lib::std::convert::Into::into)
+ }
+}
+
+impl<T> Err<(T, ErrorKind)> {
+ /// Maps `Err<(T, ErrorKind)>` to `Err<(U, ErrorKind)>` with the given `F: T -> U`
+ pub fn map_input<U, F>(self, f: F) -> Err<(U, ErrorKind)>
+ where
+ F: FnOnce(T) -> U,
+ {
+ match self {
+ Err::Incomplete(n) => Err::Incomplete(n),
+ Err::Failure((input, k)) => Err::Failure((f(input), k)),
+ Err::Error((input, k)) => Err::Error((f(input), k)),
+ }
+ }
+}
+
+impl<T> Err<error::Error<T>> {
+ /// Maps `Err<error::Error<T>>` to `Err<error::Error<U>>` with the given `F: T -> U`
+ pub fn map_input<U, F>(self, f: F) -> Err<error::Error<U>>
+ where
+ F: FnOnce(T) -> U,
+ {
+ match self {
+ Err::Incomplete(n) => Err::Incomplete(n),
+ Err::Failure(error::Error { input, code }) => Err::Failure(error::Error {
+ input: f(input),
+ code,
+ }),
+ Err::Error(error::Error { input, code }) => Err::Error(error::Error {
+ input: f(input),
+ code,
+ }),
+ }
+ }
+}
+
+#[cfg(feature = "alloc")]
+use crate::lib::std::{borrow::ToOwned, string::String, vec::Vec};
+impl Err<(&[u8], ErrorKind)> {
+ /// Obtaining ownership
+ #[cfg(feature = "alloc")]
+ pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+impl Err<(&str, ErrorKind)> {
+ /// Obtaining ownership
+ #[cfg(feature = "alloc")]
+ pub fn to_owned(self) -> Err<(String, ErrorKind)> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+impl Err<error::Error<&[u8]>> {
+ /// Obtaining ownership
+ #[cfg(feature = "alloc")]
+ pub fn to_owned(self) -> Err<error::Error<Vec<u8>>> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+impl Err<error::Error<&str>> {
+ /// Obtaining ownership
+ #[cfg(feature = "alloc")]
+ pub fn to_owned(self) -> Err<error::Error<String>> {
+ self.map_input(ToOwned::to_owned)
+ }
+}
+
+impl<E: Eq> Eq for Err<E> {}
+
+impl<E> fmt::Display for Err<E>
+where
+ E: fmt::Debug,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Err::Incomplete(Needed::Size(u)) => write!(f, "Parsing requires {} bytes/chars", u),
+ Err::Incomplete(Needed::Unknown) => write!(f, "Parsing requires more data"),
+ Err::Failure(c) => write!(f, "Parsing Failure: {:?}", c),
+ Err::Error(c) => write!(f, "Parsing Error: {:?}", c),
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+use std::error::Error;
+
+#[cfg(feature = "std")]
+impl<E> Error for Err<E>
+where
+ E: fmt::Debug,
+{
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ None // no underlying error
+ }
+}
+
+/// All nom parsers implement this trait
+///
+/// The simplest way to implement a `Parser` is with a function
+/// ```rust
+/// use nom8::prelude::*;
+///
+/// fn success(input: &str) -> IResult<&str, ()> {
+/// let output = ();
+/// Ok((input, output))
+/// }
+///
+/// let (input, output) = success.parse("Hello").unwrap();
+/// assert_eq!(input, "Hello"); // We didn't consume any input
+/// ```
+///
+/// which can be made stateful by returning a function
+/// ```rust
+/// use nom8::prelude::*;
+///
+/// fn success<O: Clone>(output: O) -> impl FnMut(&str) -> IResult<&str, O> {
+/// move |input: &str| {
+/// let output = output.clone();
+/// Ok((input, output))
+/// }
+/// }
+///
+/// let (input, output) = success("World").parse("Hello").unwrap();
+/// assert_eq!(input, "Hello"); // We didn't consume any input
+/// assert_eq!(output, "World");
+/// ```
+///
+/// Additionally, some basic types implement `Parser` as well, including
+/// - `u8` and `char`, see [`nom8::character::char`][crate::bytes::one_of]
+/// - `&[u8]` and `&str`, see [`nom8::character::char`][crate::bytes::tag]
+pub trait Parser<I, O, E> {
+ /// A parser takes in input type, and returns a `Result` containing
+ /// either the remaining input and the output value, or an error
+ fn parse(&mut self, input: I) -> IResult<I, O, E>;
+
+ /// Treat `&mut Self` as a parser
+ ///
+ /// This helps when needing to move a `Parser` when all you have is a `&mut Parser`.
+ ///
+ /// # Example
+ ///
+ /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f`
+ /// into [`length_data`][crate::multi::length_data] and `g` into
+ /// [`complete`][Parser::complete]:
+ /// ```rust,compile_fail
+ /// # use nom8::prelude::*;
+ /// # use nom8::IResult;
+ /// # use nom8::Parser;
+ /// # use nom8::error::ParseError;
+ /// # use nom8::multi::length_data;
+ /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>(
+ /// mut f: impl Parser<&'i [u8], usize, E>,
+ /// mut g: impl Parser<&'i [u8], O, E>
+ /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> {
+ /// move |i: &'i [u8]| {
+ /// let (i, data) = length_data(f).parse(i)?;
+ /// let (_, o) = g.complete().parse(data)?;
+ /// Ok((i, o))
+ /// }
+ /// }
+ /// ```
+ ///
+ /// By adding `by_ref`, we can make this work:
+ /// ```rust
+ /// # use nom8::prelude::*;
+ /// # use nom8::IResult;
+ /// # use nom8::Parser;
+ /// # use nom8::error::ParseError;
+ /// # use nom8::multi::length_data;
+ /// pub fn length_value<'i, O, E: ParseError<&'i [u8]>>(
+ /// mut f: impl Parser<&'i [u8], usize, E>,
+ /// mut g: impl Parser<&'i [u8], O, E>
+ /// ) -> impl FnMut(&'i [u8]) -> IResult<&'i [u8], O, E> {
+ /// move |i: &'i [u8]| {
+ /// let (i, data) = length_data(f.by_ref()).parse(i)?;
+ /// let (_, o) = g.by_ref().complete().parse(data)?;
+ /// Ok((i, o))
+ /// }
+ /// }
+ /// ```
+ fn by_ref(&mut self) -> ByRef<Self>
+ where
+ Self: core::marker::Sized,
+ {
+ ByRef::new(self)
+ }
+ /// Returns the provided value if the child parser succeeds.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::character::alpha1;
+ /// # fn main() {
+ ///
+ /// let mut parser = alpha1.value(1234);
+ ///
+ /// assert_eq!(parser.parse("abcd"), Ok(("", 1234)));
+ /// assert_eq!(parser.parse("123abcd;"), Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
+ /// # }
+ /// ```
+ fn value<O2>(self, val: O2) -> Value<Self, O, O2>
+ where
+ Self: core::marker::Sized,
+ O2: Clone,
+ {
+ Value::new(self, val)
+ }
+
+ /// Convert the parser's output to another type using [`std::convert::From`]
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::IResult;
+ /// # use nom8::Parser;
+ /// use nom8::character::alpha1;
+ /// # fn main() {
+ ///
+ /// fn parser1(i: &str) -> IResult<&str, &str> {
+ /// alpha1(i)
+ /// }
+ ///
+ /// let mut parser2 = parser1.output_into();
+ ///
+ /// // the parser converts the &str output of the child parser into a Vec<u8>
+ /// let bytes: IResult<&str, Vec<u8>> = parser2.parse("abcd");
+ /// assert_eq!(bytes, Ok(("", vec![97, 98, 99, 100])));
+ /// # }
+ /// ```
+ fn output_into<O2: From<O>>(self) -> OutputInto<Self, O, O2>
+ where
+ Self: core::marker::Sized,
+ {
+ OutputInto::new(self)
+ }
+
+ /// If the child parser was successful, return the consumed input as produced value.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::character::{alpha1};
+ /// use nom8::sequence::separated_pair;
+ /// # fn main() {
+ ///
+ /// let mut parser = separated_pair(alpha1, ',', alpha1).recognize();
+ ///
+ /// assert_eq!(parser.parse("abcd,efgh"), Ok(("", "abcd,efgh")));
+ /// assert_eq!(parser.parse("abcd;"),Err(Err::Error((";", ErrorKind::OneOf))));
+ /// # }
+ /// ```
+ fn recognize(self) -> Recognize<Self, O>
+ where
+ Self: core::marker::Sized,
+ {
+ Recognize::new(self)
+ }
+
+ /// if the child parser was successful, return the consumed input with the output
+ /// as a tuple. Functions similarly to [recognize](fn.recognize.html) except it
+ /// returns the parser output as well.
+ ///
+ /// This can be useful especially in cases where the output is not the same type
+ /// as the input, or the input is a user defined type.
+ ///
+ /// Returned tuple is of the format `(produced output, consumed input)`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::prelude::*;
+ /// # use nom8::{Err,error::ErrorKind, IResult};
+ /// use nom8::character::{alpha1};
+ /// use nom8::bytes::tag;
+ /// use nom8::sequence::separated_pair;
+ ///
+ /// fn inner_parser(input: &str) -> IResult<&str, bool> {
+ /// tag("1234").value(true).parse(input)
+ /// }
+ ///
+ /// # fn main() {
+ ///
+ /// let mut consumed_parser = separated_pair(alpha1, ',', alpha1).value(true).with_recognized();
+ ///
+ /// assert_eq!(consumed_parser.parse("abcd,efgh1"), Ok(("1", (true, "abcd,efgh"))));
+ /// assert_eq!(consumed_parser.parse("abcd;"),Err(Err::Error((";", ErrorKind::OneOf))));
+ ///
+ /// // the second output (representing the consumed input)
+ /// // should be the same as that of the `recognize` parser.
+ /// let mut recognize_parser = inner_parser.recognize();
+ /// let mut consumed_parser = inner_parser.with_recognized().map(|(output, consumed)| consumed);
+ ///
+ /// assert_eq!(recognize_parser.parse("1234"), consumed_parser.parse("1234"));
+ /// assert_eq!(recognize_parser.parse("abcd"), consumed_parser.parse("abcd"));
+ /// # }
+ /// ```
+ fn with_recognized(self) -> WithRecognized<Self, O>
+ where
+ Self: core::marker::Sized,
+ {
+ WithRecognized::new(self)
+ }
+
+ /// If the child parser was successful, return the location of the consumed input as produced value.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::prelude::*;
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser, input::Slice};
+ /// use nom8::input::Located;
+ /// use nom8::character::alpha1;
+ /// use nom8::sequence::separated_pair;
+ ///
+ /// let mut parser = separated_pair(alpha1.span(), ',', alpha1.span());
+ ///
+ /// assert_eq!(parser.parse(Located::new("abcd,efgh")).finish(), Ok((0..4, 5..9)));
+ /// assert_eq!(parser.parse(Located::new("abcd;")),Err(Err::Error((Located::new("abcd;").slice(4..), ErrorKind::OneOf))));
+ /// ```
+ fn span(self) -> Span<Self, O>
+ where
+ Self: core::marker::Sized,
+ I: Location + Clone,
+ {
+ Span::new(self)
+ }
+
+ /// if the child parser was successful, return the location of consumed input with the output
+ /// as a tuple. Functions similarly to [Parser::span] except it
+ /// returns the parser output as well.
+ ///
+ /// This can be useful especially in cases where the output is not the same type
+ /// as the input, or the input is a user defined type.
+ ///
+ /// Returned tuple is of the format `(produced output, consumed input)`.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::prelude::*;
+ /// # use nom8::{Err,error::ErrorKind, IResult, input::Slice};
+ /// use nom8::input::Located;
+ /// use nom8::character::alpha1;
+ /// use nom8::bytes::tag;
+ /// use nom8::sequence::separated_pair;
+ ///
+ /// fn inner_parser(input: Located<&str>) -> IResult<Located<&str>, bool> {
+ /// tag("1234").value(true).parse(input)
+ /// }
+ ///
+ /// # fn main() {
+ ///
+ /// let mut consumed_parser = separated_pair(alpha1.value(1).with_span(), ',', alpha1.value(2).with_span());
+ ///
+ /// assert_eq!(consumed_parser.parse(Located::new("abcd,efgh")).finish(), Ok(((1, 0..4), (2, 5..9))));
+ /// assert_eq!(consumed_parser.parse(Located::new("abcd;")),Err(Err::Error((Located::new("abcd;").slice(4..), ErrorKind::OneOf))));
+ ///
+ /// // the second output (representing the consumed input)
+ /// // should be the same as that of the `span` parser.
+ /// let mut recognize_parser = inner_parser.span();
+ /// let mut consumed_parser = inner_parser.with_span().map(|(output, consumed)| consumed);
+ ///
+ /// assert_eq!(recognize_parser.parse(Located::new("1234")), consumed_parser.parse(Located::new("1234")));
+ /// assert_eq!(recognize_parser.parse(Located::new("abcd")), consumed_parser.parse(Located::new("abcd")));
+ /// # }
+ /// ```
+ fn with_span(self) -> WithSpan<Self, O>
+ where
+ Self: core::marker::Sized,
+ I: Location + Clone,
+ {
+ WithSpan::new(self)
+ }
+
+ /// Maps a function over the result of a parser
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// use nom8::{Err,error::ErrorKind, IResult,Parser};
+ /// use nom8::character::digit1;
+ /// # fn main() {
+ ///
+ /// let mut parser = digit1.map(|s: &str| s.len());
+ ///
+ /// // the parser will count how many characters were returned by digit1
+ /// assert_eq!(parser.parse("123456"), Ok(("", 6)));
+ ///
+ /// // this will fail if digit1 fails
+ /// assert_eq!(parser.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+ /// # }
+ /// ```
+ fn map<G, O2>(self, g: G) -> Map<Self, G, O>
+ where
+ G: Fn(O) -> O2,
+ Self: core::marker::Sized,
+ {
+ Map::new(self, g)
+ }
+
+ /// Applies a function returning a `Result` over the result of a parser.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::character::digit1;
+ /// # fn main() {
+ ///
+ /// let mut parse = digit1.map_res(|s: &str| s.parse::<u8>());
+ ///
+ /// // the parser will convert the result of digit1 to a number
+ /// assert_eq!(parse.parse("123"), Ok(("", 123)));
+ ///
+ /// // this will fail if digit1 fails
+ /// assert_eq!(parse.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+ ///
+ /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
+ /// assert_eq!(parse.parse("123456"), Err(Err::Error(("123456", ErrorKind::MapRes))));
+ /// # }
+ /// ```
+ fn map_res<G, O2, E2>(self, g: G) -> MapRes<Self, G, O>
+ where
+ Self: core::marker::Sized,
+ G: FnMut(O) -> Result<O2, E2>,
+ {
+ MapRes::new(self, g)
+ }
+
+ /// Applies a function returning an `Option` over the result of a parser.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::character::digit1;
+ /// # fn main() {
+ ///
+ /// let mut parse = digit1.map_opt(|s: &str| s.parse::<u8>().ok());
+ ///
+ /// // the parser will convert the result of digit1 to a number
+ /// assert_eq!(parse.parse("123"), Ok(("", 123)));
+ ///
+ /// // this will fail if digit1 fails
+ /// assert_eq!(parse.parse("abc"), Err(Err::Error(("abc", ErrorKind::Digit))));
+ ///
+ /// // this will fail if the mapped function fails (a `u8` is too small to hold `123456`)
+ /// assert_eq!(parse.parse("123456"), Err(Err::Error(("123456", ErrorKind::MapOpt))));
+ /// # }
+ /// ```
+ fn map_opt<G, O2>(self, g: G) -> MapOpt<Self, G, O>
+ where
+ Self: core::marker::Sized,
+ G: FnMut(O) -> Option<O2>,
+ {
+ MapOpt::new(self, g)
+ }
+
+ /// Creates a second parser from the output of the first one, then apply over the rest of the input
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::bytes::take;
+ /// use nom8::number::u8;
+ /// # fn main() {
+ ///
+ /// let mut length_data = u8.flat_map(take);
+ ///
+ /// assert_eq!(length_data.parse(&[2, 0, 1, 2][..]), Ok((&[2][..], &[0, 1][..])));
+ /// assert_eq!(length_data.parse(&[4, 0, 1, 2][..]), Err(Err::Error((&[0, 1, 2][..], ErrorKind::Eof))));
+ /// # }
+ /// ```
+ fn flat_map<G, H, O2>(self, g: G) -> FlatMap<Self, G, O>
+ where
+ G: FnMut(O) -> H,
+ H: Parser<I, O2, E>,
+ Self: core::marker::Sized,
+ {
+ FlatMap::new(self, g)
+ }
+
+ /// Applies a second parser over the output of the first one
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// use nom8::character::digit1;
+ /// use nom8::bytes::take;
+ /// # fn main() {
+ ///
+ /// let mut digits = take(5u8).and_then(digit1);
+ ///
+ /// assert_eq!(digits.parse("12345"), Ok(("", "12345")));
+ /// assert_eq!(digits.parse("123ab"), Ok(("", "123")));
+ /// assert_eq!(digits.parse("123"), Err(Err::Error(("123", ErrorKind::Eof))));
+ /// # }
+ /// ```
+ fn and_then<G, O2>(self, g: G) -> AndThen<Self, G, O>
+ where
+ G: Parser<O, O2, E>,
+ Self: core::marker::Sized,
+ {
+ AndThen::new(self, g)
+ }
+
+ /// Returns the result of the child parser if it satisfies a verification function.
+ ///
+ /// The verification function takes as argument a reference to the output of the
+ /// parser.
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, Parser};
+ /// # use nom8::character::alpha1;
+ /// # fn main() {
+ ///
+ /// let mut parser = alpha1.verify(|s: &str| s.len() == 4);
+ ///
+ /// assert_eq!(parser.parse("abcd"), Ok(("", "abcd")));
+ /// assert_eq!(parser.parse("abcde"), Err(Err::Error(("abcde", ErrorKind::Verify))));
+ /// assert_eq!(parser.parse("123abcd;"),Err(Err::Error(("123abcd;", ErrorKind::Alpha))));
+ /// # }
+ /// ```
+ fn verify<G, O2: ?Sized>(self, second: G) -> Verify<Self, G, O2>
+ where
+ Self: core::marker::Sized,
+ G: Fn(&O2) -> bool,
+ {
+ Verify::new(self, second)
+ }
+
+ /// If parsing fails, add context to the error
+ ///
+ /// This is used mainly to add user friendly information
+ /// to errors when backtracking through a parse tree.
+ fn context<C>(self, context: C) -> Context<Self, O, C>
+ where
+ Self: core::marker::Sized,
+ C: Clone,
+ E: ContextError<I, C>,
+ {
+ Context::new(self, context)
+ }
+
+ /// Transforms [`Incomplete`][crate::Err::Incomplete] into [`Error`][crate::Err::Error]
+ ///
+ /// # Example
+ ///
+ /// ```rust
+ /// # use nom8::{Err,error::ErrorKind, IResult, input::Streaming, Parser};
+ /// # use nom8::bytes::take;
+ /// # fn main() {
+ ///
+ /// let mut parser = take(5u8).complete();
+ ///
+ /// assert_eq!(parser.parse(Streaming("abcdefg")), Ok((Streaming("fg"), "abcde")));
+ /// assert_eq!(parser.parse(Streaming("abcd")), Err(Err::Error((Streaming("abcd"), ErrorKind::Complete))));
+ /// # }
+ /// ```
+ fn complete(self) -> Complete<Self>
+ where
+ Self: core::marker::Sized,
+ {
+ Complete::new(self)
+ }
+
+ /// Convert the parser's error to another type using [`std::convert::From`]
+ fn err_into<E2: From<E>>(self) -> ErrInto<Self, E, E2>
+ where
+ Self: core::marker::Sized,
+ {
+ ErrInto::new(self)
+ }
+
+ /// Prints a message and the input if the parser fails.
+ ///
+ /// The message prints the `Error` or `Incomplete`
+ /// and the parser's calling code.
+ ///
+ /// It also displays the input in hexdump format
+ ///
+ /// ```rust
+ /// use nom8::prelude::*;
+ /// use nom8::{IResult, bytes::tag};
+ ///
+ /// fn f(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ /// tag("abcd").dbg_err("alpha tag").parse(i)
+ /// }
+ ///
+ /// let a = &b"efghijkl"[..];
+ /// f(a);
+ /// ```
+ ///
+ /// Will print the following message:
+ /// ```console
+ /// alpha tag: Error(Position(0, [101, 102, 103, 104, 105, 106, 107, 108])) at:
+ /// 00000000 65 66 67 68 69 6a 6b 6c efghijkl
+ /// ```
+ #[cfg(feature = "std")]
+ fn dbg_err<C>(self, context: C) -> DbgErr<Self, O, C>
+ where
+ C: std::fmt::Display,
+ Self: core::marker::Sized,
+ {
+ DbgErr::new(self, context)
+ }
+
+ /// Applies a second parser after the first one, return their results as a tuple
+ ///
+ /// **WARNING:** Deprecated, replaced with [`nom8::sequence::tuple`][crate::sequence::tuple]
+ #[deprecated(since = "8.0.0", note = "Replaced with `nom8::sequence::tuple")]
+ fn and<G, O2>(self, g: G) -> And<Self, G>
+ where
+ G: Parser<I, O2, E>,
+ Self: core::marker::Sized,
+ {
+ And::new(self, g)
+ }
+
+ /// Applies a second parser over the input if the first one failed
+ ///
+ /// **WARNING:** Deprecated, replaced with [`nom8::branch::alt`][crate::branch::alt]
+ #[deprecated(since = "8.0.0", note = "Replaced with `nom8::branch::alt")]
+ fn or<G>(self, g: G) -> Or<Self, G>
+ where
+ G: Parser<I, O, E>,
+ Self: core::marker::Sized,
+ {
+ Or::new(self, g)
+ }
+}
+
+impl<'a, I, O, E, F> Parser<I, O, E> for F
+where
+ F: FnMut(I) -> IResult<I, O, E> + 'a,
+{
+ fn parse(&mut self, i: I) -> IResult<I, O, E> {
+ self(i)
+ }
+}
+
+/// This is a shortcut for [`one_of`][crate::bytes::one_of].
+///
+/// # Example
+///
+/// ```
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{ErrorKind, Error}};
+/// fn parser(i: &[u8]) -> IResult<&[u8], u8> {
+/// b'a'.parse(i)
+/// }
+/// assert_eq!(parser(&b"abc"[..]), Ok((&b"bc"[..], b'a')));
+/// assert_eq!(parser(&b" abc"[..]), Err(Err::Error(Error::new(&b" abc"[..], ErrorKind::OneOf))));
+/// assert_eq!(parser(&b"bc"[..]), Err(Err::Error(Error::new(&b"bc"[..], ErrorKind::OneOf))));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error(Error::new(&b""[..], ErrorKind::OneOf))));
+/// ```
+impl<I, E> Parser<I, u8, E> for u8
+where
+ I: Slice<RangeFrom<usize>> + InputIter<Item = u8> + InputLength + InputIsStreaming<false>,
+ E: ParseError<I>,
+{
+ fn parse(&mut self, i: I) -> IResult<I, u8, E> {
+ crate::bytes::one_of(*self).parse(i)
+ }
+}
+
+/// This is a shortcut for [`one_of`][crate::bytes::one_of].
+///
+/// # Example
+///
+/// ```
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{ErrorKind, Error}};
+/// fn parser(i: &str) -> IResult<&str, char> {
+/// 'a'.parse(i)
+/// }
+/// assert_eq!(parser("abc"), Ok(("bc", 'a')));
+/// assert_eq!(parser(" abc"), Err(Err::Error(Error::new(" abc", ErrorKind::OneOf))));
+/// assert_eq!(parser("bc"), Err(Err::Error(Error::new("bc", ErrorKind::OneOf))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::OneOf))));
+/// ```
+impl<I, E> Parser<I, <I as InputIter>::Item, E> for char
+where
+ I: Slice<RangeFrom<usize>> + InputIter + InputLength + InputIsStreaming<false>,
+ <I as InputIter>::Item: AsChar + Copy,
+ E: ParseError<I>,
+{
+ fn parse(&mut self, i: I) -> IResult<I, <I as InputIter>::Item, E> {
+ crate::bytes::one_of(*self).parse(i)
+ }
+}
+
+/// This is a shortcut for [`tag`][crate::bytes::tag].
+///
+/// # Example
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed};
+/// # use nom8::branch::alt;
+/// # use nom8::bytes::take;
+///
+/// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// alt((&"Hello"[..], take(5usize))).parse(s)
+/// }
+///
+/// assert_eq!(parser(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
+/// assert_eq!(parser(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
+/// assert_eq!(parser(&b"Some"[..]), Err(Err::Error(Error::new(&b"Some"[..], ErrorKind::Eof))));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error(Error::new(&b""[..], ErrorKind::Eof))));
+/// ```
+impl<'s, I, E: ParseError<I>> Parser<I, <I as IntoOutput>::Output, E> for &'s [u8]
+where
+ I: InputTake + InputLength + Compare<&'s [u8]> + InputIsStreaming<false>,
+ I: IntoOutput,
+{
+ fn parse(&mut self, i: I) -> IResult<I, <I as IntoOutput>::Output, E> {
+ crate::bytes::tag(*self).parse(i)
+ }
+}
+
+/// This is a shortcut for [`tag`][crate::bytes::tag].
+///
+/// # Example
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed};
+/// # use nom8::branch::alt;
+/// # use nom8::bytes::take;
+///
+/// fn parser(s: &[u8]) -> IResult<&[u8], &[u8]> {
+/// alt((b"Hello", take(5usize))).parse(s)
+/// }
+///
+/// assert_eq!(parser(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
+/// assert_eq!(parser(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
+/// assert_eq!(parser(&b"Some"[..]), Err(Err::Error(Error::new(&b"Some"[..], ErrorKind::Eof))));
+/// assert_eq!(parser(&b""[..]), Err(Err::Error(Error::new(&b""[..], ErrorKind::Eof))));
+/// ```
+impl<'s, I, E: ParseError<I>, const N: usize> Parser<I, <I as IntoOutput>::Output, E>
+ for &'s [u8; N]
+where
+ I: InputTake + InputLength + Compare<&'s [u8; N]> + InputIsStreaming<false>,
+ I: IntoOutput,
+{
+ fn parse(&mut self, i: I) -> IResult<I, <I as IntoOutput>::Output, E> {
+ crate::bytes::tag(*self).parse(i)
+ }
+}
+
+/// This is a shortcut for [`tag`][crate::bytes::tag].
+///
+/// # Example
+/// ```rust
+/// # use nom8::prelude::*;
+/// # use nom8::{Err, error::{Error, ErrorKind}, Needed};
+/// # use nom8::branch::alt;
+/// # use nom8::bytes::take;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// alt(("Hello", take(5usize))).parse(s)
+/// }
+///
+/// assert_eq!(parser("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser("Something"), Ok(("hing", "Somet")));
+/// assert_eq!(parser("Some"), Err(Err::Error(Error::new("Some", ErrorKind::Eof))));
+/// assert_eq!(parser(""), Err(Err::Error(Error::new("", ErrorKind::Eof))));
+/// ```
+impl<'s, I, E: ParseError<I>> Parser<I, <I as IntoOutput>::Output, E> for &'s str
+where
+ I: InputTake + InputLength + Compare<&'s str> + InputIsStreaming<false>,
+ I: IntoOutput,
+{
+ fn parse(&mut self, i: I) -> IResult<I, <I as IntoOutput>::Output, E> {
+ crate::bytes::tag(*self).parse(i)
+ }
+}
+
+impl<I, E: ParseError<I>> Parser<I, (), E> for () {
+ fn parse(&mut self, i: I) -> IResult<I, (), E> {
+ Ok((i, ()))
+ }
+}
+
+macro_rules! impl_parser_for_tuple {
+ ($($parser:ident $output:ident),+) => (
+ #[allow(non_snake_case)]
+ impl<I, $($output),+, E: ParseError<I>, $($parser),+> Parser<I, ($($output),+,), E> for ($($parser),+,)
+ where
+ $($parser: Parser<I, $output, E>),+
+ {
+ fn parse(&mut self, i: I) -> IResult<I, ($($output),+,), E> {
+ let ($(ref mut $parser),+,) = *self;
+
+ $(let(i, $output) = $parser.parse(i)?;)+
+
+ Ok((i, ($($output),+,)))
+ }
+ }
+ )
+}
+
+macro_rules! impl_parser_for_tuples {
+ ($parser1:ident $output1:ident, $($parser:ident $output:ident),+) => {
+ impl_parser_for_tuples!(__impl $parser1 $output1; $($parser $output),+);
+ };
+ (__impl $($parser:ident $output:ident),+; $parser1:ident $output1:ident $(,$parser2:ident $output2:ident)*) => {
+ impl_parser_for_tuple!($($parser $output),+);
+ impl_parser_for_tuples!(__impl $($parser $output),+, $parser1 $output1; $($parser2 $output2),*);
+ };
+ (__impl $($parser:ident $output:ident),+;) => {
+ impl_parser_for_tuple!($($parser $output),+);
+ }
+}
+
+impl_parser_for_tuples!(
+ P1 O1,
+ P2 O2,
+ P3 O3,
+ P4 O4,
+ P5 O5,
+ P6 O6,
+ P7 O7,
+ P8 O8,
+ P9 O9,
+ P10 O10,
+ P11 O11,
+ P12 O12,
+ P13 O13,
+ P14 O14,
+ P15 O15,
+ P16 O16,
+ P17 O17,
+ P18 O18,
+ P19 O19,
+ P20 O20,
+ P21 O21
+);
+
+#[cfg(feature = "alloc")]
+use alloc::boxed::Box;
+
+#[cfg(feature = "alloc")]
+impl<'a, I, O, E> Parser<I, O, E> for Box<dyn Parser<I, O, E> + 'a> {
+ fn parse(&mut self, input: I) -> IResult<I, O, E> {
+ (**self).parse(input)
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::bytes::{tag, take};
+ use crate::error::ErrorKind;
+ use crate::input::Streaming;
+ use crate::number::be_u16;
+
+ #[doc(hidden)]
+ #[macro_export]
+ macro_rules! assert_size (
+ ($t:ty, $sz:expr) => (
+ assert!(crate::lib::std::mem::size_of::<$t>() <= $sz, "{} <= {} failed", crate::lib::std::mem::size_of::<$t>(), $sz);
+ );
+ );
+
+ #[test]
+ #[cfg(target_pointer_width = "64")]
+ fn size_test() {
+ assert_size!(IResult<&[u8], &[u8], (&[u8], u32)>, 40);
+ assert_size!(IResult<&str, &str, u32>, 40);
+ assert_size!(Needed, 8);
+ assert_size!(Err<u32>, 16);
+ assert_size!(ErrorKind, 1);
+ }
+
+ #[test]
+ fn err_map_test() {
+ let e = Err::Error(1);
+ assert_eq!(e.map(|v| v + 1), Err::Error(2));
+ }
+
+ #[test]
+ fn single_element_tuples() {
+ use crate::character::alpha1;
+ use crate::{error::ErrorKind, Err};
+
+ let mut parser = (alpha1,);
+ assert_eq!(parser.parse("abc123def"), Ok(("123def", ("abc",))));
+ assert_eq!(
+ parser.parse("123def"),
+ Err(Err::Error(("123def", ErrorKind::Alpha)))
+ );
+ }
+
+ #[test]
+ fn tuple_test() {
+ fn tuple_3(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (u16, &[u8], &[u8])> {
+ (be_u16, take(3u8), tag("fg")).parse(i)
+ }
+
+ assert_eq!(
+ tuple_3(Streaming(&b"abcdefgh"[..])),
+ Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..])))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcd"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcde"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcdejk"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"jk"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ }
+
+ #[test]
+ fn unit_type() {
+ fn parser(i: &str) -> IResult<&str, ()> {
+ ().parse(i)
+ }
+ assert_eq!(parser.parse("abxsbsh"), Ok(("abxsbsh", ())));
+ assert_eq!(parser.parse("sdfjakdsas"), Ok(("sdfjakdsas", ())));
+ assert_eq!(parser.parse(""), Ok(("", ())));
+ }
+}
diff --git a/vendor/nom8/src/sequence/mod.rs b/vendor/nom8/src/sequence/mod.rs
new file mode 100644
index 000000000..ccf37d334
--- /dev/null
+++ b/vendor/nom8/src/sequence/mod.rs
@@ -0,0 +1,291 @@
+//! Combinators applying parsers in sequence
+
+#[cfg(test)]
+mod tests;
+
+use crate::error::ParseError;
+use crate::{IResult, Parser};
+
+/// Gets an object from the first parser,
+/// then gets another object from the second parser.
+///
+/// **WARNING:** Deprecated, [`Parser`] is directly implemented for tuples
+///
+/// # Arguments
+/// * `first` The first parser to apply.
+/// * `second` The second parser to apply.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::sequence::pair;
+/// use nom8::bytes::tag;
+///
+/// let mut parser = pair(tag("abc"), tag("efg"));
+///
+/// assert_eq!(parser("abcefg"), Ok(("", ("abc", "efg"))));
+/// assert_eq!(parser("abcefghij"), Ok(("hij", ("abc", "efg"))));
+/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
+/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
+/// ```
+#[deprecated(since = "8.0.0", note = "`Parser` is directly implemented for tuples")]
+pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(
+ mut first: F,
+ mut second: G,
+) -> impl FnMut(I) -> IResult<I, (O1, O2), E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<I, O2, E>,
+{
+ move |input: I| {
+ let (input, o1) = first.parse(input)?;
+ second.parse(input).map(|(i, o2)| (i, (o1, o2)))
+ }
+}
+
+/// Matches an object from the first parser and discards it,
+/// then gets an object from the second parser.
+///
+/// # Arguments
+/// * `first` The opening parser.
+/// * `second` The second parser to get object.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::sequence::preceded;
+/// use nom8::bytes::tag;
+///
+/// let mut parser = preceded(tag("abc"), tag("efg"));
+///
+/// assert_eq!(parser("abcefg"), Ok(("", "efg")));
+/// assert_eq!(parser("abcefghij"), Ok(("hij", "efg")));
+/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
+/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
+/// ```
+pub fn preceded<I, O1, O2, E: ParseError<I>, F, G>(
+ mut first: F,
+ mut second: G,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<I, O2, E>,
+{
+ move |input: I| {
+ let (input, _) = first.parse(input)?;
+ second.parse(input)
+ }
+}
+
+/// Gets an object from the first parser,
+/// then matches an object from the second parser and discards it.
+///
+/// # Arguments
+/// * `first` The first parser to apply.
+/// * `second` The second parser to match an object.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::sequence::terminated;
+/// use nom8::bytes::tag;
+///
+/// let mut parser = terminated(tag("abc"), tag("efg"));
+///
+/// assert_eq!(parser("abcefg"), Ok(("", "abc")));
+/// assert_eq!(parser("abcefghij"), Ok(("hij", "abc")));
+/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
+/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
+/// ```
+pub fn terminated<I, O1, O2, E: ParseError<I>, F, G>(
+ mut first: F,
+ mut second: G,
+) -> impl FnMut(I) -> IResult<I, O1, E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<I, O2, E>,
+{
+ move |input: I| {
+ let (input, o1) = first.parse(input)?;
+ second.parse(input).map(|(i, _)| (i, o1))
+ }
+}
+
+/// Gets an object from the first parser,
+/// then matches an object from the sep_parser and discards it,
+/// then gets another object from the second parser.
+///
+/// # Arguments
+/// * `first` The first parser to apply.
+/// * `sep` The separator parser to apply.
+/// * `second` The second parser to apply.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::sequence::separated_pair;
+/// use nom8::bytes::tag;
+///
+/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg"));
+///
+/// assert_eq!(parser("abc|efg"), Ok(("", ("abc", "efg"))));
+/// assert_eq!(parser("abc|efghij"), Ok(("hij", ("abc", "efg"))));
+/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
+/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
+/// ```
+pub fn separated_pair<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
+ mut first: F,
+ mut sep: G,
+ mut second: H,
+) -> impl FnMut(I) -> IResult<I, (O1, O3), E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<I, O2, E>,
+ H: Parser<I, O3, E>,
+{
+ move |input: I| {
+ let (input, o1) = first.parse(input)?;
+ let (input, _) = sep.parse(input)?;
+ second.parse(input).map(|(i, o2)| (i, (o1, o2)))
+ }
+}
+
+/// Matches an object from the first parser and discards it,
+/// then gets an object from the second parser,
+/// and finally matches an object from the third parser and discards it.
+///
+/// # Arguments
+/// * `first` The first parser to apply and discard.
+/// * `second` The second parser to apply.
+/// * `third` The third parser to apply and discard.
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind, Needed};
+/// # use nom8::Needed::Size;
+/// use nom8::sequence::delimited;
+/// use nom8::bytes::tag;
+///
+/// let mut parser = delimited(tag("("), tag("abc"), tag(")"));
+///
+/// assert_eq!(parser("(abc)"), Ok(("", "abc")));
+/// assert_eq!(parser("(abc)def"), Ok(("def", "abc")));
+/// assert_eq!(parser(""), Err(Err::Error(("", ErrorKind::Tag))));
+/// assert_eq!(parser("123"), Err(Err::Error(("123", ErrorKind::Tag))));
+/// ```
+pub fn delimited<I, O1, O2, O3, E: ParseError<I>, F, G, H>(
+ mut first: F,
+ mut second: G,
+ mut third: H,
+) -> impl FnMut(I) -> IResult<I, O2, E>
+where
+ F: Parser<I, O1, E>,
+ G: Parser<I, O2, E>,
+ H: Parser<I, O3, E>,
+{
+ move |input: I| {
+ let (input, _) = first.parse(input)?;
+ let (input, o2) = second.parse(input)?;
+ third.parse(input).map(|(i, _)| (i, o2))
+ }
+}
+
+/// Helper trait for the tuple combinator.
+///
+/// This trait is implemented for tuples of parsers of up to 21 elements.
+#[deprecated(since = "8.0.0", note = "Replaced with `Parser`")]
+pub trait Tuple<I, O, E> {
+ /// Parses the input and returns a tuple of results of each parser.
+ fn parse(&mut self, input: I) -> IResult<I, O, E>;
+}
+
+#[allow(deprecated)]
+impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output, Error>>
+ Tuple<Input, (Output,), Error> for (F,)
+{
+ fn parse(&mut self, input: Input) -> IResult<Input, (Output,), Error> {
+ self.0.parse(input).map(|(i, o)| (i, (o,)))
+ }
+}
+
+macro_rules! tuple_trait(
+ ($name1:ident $ty1:ident, $name2: ident $ty2:ident, $($name:ident $ty:ident),*) => (
+ tuple_trait!(__impl $name1 $ty1, $name2 $ty2; $($name $ty),*);
+ );
+ (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident, $($name2:ident $ty2:ident),*) => (
+ tuple_trait_impl!($($name $ty),+);
+ tuple_trait!(__impl $($name $ty),+ , $name1 $ty1; $($name2 $ty2),*);
+ );
+ (__impl $($name:ident $ty: ident),+; $name1:ident $ty1:ident) => (
+ tuple_trait_impl!($($name $ty),+);
+ tuple_trait_impl!($($name $ty),+, $name1 $ty1);
+ );
+);
+
+macro_rules! tuple_trait_impl(
+ ($($name:ident $ty: ident),+) => (
+ #[allow(deprecated)]
+ impl<
+ Input: Clone, $($ty),+ , Error: ParseError<Input>,
+ $($name: Parser<Input, $ty, Error>),+
+ > Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
+
+ fn parse(&mut self, input: Input) -> IResult<Input, ( $($ty),+ ), Error> {
+ tuple_trait_inner!(0, self, input, (), $($name)+)
+
+ }
+ }
+ );
+);
+
+macro_rules! tuple_trait_inner(
+ ($it:tt, $self:expr, $input:expr, (), $head:ident $($id:ident)+) => ({
+ let (i, o) = $self.$it.parse($input.clone())?;
+
+ succ!($it, tuple_trait_inner!($self, i, ( o ), $($id)+))
+ });
+ ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident $($id:ident)+) => ({
+ let (i, o) = $self.$it.parse($input.clone())?;
+
+ succ!($it, tuple_trait_inner!($self, i, ($($parsed)* , o), $($id)+))
+ });
+ ($it:tt, $self:expr, $input:expr, ($($parsed:tt)*), $head:ident) => ({
+ let (i, o) = $self.$it.parse($input.clone())?;
+
+ Ok((i, ($($parsed)* , o)))
+ });
+);
+
+tuple_trait!(FnA A, FnB B, FnC C, FnD D, FnE E, FnF F, FnG G, FnH H, FnI I, FnJ J, FnK K, FnL L,
+ FnM M, FnN N, FnO O, FnP P, FnQ Q, FnR R, FnS S, FnT T, FnU U);
+
+// Special case: implement `Tuple` for `()`, the unit type.
+// This can come up in macros which accept a variable number of arguments.
+// Literally, `()` is an empty tuple, so it should simply parse nothing.
+#[allow(deprecated)]
+impl<I, E: ParseError<I>> Tuple<I, (), E> for () {
+ fn parse(&mut self, input: I) -> IResult<I, (), E> {
+ Ok((input, ()))
+ }
+}
+
+///Applies a tuple of parsers one by one and returns their results as a tuple.
+///There is a maximum of 21 parsers
+///
+/// **WARNING:** Deprecated, [`Parser`] is directly implemented for tuples
+///
+/// ```rust
+/// # use nom8::{Err, error::ErrorKind};
+/// use nom8::sequence::tuple;
+/// use nom8::character::{alpha1, digit1};
+/// let mut parser = tuple((alpha1, digit1, alpha1));
+///
+/// assert_eq!(parser("abc123def"), Ok(("", ("abc", "123", "def"))));
+/// assert_eq!(parser("123def"), Err(Err::Error(("123def", ErrorKind::Alpha))));
+/// ```
+#[deprecated(since = "8.0.0", note = "`Parser` is directly implemented for tuples")]
+#[allow(deprecated)]
+pub fn tuple<I, O, E: ParseError<I>, List: Tuple<I, O, E>>(
+ mut l: List,
+) -> impl FnMut(I) -> IResult<I, O, E> {
+ move |i: I| l.parse(i)
+}
diff --git a/vendor/nom8/src/sequence/tests.rs b/vendor/nom8/src/sequence/tests.rs
new file mode 100644
index 000000000..1edb21bc6
--- /dev/null
+++ b/vendor/nom8/src/sequence/tests.rs
@@ -0,0 +1,310 @@
+use super::*;
+use crate::bytes::{tag, take};
+use crate::error::{Error, ErrorKind};
+use crate::input::Streaming;
+use crate::number::be_u16;
+use crate::{Err, IResult, Needed};
+
+#[test]
+fn single_element_tuples() {
+ #![allow(deprecated)]
+ use crate::character::alpha1;
+ use crate::{error::ErrorKind, Err};
+
+ let mut parser = tuple((alpha1,));
+ assert_eq!(parser("abc123def"), Ok(("123def", ("abc",))));
+ assert_eq!(
+ parser("123def"),
+ Err(Err::Error(("123def", ErrorKind::Alpha)))
+ );
+}
+
+#[derive(PartialEq, Eq, Debug)]
+struct B {
+ a: u8,
+ b: u8,
+}
+
+#[derive(PartialEq, Eq, Debug)]
+struct C {
+ a: u8,
+ b: Option<u8>,
+}
+
+#[test]
+fn complete() {
+ use crate::bytes::tag;
+ fn err_test(i: &[u8]) -> IResult<&[u8], &[u8]> {
+ let (i, _) = tag("ijkl")(i)?;
+ tag("mnop")(i)
+ }
+ let a = &b"ijklmn"[..];
+
+ let res_a = err_test(a);
+ assert_eq!(
+ res_a,
+ Err(Err::Error(error_position!(&b"mn"[..], ErrorKind::Tag)))
+ );
+}
+
+#[test]
+fn pair_test() {
+ #![allow(deprecated)]
+ fn pair_abc_def(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8])> {
+ pair(tag("abc"), tag("def"))(i)
+ }
+
+ assert_eq!(
+ pair_abc_def(Streaming(&b"abcdefghijkl"[..])),
+ Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..])))
+ );
+ assert_eq!(
+ pair_abc_def(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ pair_abc_def(Streaming(&b"abcd"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ pair_abc_def(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ pair_abc_def(Streaming(&b"xxxdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxdef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ pair_abc_def(Streaming(&b"abcxxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn separated_pair_test() {
+ fn sep_pair_abc_def(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8])> {
+ separated_pair(tag("abc"), tag(","), tag("def"))(i)
+ }
+
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"abc,defghijkl"[..])),
+ Ok((Streaming(&b"ghijkl"[..]), (&b"abc"[..], &b"def"[..])))
+ );
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"abc,d"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"xxx,def"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx,def"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ sep_pair_abc_def(Streaming(&b"abc,xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn preceded_test() {
+ fn preceded_abcd_efgh(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ preceded(tag("abcd"), tag("efgh"))(i)
+ }
+
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"abcdefghijkl"[..])),
+ Ok((Streaming(&b"ijkl"[..]), &b"efgh"[..]))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"abcde"[..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"xxxxdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxxdef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ preceded_abcd_efgh(Streaming(&b"abcdxxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn terminated_test() {
+ fn terminated_abcd_efgh(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ terminated(tag("abcd"), tag("efgh"))(i)
+ }
+
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"abcdefghijkl"[..])),
+ Ok((Streaming(&b"ijkl"[..]), &b"abcd"[..]))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"abcde"[..])),
+ Err(Err::Incomplete(Needed::new(3)))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"xxxxdef"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxxdef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ terminated_abcd_efgh(Streaming(&b"abcdxxxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn delimited_test() {
+ fn delimited_abc_def_ghi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ delimited(tag("abc"), tag("def"), tag("ghi"))(i)
+ }
+
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"abcdefghijkl"[..])),
+ Ok((Streaming(&b"jkl"[..]), &b"def"[..]))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"ab"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"abcde"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"abcdefgh"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"xxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"xxxdefghi"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxdefghi"[..]),
+ ErrorKind::Tag
+ ),))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"abcxxxghi"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxxghi"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ assert_eq!(
+ delimited_abc_def_ghi(Streaming(&b"abcdefxxx"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"xxx"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn tuple_test() {
+ #![allow(deprecated)]
+ fn tuple_3(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (u16, &[u8], &[u8])> {
+ tuple((be_u16, take(3u8), tag("fg")))(i)
+ }
+
+ assert_eq!(
+ tuple_3(Streaming(&b"abcdefgh"[..])),
+ Ok((Streaming(&b"h"[..]), (0x6162u16, &b"cde"[..], &b"fg"[..])))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcd"[..])),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcde"[..])),
+ Err(Err::Incomplete(Needed::new(2)))
+ );
+ assert_eq!(
+ tuple_3(Streaming(&b"abcdejk"[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&b"jk"[..]),
+ ErrorKind::Tag
+ )))
+ );
+}
+
+#[test]
+fn unit_type() {
+ #![allow(deprecated)]
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())("abxsbsh"),
+ Ok(("abxsbsh", ()))
+ );
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())("sdfjakdsas"),
+ Ok(("sdfjakdsas", ()))
+ );
+ assert_eq!(
+ tuple::<&'static str, (), Error<&'static str>, ()>(())(""),
+ Ok(("", ()))
+ );
+}
diff --git a/vendor/nom8/src/str.rs b/vendor/nom8/src/str.rs
new file mode 100644
index 000000000..593e0ba9b
--- /dev/null
+++ b/vendor/nom8/src/str.rs
@@ -0,0 +1,539 @@
+#[cfg(test)]
+mod test {
+ use crate::input::Streaming;
+ use crate::prelude::*;
+ #[cfg(feature = "alloc")]
+ use crate::{branch::alt, bytes::tag_no_case, multi::many1};
+ use crate::{
+ bytes::{tag, take, take_till, take_till1, take_until, take_while1},
+ error::{self, ErrorKind},
+ Err, IResult,
+ };
+
+ #[test]
+ fn tagtr_succeed() {
+ const INPUT: &str = "Hello World!";
+ const TAG: &str = "Hello";
+ fn test(input: &str) -> IResult<&str, &str> {
+ tag(TAG)(input)
+ }
+
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(extra == " World!", "Parser `tag` consumed leftover input.");
+ assert!(
+ output == TAG,
+ "Parser `tag` doesn't return the tag it matched on success. \
+ Expected `{}`, got `{}`.",
+ TAG,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `tag` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn tagtr_incomplete() {
+ use crate::bytes::tag;
+
+ const INPUT: &str = "Hello";
+ const TAG: &str = "Hello World!";
+
+ let res: IResult<_, _, error::Error<_>> = tag(TAG)(Streaming(INPUT));
+ match res {
+ Err(Err::Incomplete(_)) => (),
+ other => {
+ panic!(
+ "Parser `tag` didn't require more input when it should have. \
+ Got `{:?}`.",
+ other
+ );
+ }
+ };
+ }
+
+ #[test]
+ fn tagtr_error() {
+ const INPUT: &str = "Hello World!";
+ const TAG: &str = "Random"; // TAG must be closer than INPUT.
+
+ let res: IResult<_, _, error::Error<_>> = tag(TAG)(INPUT);
+ match res {
+ Err(Err::Error(_)) => (),
+ other => {
+ panic!(
+ "Parser `tag` didn't fail when it should have. Got `{:?}`.`",
+ other
+ );
+ }
+ };
+ }
+
+ #[test]
+ fn take_s_succeed() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+
+ let res: IResult<_, _, error::Error<_>> = take(9_usize)(INPUT);
+ match res {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_s` consumed leftover input. Leftover `{}`.",
+ extra
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_s` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_s` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_until_succeed() {
+ const INPUT: &str = "βèƒôřèÂßÇ∂áƒƭèř";
+ const FIND: &str = "ÂßÇ∂";
+ const CONSUMED: &str = "βèƒôřè";
+ const LEFTOVER: &str = "ÂßÇ∂áƒƭèř";
+
+ let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(INPUT);
+ match res {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_until`\
+ consumed leftover input. Leftover `{}`.",
+ extra
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_until`\
+ doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_until` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_s_incomplete() {
+ use crate::bytes::take;
+
+ const INPUT: &str = "βèƒôřèÂßÇá";
+
+ let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(Streaming(INPUT));
+ match res {
+ Err(Err::Incomplete(_)) => (),
+ other => panic!(
+ "Parser `take` didn't require more input when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ }
+ }
+
+ use crate::Needed;
+
+ fn is_alphabetic(c: char) -> bool {
+ (c as u8 >= 0x41 && c as u8 <= 0x5A) || (c as u8 >= 0x61 && c as u8 <= 0x7A)
+ }
+
+ #[test]
+ fn take_while() {
+ use crate::bytes::take_while;
+
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while(is_alphabetic)(i)
+ }
+ let a = "";
+ let b = "abcd";
+ let c = "abcd123";
+ let d = "123";
+
+ assert_eq!(f(Streaming(&a[..])), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(&b[..])), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(&c[..])), Ok((Streaming(&d[..]), &b[..])));
+ assert_eq!(f(Streaming(&d[..])), Ok((Streaming(&d[..]), &a[..])));
+ }
+
+ #[test]
+ fn test_take_while1() {
+ fn f(i: Streaming<&str>) -> IResult<Streaming<&str>, &str> {
+ take_while1(is_alphabetic)(i)
+ }
+ let a = "";
+ let b = "abcd";
+ let c = "abcd123";
+ let d = "123";
+
+ assert_eq!(f(Streaming(&a[..])), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(&b[..])), Err(Err::Incomplete(Needed::new(1))));
+ assert_eq!(f(Streaming(&c[..])), Ok((Streaming(&"123"[..]), &b[..])));
+ assert_eq!(
+ f(Streaming(&d[..])),
+ Err(Err::Error(error_position!(
+ Streaming(&d[..]),
+ ErrorKind::TakeWhile1
+ )))
+ );
+ }
+
+ #[test]
+ fn take_till_s_succeed() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+ fn till_s(c: char) -> bool {
+ c == 'á'
+ }
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_till(till_s)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_till` consumed leftover input."
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_till` doesn't return the string it consumed on success. \
+ Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_till` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_while_succeed_none() {
+ use crate::bytes::take_while;
+
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const CONSUMED: &str = "";
+ const LEFTOVER: &str = "βèƒôřèÂßÇáƒƭèř";
+ fn while_s(c: char) -> bool {
+ c == '9'
+ }
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while(while_s)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_while` consumed leftover input."
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_while` doesn't return the string it consumed on success. \
+ Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_while` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn is_not_succeed() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const AVOID: &str = "£úçƙ¥á";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_till1(AVOID)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `is_not` consumed leftover input. Leftover `{}`.",
+ extra
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `is_not` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `is_not` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_while_succeed_some() {
+ use crate::bytes::take_while;
+
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+ fn while_s(c: char) -> bool {
+ c == 'β'
+ || c == 'è'
+ || c == 'ƒ'
+ || c == 'ô'
+ || c == 'ř'
+ || c == 'è'
+ || c == 'Â'
+ || c == 'ß'
+ || c == 'Ç'
+ }
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while(while_s)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_while` consumed leftover input."
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_while` doesn't return the string it consumed on success. \
+ Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_while` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn is_not_fail() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const AVOID: &str = "βúçƙ¥";
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_till1(AVOID)(input)
+ }
+ match test(INPUT) {
+ Err(Err::Error(_)) => (),
+ other => panic!(
+ "Parser `is_not` didn't fail when it should have. Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_while1_succeed() {
+ use crate::bytes::take_while1;
+
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+ fn while1_s(c: char) -> bool {
+ c == 'β'
+ || c == 'è'
+ || c == 'ƒ'
+ || c == 'ô'
+ || c == 'ř'
+ || c == 'è'
+ || c == 'Â'
+ || c == 'ß'
+ || c == 'Ç'
+ }
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while1(while1_s)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `take_while1` consumed leftover input."
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `take_while1` doesn't return the string it consumed on success. \
+ Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `take_while1` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_until_incomplete() {
+ use crate::bytes::take_until;
+
+ const INPUT: &str = "βèƒôřè";
+ const FIND: &str = "βèƒôřèÂßÇ";
+
+ let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(Streaming(INPUT));
+ match res {
+ Err(Err::Incomplete(_)) => (),
+ other => panic!(
+ "Parser `take_until` didn't require more input when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn is_a_succeed() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const MATCH: &str = "βèƒôřèÂßÇ";
+ const CONSUMED: &str = "βèƒôřèÂßÇ";
+ const LEFTOVER: &str = "áƒƭèř";
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while1(MATCH)(input)
+ }
+ match test(INPUT) {
+ Ok((extra, output)) => {
+ assert!(
+ extra == LEFTOVER,
+ "Parser `is_a` consumed leftover input. Leftover `{}`.",
+ extra
+ );
+ assert!(
+ output == CONSUMED,
+ "Parser `is_a` doesn't return the string it consumed on success. Expected `{}`, got `{}`.",
+ CONSUMED,
+ output
+ );
+ }
+ other => panic!(
+ "Parser `is_a` didn't succeed when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_while1_fail() {
+ use crate::bytes::take_while1;
+
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ fn while1_s(c: char) -> bool {
+ c == '9'
+ }
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while1(while1_s)(input)
+ }
+ match test(INPUT) {
+ Err(Err::Error(_)) => (),
+ other => panic!(
+ "Parser `take_while1` didn't fail when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn is_a_fail() {
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const MATCH: &str = "Ûñℓúçƙ¥";
+ fn test(input: &str) -> IResult<&str, &str> {
+ take_while1(MATCH)(input)
+ }
+ match test(INPUT) {
+ Err(Err::Error(_)) => (),
+ other => panic!(
+ "Parser `is_a` didn't fail when it should have. Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ fn take_until_error() {
+ use crate::bytes::take_until;
+
+ const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
+ const FIND: &str = "Ráñδô₥";
+
+ let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(Streaming(INPUT));
+ match res {
+ Err(Err::Incomplete(_)) => (),
+ other => panic!(
+ "Parser `take_until` didn't fail when it should have. \
+ Got `{:?}`.",
+ other
+ ),
+ };
+ }
+
+ #[test]
+ #[cfg(feature = "alloc")]
+ fn recognize_is_a() {
+ let a = "aabbab";
+ let b = "ababcd";
+
+ fn f(i: &str) -> IResult<&str, &str> {
+ many1(alt((tag("a"), tag("b")))).recognize().parse(i)
+ }
+
+ assert_eq!(f(&a[..]), Ok((&a[6..], &a[..])));
+ assert_eq!(f(&b[..]), Ok((&b[4..], &b[..4])));
+ }
+
+ #[test]
+ fn utf8_indexing() {
+ fn dot(i: &str) -> IResult<&str, &str> {
+ tag(".")(i)
+ }
+
+ let _ = dot("點");
+ }
+
+ #[cfg(feature = "alloc")]
+ #[test]
+ fn case_insensitive() {
+ fn test(i: &str) -> IResult<&str, &str> {
+ tag_no_case("ABcd")(i)
+ }
+ assert_eq!(test("aBCdefgh"), Ok(("efgh", "aBCd")));
+ assert_eq!(test("abcdefgh"), Ok(("efgh", "abcd")));
+ assert_eq!(test("ABCDefgh"), Ok(("efgh", "ABCD")));
+ }
+}
diff --git a/vendor/nom8/tests/arithmetic.rs b/vendor/nom8/tests/arithmetic.rs
new file mode 100644
index 000000000..35e1bf1cc
--- /dev/null
+++ b/vendor/nom8/tests/arithmetic.rs
@@ -0,0 +1,92 @@
+use nom8::prelude::*;
+use nom8::{
+ branch::alt,
+ character::{digit1 as digit, space0 as space},
+ multi::fold_many0,
+ sequence::delimited,
+ IResult,
+};
+
+// Parser definition
+
+use std::str::FromStr;
+
+// We parse any expr surrounded by parens, ignoring all whitespaces around those
+fn parens(i: &str) -> IResult<&str, i64> {
+ delimited(space, delimited("(", expr, ")"), space)(i)
+}
+
+// We transform an integer string into a i64, ignoring surrounding whitespaces
+// We look for a digit suite, and try to convert it.
+// If either str::from_utf8 or FromStr::from_str fail,
+// we fallback to the parens parser defined above
+fn factor(i: &str) -> IResult<&str, i64> {
+ alt((
+ delimited(space, digit, space).map_res(FromStr::from_str),
+ parens,
+ ))(i)
+}
+
+// We read an initial factor and for each time we find
+// a * or / operator followed by another factor, we do
+// the math by folding everything
+fn term(i: &str) -> IResult<&str, i64> {
+ let (i, init) = factor(i)?;
+
+ fold_many0(
+ (alt(('*', '/')), factor),
+ move || init,
+ |acc, (op, val): (char, i64)| {
+ if op == '*' {
+ acc * val
+ } else {
+ acc / val
+ }
+ },
+ )(i)
+}
+
+fn expr(i: &str) -> IResult<&str, i64> {
+ let (i, init) = term(i)?;
+
+ fold_many0(
+ (alt(('+', '-')), term),
+ move || init,
+ |acc, (op, val): (char, i64)| {
+ if op == '+' {
+ acc + val
+ } else {
+ acc - val
+ }
+ },
+ )(i)
+}
+
+#[test]
+fn factor_test() {
+ assert_eq!(factor("3"), Ok(("", 3)));
+ assert_eq!(factor(" 12"), Ok(("", 12)));
+ assert_eq!(factor("537 "), Ok(("", 537)));
+ assert_eq!(factor(" 24 "), Ok(("", 24)));
+}
+
+#[test]
+fn term_test() {
+ assert_eq!(term(" 12 *2 / 3"), Ok(("", 8)));
+ assert_eq!(term(" 2* 3 *2 *2 / 3"), Ok(("", 8)));
+ assert_eq!(term(" 48 / 3/2"), Ok(("", 8)));
+}
+
+#[test]
+fn expr_test() {
+ assert_eq!(expr(" 1 + 2 "), Ok(("", 3)));
+ assert_eq!(expr(" 12 + 6 - 4+ 3"), Ok(("", 17)));
+ assert_eq!(expr(" 1 + 2*3 + 4"), Ok(("", 11)));
+}
+
+#[test]
+fn parens_test() {
+ assert_eq!(expr(" ( 2 )"), Ok(("", 2)));
+ assert_eq!(expr(" 2* ( 3 + 4 ) "), Ok(("", 14)));
+ assert_eq!(expr(" 2*2 / ( 5 - 1) + 3"), Ok(("", 4)));
+}
diff --git a/vendor/nom8/tests/arithmetic_ast.rs b/vendor/nom8/tests/arithmetic_ast.rs
new file mode 100644
index 000000000..3e49dd2a1
--- /dev/null
+++ b/vendor/nom8/tests/arithmetic_ast.rs
@@ -0,0 +1,159 @@
+use std::fmt;
+use std::fmt::{Debug, Display, Formatter};
+
+use std::str::FromStr;
+
+use nom8::prelude::*;
+use nom8::{
+ branch::alt,
+ character::{digit1 as digit, multispace0 as multispace},
+ multi::many0,
+ sequence::{delimited, preceded},
+ IResult,
+};
+
+pub enum Expr {
+ Value(i64),
+ Add(Box<Expr>, Box<Expr>),
+ Sub(Box<Expr>, Box<Expr>),
+ Mul(Box<Expr>, Box<Expr>),
+ Div(Box<Expr>, Box<Expr>),
+ Paren(Box<Expr>),
+}
+
+#[derive(Debug)]
+pub enum Oper {
+ Add,
+ Sub,
+ Mul,
+ Div,
+}
+
+impl Display for Expr {
+ fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
+ use self::Expr::*;
+ match *self {
+ Value(val) => write!(format, "{}", val),
+ Add(ref left, ref right) => write!(format, "{} + {}", left, right),
+ Sub(ref left, ref right) => write!(format, "{} - {}", left, right),
+ Mul(ref left, ref right) => write!(format, "{} * {}", left, right),
+ Div(ref left, ref right) => write!(format, "{} / {}", left, right),
+ Paren(ref expr) => write!(format, "({})", expr),
+ }
+ }
+}
+
+impl Debug for Expr {
+ fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
+ use self::Expr::*;
+ match *self {
+ Value(val) => write!(format, "{}", val),
+ Add(ref left, ref right) => write!(format, "({:?} + {:?})", left, right),
+ Sub(ref left, ref right) => write!(format, "({:?} - {:?})", left, right),
+ Mul(ref left, ref right) => write!(format, "({:?} * {:?})", left, right),
+ Div(ref left, ref right) => write!(format, "({:?} / {:?})", left, right),
+ Paren(ref expr) => write!(format, "[{:?}]", expr),
+ }
+ }
+}
+
+fn parens(i: &str) -> IResult<&str, Expr> {
+ delimited(
+ multispace,
+ delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"),
+ multispace,
+ )(i)
+}
+
+fn factor(i: &str) -> IResult<&str, Expr> {
+ alt((
+ delimited(multispace, digit, multispace)
+ .map_res(FromStr::from_str)
+ .map(Expr::Value),
+ parens,
+ ))(i)
+}
+
+fn fold_exprs(initial: Expr, remainder: Vec<(Oper, Expr)>) -> Expr {
+ remainder.into_iter().fold(initial, |acc, pair| {
+ let (oper, expr) = pair;
+ match oper {
+ Oper::Add => Expr::Add(Box::new(acc), Box::new(expr)),
+ Oper::Sub => Expr::Sub(Box::new(acc), Box::new(expr)),
+ Oper::Mul => Expr::Mul(Box::new(acc), Box::new(expr)),
+ Oper::Div => Expr::Div(Box::new(acc), Box::new(expr)),
+ }
+ })
+}
+
+fn term(i: &str) -> IResult<&str, Expr> {
+ let (i, initial) = factor(i)?;
+ let (i, remainder) = many0(alt((
+ |i| {
+ let (i, mul) = preceded("*", factor)(i)?;
+ Ok((i, (Oper::Mul, mul)))
+ },
+ |i| {
+ let (i, div) = preceded("/", factor)(i)?;
+ Ok((i, (Oper::Div, div)))
+ },
+ )))(i)?;
+
+ Ok((i, fold_exprs(initial, remainder)))
+}
+
+fn expr(i: &str) -> IResult<&str, Expr> {
+ let (i, initial) = term(i)?;
+ let (i, remainder) = many0(alt((
+ |i| {
+ let (i, add) = preceded("+", term)(i)?;
+ Ok((i, (Oper::Add, add)))
+ },
+ |i| {
+ let (i, sub) = preceded("-", term)(i)?;
+ Ok((i, (Oper::Sub, sub)))
+ },
+ )))(i)?;
+
+ Ok((i, fold_exprs(initial, remainder)))
+}
+
+#[test]
+fn factor_test() {
+ assert_eq!(
+ factor(" 3 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("3")))
+ );
+}
+
+#[test]
+fn term_test() {
+ assert_eq!(
+ term(" 3 * 5 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("(3 * 5)")))
+ );
+}
+
+#[test]
+fn expr_test() {
+ assert_eq!(
+ expr(" 1 + 2 * 3 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("(1 + (2 * 3))")))
+ );
+ assert_eq!(
+ expr(" 1 + 2 * 3 / 4 - 5 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("((1 + ((2 * 3) / 4)) - 5)")))
+ );
+ assert_eq!(
+ expr(" 72 / 2 / 3 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("((72 / 2) / 3)")))
+ );
+}
+
+#[test]
+fn parens_test() {
+ assert_eq!(
+ expr(" ( 1 + 2 ) * 3 ").map(|(i, x)| (i, format!("{:?}", x))),
+ Ok(("", String::from("([(1 + 2)] * 3)")))
+ );
+}
diff --git a/vendor/nom8/tests/css.rs b/vendor/nom8/tests/css.rs
new file mode 100644
index 000000000..b3b308804
--- /dev/null
+++ b/vendor/nom8/tests/css.rs
@@ -0,0 +1,45 @@
+use nom8::bytes::{tag, take_while_m_n};
+use nom8::prelude::*;
+
+#[derive(Debug, PartialEq)]
+pub struct Color {
+ pub red: u8,
+ pub green: u8,
+ pub blue: u8,
+}
+
+fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
+ u8::from_str_radix(input, 16)
+}
+
+fn is_hex_digit(c: char) -> bool {
+ c.is_digit(16)
+}
+
+fn hex_primary(input: &str) -> IResult<&str, u8> {
+ take_while_m_n(2, 2, is_hex_digit)
+ .map_res(from_hex)
+ .parse(input)
+}
+
+fn hex_color(input: &str) -> IResult<&str, Color> {
+ let (input, _) = tag("#")(input)?;
+ let (input, (red, green, blue)) = (hex_primary, hex_primary, hex_primary).parse(input)?;
+
+ Ok((input, Color { red, green, blue }))
+}
+
+#[test]
+fn parse_color() {
+ assert_eq!(
+ hex_color("#2F14DF"),
+ Ok((
+ "",
+ Color {
+ red: 47,
+ green: 20,
+ blue: 223,
+ }
+ ))
+ );
+}
diff --git a/vendor/nom8/tests/custom_errors.rs b/vendor/nom8/tests/custom_errors.rs
new file mode 100644
index 000000000..8ca0d7b2d
--- /dev/null
+++ b/vendor/nom8/tests/custom_errors.rs
@@ -0,0 +1,49 @@
+#![allow(dead_code)]
+
+use nom8::bytes::tag;
+use nom8::character::digit1 as digit;
+use nom8::error::{ErrorKind, ParseError};
+use nom8::input::Streaming;
+#[cfg(feature = "alloc")]
+use nom8::multi::count;
+use nom8::prelude::*;
+use nom8::sequence::terminated;
+use nom8::IResult;
+
+#[derive(Debug)]
+pub struct CustomError(String);
+
+impl<'a> From<(&'a str, ErrorKind)> for CustomError {
+ fn from(error: (&'a str, ErrorKind)) -> Self {
+ CustomError(format!("error code was: {:?}", error))
+ }
+}
+
+impl<'a> ParseError<Streaming<&'a str>> for CustomError {
+ fn from_error_kind(_: Streaming<&'a str>, kind: ErrorKind) -> Self {
+ CustomError(format!("error code was: {:?}", kind))
+ }
+
+ fn append(_: Streaming<&'a str>, kind: ErrorKind, other: CustomError) -> Self {
+ CustomError(format!("{:?}\nerror code was: {:?}", other, kind))
+ }
+}
+
+fn test1(input: Streaming<&str>) -> IResult<Streaming<&str>, &str, CustomError> {
+ //fix_error!(input, CustomError, tag!("abcd"))
+ tag("abcd")(input)
+}
+
+fn test2(input: Streaming<&str>) -> IResult<Streaming<&str>, &str, CustomError> {
+ //terminated!(input, test1, fix_error!(CustomError, digit))
+ terminated(test1, digit)(input)
+}
+
+fn test3(input: Streaming<&str>) -> IResult<Streaming<&str>, &str, CustomError> {
+ test1.verify(|s: &str| s.starts_with("abcd")).parse(input)
+}
+
+#[cfg(feature = "alloc")]
+fn test4(input: Streaming<&str>) -> IResult<Streaming<&str>, Vec<&str>, CustomError> {
+ count(test1, 4)(input)
+}
diff --git a/vendor/nom8/tests/escaped.rs b/vendor/nom8/tests/escaped.rs
new file mode 100644
index 000000000..ed99128d3
--- /dev/null
+++ b/vendor/nom8/tests/escaped.rs
@@ -0,0 +1,28 @@
+use nom8::bytes::escaped;
+use nom8::bytes::one_of;
+use nom8::character::digit1;
+use nom8::{error::ErrorKind, Err, IResult};
+
+fn esc(s: &str) -> IResult<&str, &str, (&str, ErrorKind)> {
+ escaped(digit1, '\\', one_of("\"n\\"))(s)
+}
+
+#[cfg(feature = "alloc")]
+fn esc_trans(s: &str) -> IResult<&str, String, (&str, ErrorKind)> {
+ use nom8::bytes::escaped_transform;
+ escaped_transform(digit1, '\\', "n")(s)
+}
+
+#[test]
+fn test_escaped() {
+ assert_eq!(esc("abcd"), Err(Err::Error(("abcd", ErrorKind::Escaped))));
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn test_escaped_transform() {
+ assert_eq!(
+ esc_trans("abcd"),
+ Err(Err::Error(("abcd", ErrorKind::EscapedTransform)))
+ );
+}
diff --git a/vendor/nom8/tests/float.rs b/vendor/nom8/tests/float.rs
new file mode 100644
index 000000000..270db3001
--- /dev/null
+++ b/vendor/nom8/tests/float.rs
@@ -0,0 +1,46 @@
+use nom8::branch::alt;
+use nom8::character::digit1 as digit;
+use nom8::combinator::opt;
+use nom8::prelude::*;
+use nom8::sequence::delimited;
+use nom8::IResult;
+
+use std::str;
+use std::str::FromStr;
+
+fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> {
+ let float_bytes = alt((
+ delimited(digit, ".", opt(digit)),
+ delimited(opt(digit), ".", digit),
+ ))
+ .recognize();
+ let float_str = float_bytes.map_res(str::from_utf8);
+ float_str.map_res(FromStr::from_str).parse(i)
+}
+
+fn float(i: &[u8]) -> IResult<&[u8], f32> {
+ (opt(alt(("+", "-"))), unsigned_float)
+ .map(|(sign, value)| {
+ sign
+ .and_then(|s| if s[0] == b'-' { Some(-1f32) } else { None })
+ .unwrap_or(1f32)
+ * value
+ })
+ .parse(i)
+}
+
+#[test]
+fn unsigned_float_test() {
+ assert_eq!(unsigned_float(&b"123.456;"[..]), Ok((&b";"[..], 123.456)));
+ assert_eq!(unsigned_float(&b"0.123;"[..]), Ok((&b";"[..], 0.123)));
+ assert_eq!(unsigned_float(&b"123.0;"[..]), Ok((&b";"[..], 123.0)));
+ assert_eq!(unsigned_float(&b"123.;"[..]), Ok((&b";"[..], 123.0)));
+ assert_eq!(unsigned_float(&b".123;"[..]), Ok((&b";"[..], 0.123)));
+}
+
+#[test]
+fn float_test() {
+ assert_eq!(float(&b"123.456;"[..]), Ok((&b";"[..], 123.456)));
+ assert_eq!(float(&b"+123.456;"[..]), Ok((&b";"[..], 123.456)));
+ assert_eq!(float(&b"-123.456;"[..]), Ok((&b";"[..], -123.456)));
+}
diff --git a/vendor/nom8/tests/fnmut.rs b/vendor/nom8/tests/fnmut.rs
new file mode 100644
index 000000000..f96730420
--- /dev/null
+++ b/vendor/nom8/tests/fnmut.rs
@@ -0,0 +1,39 @@
+use nom8::{
+ bytes::tag,
+ multi::{many0, many0_count},
+};
+
+#[test]
+fn parse() {
+ let mut counter = 0;
+
+ let res = {
+ let mut parser = many0::<_, _, (), _>(|i| {
+ counter += 1;
+ tag("abc")(i)
+ });
+
+ parser("abcabcabcabc").unwrap()
+ };
+
+ println!("res: {:?}", res);
+ assert_eq!(counter, 5);
+}
+
+#[test]
+fn accumulate() {
+ let mut v = Vec::new();
+
+ let (_, count) = {
+ let mut parser = many0_count::<_, _, (), _>(|i| {
+ let (i, o) = tag("abc")(i)?;
+ v.push(o);
+ Ok((i, ()))
+ });
+ parser("abcabcabcabc").unwrap()
+ };
+
+ println!("v: {:?}", v);
+ assert_eq!(count, 4);
+ assert_eq!(v.len(), 4);
+}
diff --git a/vendor/nom8/tests/ini.rs b/vendor/nom8/tests/ini.rs
new file mode 100644
index 000000000..21c75aaa4
--- /dev/null
+++ b/vendor/nom8/tests/ini.rs
@@ -0,0 +1,202 @@
+use nom8::prelude::*;
+use nom8::{
+ bytes::take_while,
+ character::{alphanumeric1 as alphanumeric, multispace0 as multispace, space0 as space},
+ combinator::opt,
+ multi::many0,
+ sequence::{delimited, separated_pair, terminated},
+};
+
+use std::collections::HashMap;
+use std::str;
+
+fn category(i: &[u8]) -> IResult<&[u8], &str> {
+ delimited('[', take_while(|c| c != b']'), ']')
+ .map_res(str::from_utf8)
+ .parse(i)
+}
+
+fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> {
+ let (i, key) = alphanumeric.map_res(str::from_utf8).parse(i)?;
+ let (i, _) = (opt(space), '=', opt(space)).parse(i)?;
+ let (i, val) = take_while(|c| c != b'\n' && c != b';')
+ .map_res(str::from_utf8)
+ .parse(i)?;
+ let (i, _) = opt((';', take_while(|c| c != b'\n')))(i)?;
+ Ok((i, (key, val)))
+}
+
+fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> {
+ many0(terminated(key_value, opt(multispace)))
+ .map(|vec| vec.into_iter().collect())
+ .parse(i)
+}
+
+fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> {
+ let (i, category) = terminated(category, opt(multispace))(i)?;
+ let (i, keys) = keys_and_values(i)?;
+ Ok((i, (category, keys)))
+}
+
+fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> {
+ many0(separated_pair(
+ category,
+ opt(multispace),
+ many0(terminated(key_value, opt(multispace))).map(|vec: Vec<_>| vec.into_iter().collect()),
+ ))
+ .map(|vec: Vec<_>| vec.into_iter().collect())
+ .parse(i)
+}
+
+#[test]
+fn parse_category_test() {
+ let ini_file = &b"[category]
+
+parameter=value
+key = value2"[..];
+
+ let ini_without_category = &b"\n\nparameter=value
+key = value2"[..];
+
+ let res = category(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_category, "category")));
+}
+
+#[test]
+fn parse_key_value_test() {
+ let ini_file = &b"parameter=value
+key = value2"[..];
+
+ let ini_without_key_value = &b"\nkey = value2"[..];
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_key_value_with_space_test() {
+ let ini_file = &b"parameter = value
+key = value2"[..];
+
+ let ini_without_key_value = &b"\nkey = value2"[..];
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_key_value_with_comment_test() {
+ let ini_file = &b"parameter=value;abc
+key = value2"[..];
+
+ let ini_without_key_value = &b"\nkey = value2"[..];
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {:?} | o: ({:?},{:?})", str::from_utf8(i), o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_multiple_keys_and_values_test() {
+ let ini_file = &b"parameter=value;abc
+
+key = value2
+
+[category]"[..];
+
+ let ini_without_key_value = &b"[category]"[..];
+
+ let res = keys_and_values(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
+ _ => println!("error"),
+ }
+
+ let mut expected: HashMap<&str, &str> = HashMap::new();
+ expected.insert("parameter", "value");
+ expected.insert("key", "value2");
+ assert_eq!(res, Ok((ini_without_key_value, expected)));
+}
+
+#[test]
+fn parse_category_then_multiple_keys_and_values_test() {
+ //FIXME: there can be an empty line or a comment line after a category
+ let ini_file = &b"[abcd]
+parameter=value;abc
+
+key = value2
+
+[category]"[..];
+
+ let ini_after_parser = &b"[category]"[..];
+
+ let res = category_and_keys(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
+ _ => println!("error"),
+ }
+
+ let mut expected_h: HashMap<&str, &str> = HashMap::new();
+ expected_h.insert("parameter", "value");
+ expected_h.insert("key", "value2");
+ assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h))));
+}
+
+#[test]
+fn parse_multiple_categories_test() {
+ let ini_file = &b"[abcd]
+
+parameter=value;abc
+
+key = value2
+
+[category]
+parameter3=value3
+key4 = value4
+"[..];
+
+ let ini_after_parser = &b""[..];
+
+ let res = categories(ini_file);
+ //println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {:?} | o: {:?}", str::from_utf8(i), o),
+ _ => println!("error"),
+ }
+
+ let mut expected_1: HashMap<&str, &str> = HashMap::new();
+ expected_1.insert("parameter", "value");
+ expected_1.insert("key", "value2");
+ let mut expected_2: HashMap<&str, &str> = HashMap::new();
+ expected_2.insert("parameter3", "value3");
+ expected_2.insert("key4", "value4");
+ let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
+ expected_h.insert("abcd", expected_1);
+ expected_h.insert("category", expected_2);
+ assert_eq!(res, Ok((ini_after_parser, expected_h)));
+}
diff --git a/vendor/nom8/tests/ini_str.rs b/vendor/nom8/tests/ini_str.rs
new file mode 100644
index 000000000..d46013881
--- /dev/null
+++ b/vendor/nom8/tests/ini_str.rs
@@ -0,0 +1,217 @@
+use nom8::prelude::*;
+use nom8::{
+ bytes::{take_till, take_while, take_while1},
+ character::{alphanumeric1 as alphanumeric, space0 as space},
+ combinator::opt,
+ multi::many0,
+ sequence::{delimited, terminated},
+};
+
+use std::collections::HashMap;
+
+fn is_line_ending_or_comment(chr: char) -> bool {
+ chr == ';' || chr == '\n'
+}
+
+fn not_line_ending(i: &str) -> IResult<&str, &str> {
+ take_while(|c| c != '\r' && c != '\n')(i)
+}
+
+fn space_or_line_ending(i: &str) -> IResult<&str, &str> {
+ take_while1(" \r\n")(i)
+}
+
+fn category(i: &str) -> IResult<&str, &str> {
+ terminated(
+ delimited('[', take_while(|c| c != ']'), ']'),
+ opt(take_while1(" \r\n")),
+ )(i)
+}
+
+fn key_value(i: &str) -> IResult<&str, (&str, &str)> {
+ let (i, key) = alphanumeric(i)?;
+ let (i, _) = (opt(space), "=", opt(space)).parse(i)?;
+ let (i, val) = take_till(is_line_ending_or_comment)(i)?;
+ let (i, _) = opt(space)(i)?;
+ let (i, _) = opt((";", not_line_ending))(i)?;
+ let (i, _) = opt(space_or_line_ending)(i)?;
+
+ Ok((i, (key, val)))
+}
+
+fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> {
+ many0(key_value)(i)
+}
+
+fn keys_and_values(input: &str) -> IResult<&str, HashMap<&str, &str>> {
+ match keys_and_values_aggregator(input) {
+ Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())),
+ Err(e) => Err(e),
+ }
+}
+
+fn category_and_keys(i: &str) -> IResult<&str, (&str, HashMap<&str, &str>)> {
+ (category, keys_and_values).parse(i)
+}
+
+fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> {
+ many0(category_and_keys)(i)
+}
+
+fn categories(input: &str) -> IResult<&str, HashMap<&str, HashMap<&str, &str>>> {
+ match categories_aggregator(input) {
+ Ok((i, tuple_vec)) => Ok((i, tuple_vec.into_iter().collect())),
+ Err(e) => Err(e),
+ }
+}
+
+#[test]
+fn parse_category_test() {
+ let ini_file = "[category]
+
+parameter=value
+key = value2";
+
+ let ini_without_category = "parameter=value
+key = value2";
+
+ let res = category(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, o)) => println!("i: {} | o: {:?}", i, o),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_category, "category")));
+}
+
+#[test]
+fn parse_key_value_test() {
+ let ini_file = "parameter=value
+key = value2";
+
+ let ini_without_key_value = "key = value2";
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_key_value_with_space_test() {
+ let ini_file = "parameter = value
+key = value2";
+
+ let ini_without_key_value = "key = value2";
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_key_value_with_comment_test() {
+ let ini_file = "parameter=value;abc
+key = value2";
+
+ let ini_without_key_value = "key = value2";
+
+ let res = key_value(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, (o1, o2))) => println!("i: {} | o: ({:?},{:?})", i, o1, o2),
+ _ => println!("error"),
+ }
+
+ assert_eq!(res, Ok((ini_without_key_value, ("parameter", "value"))));
+}
+
+#[test]
+fn parse_multiple_keys_and_values_test() {
+ let ini_file = "parameter=value;abc
+
+key = value2
+
+[category]";
+
+ let ini_without_key_value = "[category]";
+
+ let res = keys_and_values(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
+ _ => println!("error"),
+ }
+
+ let mut expected: HashMap<&str, &str> = HashMap::new();
+ expected.insert("parameter", "value");
+ expected.insert("key", "value2");
+ assert_eq!(res, Ok((ini_without_key_value, expected)));
+}
+
+#[test]
+fn parse_category_then_multiple_keys_and_values_test() {
+ //FIXME: there can be an empty line or a comment line after a category
+ let ini_file = "[abcd]
+parameter=value;abc
+
+key = value2
+
+[category]";
+
+ let ini_after_parser = "[category]";
+
+ let res = category_and_keys(ini_file);
+ println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
+ _ => println!("error"),
+ }
+
+ let mut expected_h: HashMap<&str, &str> = HashMap::new();
+ expected_h.insert("parameter", "value");
+ expected_h.insert("key", "value2");
+ assert_eq!(res, Ok((ini_after_parser, ("abcd", expected_h))));
+}
+
+#[test]
+fn parse_multiple_categories_test() {
+ let ini_file = "[abcd]
+
+parameter=value;abc
+
+key = value2
+
+[category]
+parameter3=value3
+key4 = value4
+";
+
+ let res = categories(ini_file);
+ //println!("{:?}", res);
+ match res {
+ Ok((i, ref o)) => println!("i: {} | o: {:?}", i, o),
+ _ => println!("error"),
+ }
+
+ let mut expected_1: HashMap<&str, &str> = HashMap::new();
+ expected_1.insert("parameter", "value");
+ expected_1.insert("key", "value2");
+ let mut expected_2: HashMap<&str, &str> = HashMap::new();
+ expected_2.insert("parameter3", "value3");
+ expected_2.insert("key4", "value4");
+ let mut expected_h: HashMap<&str, HashMap<&str, &str>> = HashMap::new();
+ expected_h.insert("abcd", expected_1);
+ expected_h.insert("category", expected_2);
+ assert_eq!(res, Ok(("", expected_h)));
+}
diff --git a/vendor/nom8/tests/issues.rs b/vendor/nom8/tests/issues.rs
new file mode 100644
index 000000000..7ac0f0b6c
--- /dev/null
+++ b/vendor/nom8/tests/issues.rs
@@ -0,0 +1,248 @@
+//#![feature(trace_macros)]
+#![allow(dead_code)]
+#![cfg_attr(feature = "cargo-clippy", allow(redundant_closure))]
+
+use nom8::input::Streaming;
+use nom8::prelude::*;
+use nom8::{error::ErrorKind, Err, IResult, Needed};
+
+#[allow(dead_code)]
+struct Range {
+ start: char,
+ end: char,
+}
+
+pub fn take_char(input: &[u8]) -> IResult<&[u8], char> {
+ if !input.is_empty() {
+ Ok((&input[1..], input[0] as char))
+ } else {
+ Err(Err::Incomplete(Needed::new(1)))
+ }
+}
+
+#[cfg(feature = "std")]
+mod parse_int {
+ use nom8::input::HexDisplay;
+ use nom8::input::Streaming;
+ use nom8::prelude::*;
+ use nom8::{
+ character::{digit1 as digit, space1 as space},
+ combinator::opt,
+ multi::many0,
+ IResult,
+ };
+ use std::str;
+
+ fn parse_ints(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<i32>> {
+ many0(spaces_or_int)(input)
+ }
+
+ fn spaces_or_int(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, i32> {
+ println!("{}", input.to_hex(8));
+ let (i, _) = opt(space.complete())(input)?;
+ let (i, res) = digit
+ .complete()
+ .map(|x| {
+ println!("x: {:?}", x);
+ let result = str::from_utf8(x).unwrap();
+ println!("Result: {}", result);
+ println!("int is empty?: {}", x.is_empty());
+ match result.parse() {
+ Ok(i) => i,
+ Err(e) => panic!("UH OH! NOT A DIGIT! {:?}", e),
+ }
+ })
+ .parse(i)?;
+
+ Ok((i, res))
+ }
+
+ #[test]
+ fn issue_142() {
+ let subject = parse_ints(Streaming(&b"12 34 5689a"[..]));
+ let expected = Ok((Streaming(&b"a"[..]), vec![12, 34, 5689]));
+ assert_eq!(subject, expected);
+
+ let subject = parse_ints(Streaming(&b"12 34 5689 "[..]));
+ let expected = Ok((Streaming(&b" "[..]), vec![12, 34, 5689]));
+ assert_eq!(subject, expected)
+ }
+}
+
+#[test]
+fn usize_length_bytes_issue() {
+ use nom8::multi::length_data;
+ use nom8::number::be_u16;
+ let _: IResult<Streaming<&[u8]>, &[u8], (Streaming<&[u8]>, ErrorKind)> =
+ length_data(be_u16)(Streaming(b"012346"));
+}
+
+#[test]
+fn take_till_issue() {
+ use nom8::bytes::take_till;
+
+ fn nothing(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ take_till(|_| true)(i)
+ }
+
+ assert_eq!(
+ nothing(Streaming(b"")),
+ Err(Err::Incomplete(Needed::new(1)))
+ );
+ assert_eq!(
+ nothing(Streaming(b"abc")),
+ Ok((Streaming(&b"abc"[..]), &b""[..]))
+ );
+}
+
+#[test]
+fn issue_655() {
+ use nom8::character::{line_ending, not_line_ending};
+ fn twolines(i: Streaming<&str>) -> IResult<Streaming<&str>, (&str, &str)> {
+ let (i, l1) = not_line_ending(i)?;
+ let (i, _) = line_ending(i)?;
+ let (i, l2) = not_line_ending(i)?;
+ let (i, _) = line_ending(i)?;
+
+ Ok((i, (l1, l2)))
+ }
+
+ assert_eq!(
+ twolines(Streaming("foo\nbar\n")),
+ Ok((Streaming(""), ("foo", "bar")))
+ );
+ assert_eq!(
+ twolines(Streaming("féo\nbar\n")),
+ Ok((Streaming(""), ("féo", "bar")))
+ );
+ assert_eq!(
+ twolines(Streaming("foé\nbar\n")),
+ Ok((Streaming(""), ("foé", "bar")))
+ );
+ assert_eq!(
+ twolines(Streaming("foé\r\nbar\n")),
+ Ok((Streaming(""), ("foé", "bar")))
+ );
+}
+
+#[cfg(feature = "alloc")]
+fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
+ use nom8::bytes::{tag, take_till1};
+ use nom8::multi::separated_list0;
+
+ separated_list0(tag([0x0]), take_till1([0x0u8]))(i)
+}
+
+mod issue_647 {
+ use nom8::bytes::tag;
+ use nom8::multi::separated_list0;
+ use nom8::prelude::*;
+ use nom8::{error::Error, number::be_f64, Err, IResult};
+ pub type Input<'a> = nom8::input::Streaming<&'a [u8]>;
+
+ #[derive(PartialEq, Debug, Clone)]
+ struct Data {
+ c: f64,
+ v: Vec<f64>,
+ }
+
+ fn list<'a, 'b>(
+ input: Input<'a>,
+ _cs: &'b f64,
+ ) -> Result<(Input<'a>, Vec<f64>), Err<Error<Input<'a>>>> {
+ separated_list0(tag(",").complete(), be_f64.complete())(input)
+ }
+
+ fn data(input: Input<'_>) -> IResult<Input<'_>, Data> {
+ let (i, c) = be_f64(input)?;
+ let (i, _) = tag("\n")(i)?;
+ let (i, v) = list(i, &c)?;
+ Ok((i, Data { c, v }))
+ }
+}
+
+#[test]
+fn issue_848_overflow_incomplete_bits_to_bytes() {
+ fn take(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ use nom8::bytes::take;
+ take(0x2000000000000000_usize)(i)
+ }
+ fn parser(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ use nom8::bits::{bits, bytes};
+
+ bits(bytes(take))(i)
+ }
+ assert_eq!(
+ parser(Streaming(&b""[..])),
+ Err(Err::Failure(nom8::error_position!(
+ Streaming(&b""[..]),
+ ErrorKind::TooLarge
+ )))
+ );
+}
+
+#[test]
+fn issue_942() {
+ use nom8::error::{ContextError, ParseError};
+ pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str, &'static str>>(
+ i: &'a str,
+ ) -> IResult<&'a str, usize, E> {
+ use nom8::{bytes::one_of, multi::many0_count};
+ many0_count(one_of('a').context("char_a"))(i)
+ }
+ assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
+}
+
+#[test]
+fn issue_many_m_n_with_zeros() {
+ use nom8::multi::many_m_n;
+ let mut parser = many_m_n::<_, _, (), _>(0, 0, 'a');
+ assert_eq!(parser("aaa"), Ok(("aaa", vec![])));
+}
+
+#[test]
+fn issue_1027_convert_error_panic_nonempty() {
+ use nom8::error::{convert_error, VerboseError};
+
+ let input = "a";
+
+ let result: IResult<_, _, VerboseError<&str>> = ('a', 'b').parse(input);
+ let err = match result.unwrap_err() {
+ Err::Error(e) => e,
+ _ => unreachable!(),
+ };
+
+ let msg = convert_error(input, err);
+ assert_eq!(msg, "0: at line 1, in OneOf:\na\n ^\n\n",);
+}
+
+#[test]
+fn issue_1231_bits_expect_fn_closure() {
+ use nom8::bits::{bits, take};
+ use nom8::error::Error;
+ pub fn example(input: &[u8]) -> IResult<&[u8], (u8, u8)> {
+ bits::<_, _, Error<_>, _, _>((take(1usize), take(1usize)))(input)
+ }
+ assert_eq!(example(&[0xff]), Ok((&b""[..], (1, 1))));
+}
+
+#[test]
+fn issue_1282_findtoken_char() {
+ use nom8::bytes::one_of;
+ use nom8::error::Error;
+ let parser = one_of::<_, _, Error<_>, false>(&['a', 'b', 'c'][..]);
+ assert_eq!(parser("aaa"), Ok(("aa", 'a')));
+}
+
+#[test]
+fn issue_1459_clamp_capacity() {
+ // shouldn't panic
+ use nom8::multi::many_m_n;
+ let mut parser = many_m_n::<_, _, (), _>(usize::MAX, usize::MAX, 'a');
+ assert_eq!(parser("a"), Err(nom8::Err::Error(())));
+
+ // shouldn't panic
+ use nom8::multi::count;
+ let mut parser = count::<_, _, (), _>('a', usize::MAX);
+ assert_eq!(parser("a"), Err(nom8::Err::Error(())));
+}
diff --git a/vendor/nom8/tests/json.rs b/vendor/nom8/tests/json.rs
new file mode 100644
index 000000000..086b59c13
--- /dev/null
+++ b/vendor/nom8/tests/json.rs
@@ -0,0 +1,228 @@
+#![cfg(feature = "alloc")]
+
+use nom8::{
+ branch::alt,
+ bytes::{any, none_of, tag, take},
+ character::{f64, multispace0},
+ error::ParseError,
+ multi::{fold_many0, separated_list0},
+ sequence::{delimited, preceded, separated_pair},
+ IResult, Parser,
+};
+
+use std::collections::HashMap;
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum JsonValue {
+ Null,
+ Bool(bool),
+ Str(String),
+ Num(f64),
+ Array(Vec<JsonValue>),
+ Object(HashMap<String, JsonValue>),
+}
+
+fn boolean(input: &str) -> IResult<&str, bool> {
+ alt((tag("false").value(false), tag("true").value(true)))(input)
+}
+
+fn u16_hex(input: &str) -> IResult<&str, u16> {
+ take(4usize)
+ .map_res(|s| u16::from_str_radix(s, 16))
+ .parse(input)
+}
+
+fn unicode_escape(input: &str) -> IResult<&str, char> {
+ alt((
+ // Not a surrogate
+ u16_hex
+ .verify(|cp| !(0xD800..0xE000).contains(cp))
+ .map(|cp| cp as u32),
+ // See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details
+ separated_pair(u16_hex, "\\u", u16_hex)
+ .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low))
+ .map(|(high, low)| {
+ let high_ten = (high as u32) - 0xD800;
+ let low_ten = (low as u32) - 0xDC00;
+ (high_ten << 10) + low_ten + 0x10000
+ }),
+ ))
+ .map_opt(
+ // Could be probably replaced with .unwrap() or _unchecked due to the verify checks
+ std::char::from_u32,
+ )
+ .parse(input)
+}
+
+fn character(input: &str) -> IResult<&str, char> {
+ let (input, c) = none_of("\"")(input)?;
+ if c == '\\' {
+ alt((
+ any.map_res(|c| {
+ Ok(match c {
+ '"' | '\\' | '/' => c,
+ 'b' => '\x08',
+ 'f' => '\x0C',
+ 'n' => '\n',
+ 'r' => '\r',
+ 't' => '\t',
+ _ => return Err(()),
+ })
+ }),
+ preceded('u', unicode_escape),
+ ))(input)
+ } else {
+ Ok((input, c))
+ }
+}
+
+fn string(input: &str) -> IResult<&str, String> {
+ delimited(
+ '"',
+ fold_many0(character, String::new, |mut string, c| {
+ string.push(c);
+ string
+ }),
+ '"',
+ )(input)
+}
+
+fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, O, E>>(f: F) -> impl Parser<&'a str, O, E> {
+ delimited(multispace0, f, multispace0)
+}
+
+fn array(input: &str) -> IResult<&str, Vec<JsonValue>> {
+ delimited('[', ws(separated_list0(ws(','), json_value)), ']')(input)
+}
+
+fn object(input: &str) -> IResult<&str, HashMap<String, JsonValue>> {
+ delimited(
+ '{',
+ ws(separated_list0(
+ ws(','),
+ separated_pair(string, ws(':'), json_value),
+ )),
+ '}',
+ )
+ .map(|key_values| key_values.into_iter().collect())
+ .parse(input)
+}
+
+fn json_value(input: &str) -> IResult<&str, JsonValue> {
+ use JsonValue::*;
+
+ alt((
+ tag("null").value(Null),
+ boolean.map(Bool),
+ string.map(Str),
+ f64.map(Num),
+ array.map(Array),
+ object.map(Object),
+ ))(input)
+}
+
+fn json(input: &str) -> IResult<&str, JsonValue> {
+ ws(json_value).parse(input)
+}
+
+#[test]
+fn json_string() {
+ assert_eq!(string("\"\""), Ok(("", "".to_string())));
+ assert_eq!(string("\"abc\""), Ok(("", "abc".to_string())));
+ assert_eq!(
+ string("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""),
+ Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01——def".to_string())),
+ );
+ assert_eq!(string("\"\\uD83D\\uDE10\""), Ok(("", "😐".to_string())));
+
+ assert!(string("\"").is_err());
+ assert!(string("\"abc").is_err());
+ assert!(string("\"\\\"").is_err());
+ assert!(string("\"\\u123\"").is_err());
+ assert!(string("\"\\uD800\"").is_err());
+ assert!(string("\"\\uD800\\uD800\"").is_err());
+ assert!(string("\"\\uDC00\"").is_err());
+}
+
+#[test]
+fn json_object() {
+ use JsonValue::*;
+
+ let input = r#"{"a":42,"b":"x"}"#;
+
+ let expected = Object(
+ vec![
+ ("a".to_string(), Num(42.0)),
+ ("b".to_string(), Str("x".to_string())),
+ ]
+ .into_iter()
+ .collect(),
+ );
+
+ assert_eq!(json(input), Ok(("", expected)));
+}
+
+#[test]
+fn json_array() {
+ use JsonValue::*;
+
+ let input = r#"[42,"x"]"#;
+
+ let expected = Array(vec![Num(42.0), Str("x".to_string())]);
+
+ assert_eq!(json(input), Ok(("", expected)));
+}
+
+#[test]
+fn json_whitespace() {
+ use JsonValue::*;
+
+ let input = r#"
+ {
+ "null" : null,
+ "true" :true ,
+ "false": false ,
+ "number" : 123e4 ,
+ "string" : " abc 123 " ,
+ "array" : [ false , 1 , "two" ] ,
+ "object" : { "a" : 1.0 , "b" : "c" } ,
+ "empty_array" : [ ] ,
+ "empty_object" : { }
+ }
+ "#;
+
+ assert_eq!(
+ json(input),
+ Ok((
+ "",
+ Object(
+ vec![
+ ("null".to_string(), Null),
+ ("true".to_string(), Bool(true)),
+ ("false".to_string(), Bool(false)),
+ ("number".to_string(), Num(123e4)),
+ ("string".to_string(), Str(" abc 123 ".to_string())),
+ (
+ "array".to_string(),
+ Array(vec![Bool(false), Num(1.0), Str("two".to_string())])
+ ),
+ (
+ "object".to_string(),
+ Object(
+ vec![
+ ("a".to_string(), Num(1.0)),
+ ("b".to_string(), Str("c".to_string())),
+ ]
+ .into_iter()
+ .collect()
+ )
+ ),
+ ("empty_array".to_string(), Array(vec![]),),
+ ("empty_object".to_string(), Object(HashMap::new()),),
+ ]
+ .into_iter()
+ .collect()
+ )
+ ))
+ );
+}
diff --git a/vendor/nom8/tests/mp4.rs b/vendor/nom8/tests/mp4.rs
new file mode 100644
index 000000000..076b1161c
--- /dev/null
+++ b/vendor/nom8/tests/mp4.rs
@@ -0,0 +1,324 @@
+#![allow(dead_code)]
+
+use nom8::input::Streaming;
+use nom8::prelude::*;
+use nom8::{
+ branch::alt,
+ bytes::{tag, take},
+ error::ErrorKind,
+ multi::many0,
+ number::{be_f32, be_u16, be_u32, be_u64},
+ Err, IResult, Needed,
+};
+
+use std::str;
+
+fn mp4_box(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &[u8]> {
+ match be_u32(input) {
+ Ok((i, offset)) => {
+ let sz: usize = offset as usize;
+ if i.len() >= sz - 4 {
+ Ok((Streaming(&i[(sz - 4)..]), &i[0..(sz - 4)]))
+ } else {
+ Err(Err::Incomplete(Needed::new(offset as usize + 4)))
+ }
+ }
+ Err(e) => Err(e),
+ }
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+#[derive(PartialEq,Eq,Debug)]
+struct FileType<'a> {
+ major_brand: &'a str,
+ major_brand_version: &'a [u8],
+ compatible_brands: Vec<&'a str>
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+#[allow(non_snake_case)]
+#[derive(Debug,Clone)]
+pub struct Mvhd32 {
+ version_flags: u32, // actually:
+ // version: u8,
+ // flags: u24 // 3 bytes
+ created_date: u32,
+ modified_date: u32,
+ scale: u32,
+ duration: u32,
+ speed: f32,
+ volume: u16, // actually a 2 bytes decimal
+ /* 10 bytes reserved */
+ scaleA: f32,
+ rotateB: f32,
+ angleU: f32,
+ rotateC: f32,
+ scaleD: f32,
+ angleV: f32,
+ positionX: f32,
+ positionY: f32,
+ scaleW: f32,
+ preview: u64,
+ poster: u32,
+ selection: u64,
+ current_time: u32,
+ track_id: u32
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+#[allow(non_snake_case)]
+#[derive(Debug,Clone)]
+pub struct Mvhd64 {
+ version_flags: u32, // actually:
+ // version: u8,
+ // flags: u24 // 3 bytes
+ created_date: u64,
+ modified_date: u64,
+ scale: u32,
+ duration: u64,
+ speed: f32,
+ volume: u16, // actually a 2 bytes decimal
+ /* 10 bytes reserved */
+ scaleA: f32,
+ rotateB: f32,
+ angleU: f32,
+ rotateC: f32,
+ scaleD: f32,
+ angleV: f32,
+ positionX: f32,
+ positionY: f32,
+ scaleW: f32,
+ preview: u64,
+ poster: u32,
+ selection: u64,
+ current_time: u32,
+ track_id: u32
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+fn mvhd32(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MvhdBox> {
+ let (i, version_flags) = be_u32(i)?;
+ let (i, created_date) = be_u32(i)?;
+ let (i, modified_date) = be_u32(i)?;
+ let (i, scale) = be_u32(i)?;
+ let (i, duration) = be_u32(i)?;
+ let (i, speed) = be_f32(i)?;
+ let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal
+ let (i, _) = take(10_usize)(i)?;
+ let (i, scale_a) = be_f32(i)?;
+ let (i, rotate_b) = be_f32(i)?;
+ let (i, angle_u) = be_f32(i)?;
+ let (i, rotate_c) = be_f32(i)?;
+ let (i, scale_d) = be_f32(i)?;
+ let (i, angle_v) = be_f32(i)?;
+ let (i, position_x) = be_f32(i)?;
+ let (i, position_y) = be_f32(i)?;
+ let (i, scale_w) = be_f32(i)?;
+ let (i, preview) = be_u64(i)?;
+ let (i, poster) = be_u32(i)?;
+ let (i, selection) = be_u64(i)?;
+ let (i, current_time) = be_u32(i)?;
+ let (i, track_id) = be_u32(i)?;
+
+ let mvhd_box = MvhdBox::M32(Mvhd32 {
+ version_flags,
+ created_date,
+ modified_date,
+ scale,
+ duration,
+ speed,
+ volume,
+ scaleA: scale_a,
+ rotateB: rotate_b,
+ angleU: angle_u,
+ rotateC: rotate_c,
+ scaleD: scale_d,
+ angleV: angle_v,
+ positionX: position_x,
+ positionY: position_y,
+ scaleW: scale_w,
+ preview,
+ poster,
+ selection,
+ current_time,
+ track_id,
+ });
+
+ Ok((i, mvhd_box))
+}
+
+#[cfg_attr(rustfmt, rustfmt_skip)]
+fn mvhd64(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MvhdBox> {
+ let (i, version_flags) = be_u32(i)?;
+ let (i, created_date) = be_u64(i)?;
+ let (i, modified_date) = be_u64(i)?;
+ let (i, scale) = be_u32(i)?;
+ let (i, duration) = be_u64(i)?;
+ let (i, speed) = be_f32(i)?;
+ let (i, volume) = be_u16(i)?; // actually a 2 bytes decimal
+ let (i, _) = take(10_usize)(i)?;
+ let (i, scale_a) = be_f32(i)?;
+ let (i, rotate_b) = be_f32(i)?;
+ let (i, angle_u) = be_f32(i)?;
+ let (i, rotate_c) = be_f32(i)?;
+ let (i, scale_d) = be_f32(i)?;
+ let (i, angle_v) = be_f32(i)?;
+ let (i, position_x) = be_f32(i)?;
+ let (i, position_y) = be_f32(i)?;
+ let (i, scale_w) = be_f32(i)?;
+ let (i, preview) = be_u64(i)?;
+ let (i, poster) = be_u32(i)?;
+ let (i, selection) = be_u64(i)?;
+ let (i, current_time) = be_u32(i)?;
+ let (i, track_id) = be_u32(i)?;
+
+ let mvhd_box = MvhdBox::M64(Mvhd64 {
+ version_flags,
+ created_date,
+ modified_date,
+ scale,
+ duration,
+ speed,
+ volume,
+ scaleA: scale_a,
+ rotateB: rotate_b,
+ angleU: angle_u,
+ rotateC: rotate_c,
+ scaleD: scale_d,
+ angleV: angle_v,
+ positionX: position_x,
+ positionY: position_y,
+ scaleW: scale_w,
+ preview,
+ poster,
+ selection,
+ current_time,
+ track_id,
+ });
+
+ Ok((i, mvhd_box))
+}
+
+#[derive(Debug, Clone)]
+pub enum MvhdBox {
+ M32(Mvhd32),
+ M64(Mvhd64),
+}
+
+#[derive(Debug, Clone)]
+pub enum MoovBox {
+ Mdra,
+ Dref,
+ Cmov,
+ Rmra,
+ Iods,
+ Mvhd(MvhdBox),
+ Clip,
+ Trak,
+ Udta,
+}
+
+#[derive(Debug)]
+enum MP4BoxType {
+ Ftyp,
+ Moov,
+ Mdat,
+ Free,
+ Skip,
+ Wide,
+ Mdra,
+ Dref,
+ Cmov,
+ Rmra,
+ Iods,
+ Mvhd,
+ Clip,
+ Trak,
+ Udta,
+ Unknown,
+}
+
+#[derive(Debug)]
+struct MP4BoxHeader {
+ length: u32,
+ tag: MP4BoxType,
+}
+
+fn brand_name(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, &str> {
+ take(4_usize).map_res(str::from_utf8).parse(input)
+}
+
+fn filetype_parser(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, FileType<'_>> {
+ let (i, name) = brand_name(input)?;
+ let (i, version) = take(4_usize)(i)?;
+ let (i, brands) = many0(brand_name)(i)?;
+
+ let ft = FileType {
+ major_brand: name,
+ major_brand_version: version,
+ compatible_brands: brands,
+ };
+ Ok((i, ft))
+}
+
+fn mvhd_box(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MvhdBox> {
+ let res = if input.len() < 100 {
+ Err(Err::Incomplete(Needed::new(100)))
+ } else if input.len() == 100 {
+ mvhd32(input)
+ } else if input.len() == 112 {
+ mvhd64(input)
+ } else {
+ Err(Err::Error(nom8::error_position!(
+ input,
+ ErrorKind::TooLarge
+ )))
+ };
+ println!("res: {:?}", res);
+ res
+}
+
+fn unknown_box_type(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MP4BoxType> {
+ Ok((input, MP4BoxType::Unknown))
+}
+
+fn box_type(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MP4BoxType> {
+ alt((
+ tag("ftyp").map(|_| MP4BoxType::Ftyp),
+ tag("moov").map(|_| MP4BoxType::Moov),
+ tag("mdat").map(|_| MP4BoxType::Mdat),
+ tag("free").map(|_| MP4BoxType::Free),
+ tag("skip").map(|_| MP4BoxType::Skip),
+ tag("wide").map(|_| MP4BoxType::Wide),
+ unknown_box_type,
+ ))(input)
+}
+
+// warning, an alt combinator with 9 branches containing a tag combinator
+// can make the compilation very slow. Use functions as sub parsers,
+// or split into multiple alt parsers if it gets slow
+fn moov_type(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MP4BoxType> {
+ alt((
+ tag("mdra").map(|_| MP4BoxType::Mdra),
+ tag("dref").map(|_| MP4BoxType::Dref),
+ tag("cmov").map(|_| MP4BoxType::Cmov),
+ tag("rmra").map(|_| MP4BoxType::Rmra),
+ tag("iods").map(|_| MP4BoxType::Iods),
+ tag("mvhd").map(|_| MP4BoxType::Mvhd),
+ tag("clip").map(|_| MP4BoxType::Clip),
+ tag("trak").map(|_| MP4BoxType::Trak),
+ tag("udta").map(|_| MP4BoxType::Udta),
+ ))(input)
+}
+
+fn box_header(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MP4BoxHeader> {
+ let (i, length) = be_u32(input)?;
+ let (i, tag) = box_type(i)?;
+ Ok((i, MP4BoxHeader { length, tag }))
+}
+
+fn moov_header(input: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, MP4BoxHeader> {
+ let (i, length) = be_u32(input)?;
+ let (i, tag) = moov_type(i)?;
+ Ok((i, MP4BoxHeader { length, tag }))
+}
diff --git a/vendor/nom8/tests/multiline.rs b/vendor/nom8/tests/multiline.rs
new file mode 100644
index 000000000..c62ee5915
--- /dev/null
+++ b/vendor/nom8/tests/multiline.rs
@@ -0,0 +1,31 @@
+use nom8::{
+ character::{alphanumeric1 as alphanumeric, line_ending as eol},
+ multi::many0,
+ sequence::terminated,
+ IResult,
+};
+
+pub fn end_of_line(input: &str) -> IResult<&str, &str> {
+ if input.is_empty() {
+ Ok((input, input))
+ } else {
+ eol(input)
+ }
+}
+
+pub fn read_line(input: &str) -> IResult<&str, &str> {
+ terminated(alphanumeric, end_of_line)(input)
+}
+
+pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> {
+ many0(read_line)(input)
+}
+
+#[cfg(feature = "alloc")]
+#[test]
+fn read_lines_test() {
+ let res = Ok(("", vec!["Duck", "Dog", "Cow"]));
+
+ assert_eq!(read_lines("Duck\nDog\nCow\n"), res);
+ assert_eq!(read_lines("Duck\nDog\nCow"), res);
+}
diff --git a/vendor/nom8/tests/overflow.rs b/vendor/nom8/tests/overflow.rs
new file mode 100644
index 000000000..5a771ea30
--- /dev/null
+++ b/vendor/nom8/tests/overflow.rs
@@ -0,0 +1,162 @@
+#![cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))]
+#![cfg(target_pointer_width = "64")]
+
+use nom8::bytes::take;
+use nom8::input::Streaming;
+#[cfg(feature = "alloc")]
+use nom8::multi::{length_data, many0};
+#[cfg(feature = "alloc")]
+use nom8::number::be_u64;
+use nom8::prelude::*;
+use nom8::{Err, Needed};
+
+// Parser definition
+
+// We request a length that would trigger an overflow if computing consumed + requested
+fn parser02(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (&[u8], &[u8])> {
+ (take(1_usize), take(18446744073709551615_usize)).parse(i)
+}
+
+#[test]
+fn overflow_incomplete_tuple() {
+ assert_eq!(
+ parser02(Streaming(&b"3"[..])),
+ Err(Err::Incomplete(Needed::new(18446744073709551615)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_bytes() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many0(length_data(be_u64))(i)
+ }
+
+ // Trigger an overflow in length_data
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551615)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many0() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many0(length_data(be_u64))(i)
+ }
+
+ // Trigger an overflow in many0
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many1() {
+ use nom8::multi::many1;
+
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many1(length_data(be_u64))(i)
+ }
+
+ // Trigger an overflow in many1
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many_till() {
+ use nom8::{bytes::tag, multi::many_till};
+
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, (Vec<&[u8]>, &[u8])> {
+ many_till(length_data(be_u64), tag("abc"))(i)
+ }
+
+ // Trigger an overflow in many_till
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_many_m_n() {
+ use nom8::multi::many_m_n;
+
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many_m_n(2, 4, length_data(be_u64))(i)
+ }
+
+ // Trigger an overflow in many_m_n
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_count() {
+ use nom8::multi::count;
+
+ fn counter(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ count(length_data(be_u64), 2)(i)
+ }
+
+ assert_eq!(
+ counter(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xef"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551599)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_count() {
+ use nom8::multi::length_count;
+ use nom8::number::be_u8;
+
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ length_count(be_u8, length_data(be_u64))(i)
+ }
+
+ assert_eq!(
+ multi(Streaming(
+ &b"\x04\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xee"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551598)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
+fn overflow_incomplete_length_data() {
+ fn multi(i: Streaming<&[u8]>) -> IResult<Streaming<&[u8]>, Vec<&[u8]>> {
+ many0(length_data(be_u64))(i)
+ }
+
+ assert_eq!(
+ multi(Streaming(
+ &b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]
+ )),
+ Err(Err::Incomplete(Needed::new(18446744073709551615)))
+ );
+}
diff --git a/vendor/nom8/tests/reborrow_fold.rs b/vendor/nom8/tests/reborrow_fold.rs
new file mode 100644
index 000000000..9041131fd
--- /dev/null
+++ b/vendor/nom8/tests/reborrow_fold.rs
@@ -0,0 +1,30 @@
+#![allow(dead_code)]
+// #![allow(unused_variables)]
+
+use std::str;
+
+use nom8::bytes::take_till1;
+use nom8::multi::fold_many0;
+use nom8::prelude::*;
+use nom8::sequence::delimited;
+use nom8::IResult;
+
+fn atom<'a>(_tomb: &'a mut ()) -> impl FnMut(&'a [u8]) -> IResult<&'a [u8], String> {
+ move |input| {
+ take_till1(" \t\r\n")
+ .map_res(str::from_utf8)
+ .map(ToString::to_string)
+ .parse(input)
+ }
+}
+
+// FIXME: should we support the use case of borrowing data mutably in a parser?
+fn list<'a>(i: &'a [u8], tomb: &'a mut ()) -> IResult<&'a [u8], String> {
+ delimited(
+ '(',
+ fold_many0(atom(tomb), String::new, |acc: String, next: String| {
+ acc + next.as_str()
+ }),
+ ')',
+ )(i)
+}