chore: checkpoint before Python removal

This commit is contained in:
2026-03-26 22:33:59 +00:00
parent 683cec9307
commit e568ddf82a
29972 changed files with 11269302 additions and 2 deletions

1
vendor/nom/.cargo-checksum.json vendored Normal file
View File

@@ -0,0 +1 @@
{"files":{".cargo_vcs_info.json":"e10f44062736af6c6ad421467db3f7d0ccc3c1dc65a2ee1d5e9530e0d793e60c","CHANGELOG.md":"d526d20deb0dd12f2f6e528f786029f4e14c880cb75f2d82ec8807364c74be31","Cargo.lock":"2b4341e0af086bbac33e82e11353047449fd66cc1b86770133bac8007eb5da95","Cargo.toml":"0c4c034419168b542235727a352b8c3d12476d839480a6e933f4fc7966c6a812","Cargo.toml.orig":"74762db5ea3fb7dbb7aed12c1851e05cca0a37c8fd7bfef82e0d5b0d9aef7e95","LICENSE":"4dbda04344456f09a7a588140455413a9ac59b6b26a1ef7cdf9c800c012d87f0","README.md":"f0f855c2c2e4b5a69c7e901440665ee85aca748c6d73ea14f1ca952318a61fbe","doc/nom_recipes.md":"432e837e6b280ad9842868d20076d43d8dcdd9aea9ed6ab32a6e62c2a00c5d38","src/bits/complete.rs":"467122d4056c0e2655fd4ba087f1ee5042fb86453b662ae7ebe2e42c0066a09a","src/bits/mod.rs":"6b8e799f513834da948525002cb0e2a0b5da5f71715c443ede31bdd18424df36","src/bits/streaming.rs":"dfba58d569c1ab89f6cb9e33153775ed19d45385e39d5047eb717c44b07e3cc0","src/branch/mod.rs":"f99d29c4b001b500cc5226ccff5c13a250da06cc7428e76b3bc61125fb11c5d1","src/branch/tests.rs":"fb8198d2a6945bbefc153217634a306d27fe465664472ce29c61421841b3e4a6","src/bytes/complete.rs":"40682a06b92fcbd3f4e7c8b266b12dcfc797b715cc55d5f5c5073616a55efe1b","src/bytes/mod.rs":"219f031a11dab2ae1d2a08b37a1c1a7fc641c7e1338a42826f9809dc7c309510","src/bytes/streaming.rs":"6c1e454839c99fcb19704ee82b1b74b5492073dc71faa364694853d2a564ca11","src/bytes/tests.rs":"6ae0aa7a97daa291ec68aa20cc8635ac7665374194c665251240e3534dab991c","src/character/complete.rs":"1d0c6a7f9cfc97164f17c87e9125981c2a0814904d0de2a7ba6f4019d3d30ca0","src/character/mod.rs":"e713c9a56e5c3e2757b4685048139509fe58e18985c06be9192fbb8bbae3213e","src/character/streaming.rs":"b883f3d745d16b0ec163c5d14feae1e255f2809da540eb507c2d63e0ac146e10","src/character/tests.rs":"faa8053912f374bb5228f5269e9f8aa13e60c23d239d6acae39463892018b348","src/combinator/mod.rs":"a75359d9f86a2494c850d64e7b4dcc4550509ec1fae2dfb49aba5edc9c62e2ab","src/combinator/tests.rs":"46290c938f132a8a01aafd58d6e63e6da851282a22c1db41a430d1d780b4373d","src/error.rs":"4a73ae2a2743b3dd029ad76ebed264af73fef875d061189abdaabf026acb89a8","src/internal.rs":"c3df969cc76196d2f9903d9ff2c0ce8a58c766efbf92216f4797d945a6f980ee","src/lib.rs":"6022ac91a16e3f00f458cac7a198a81fcd6bee5dc9e75903d3438f447eb70fd7","src/macros.rs":"11ac3dee346e5bf61015f328975cf6ea6f438683eb3b8b6c7c8e6383b0c5b7af","src/multi/mod.rs":"6426717e34019ef32c00cc86d8b2683f7c4510e2c056e7762cce7595dab14bce","src/multi/tests.rs":"6107a64f4bb6675fbb93c5835f89992d03252e98fa29a86a44cf8894050c9ab7","src/number/complete.rs":"63ad29969e4f20dcfd7acc6fc08e60f9e3d90b1c3e574267ef274f56468464d7","src/number/mod.rs":"353111b0cadc422ee4b89ac4881262187276a39f5a65d0f391fb3f2df7c9d35b","src/number/streaming.rs":"a18ff0a3aaa79d68956c0dae1ecd6bc997edc0ea2b568208a6a2542acd80bfe5","src/sequence/mod.rs":"6e7e65213283c2fbfa2297fae0ae1d1f02a2fb6ee5e79dde761974054815814c","src/sequence/tests.rs":"2a80de26fd6d8725626c1ae2009b17ca6fda38b1f993426cb2706c05ccb5737a","src/str.rs":"c781cd3f7eb00e3d9d1426302311c7f0594a912391e615af4f36cc84c6d35751","src/traits.rs":"3bcc85e2272c75dfcd915d1be5e68243c3ac3282f36530021b31ce6f02ddca65","tests/arithmetic.rs":"06250fb1f4a6c244962dbf303d4d6013735dcabc39a706bff2046f2e8c6e8c28","tests/arithmetic_ast.rs":"0556e8fddc6897859615ccc36a033e64230d0c95d22e271522daff1513757bc7","tests/css.rs":"38efa43acc5db47a26e38992418ccd90e2700329d6fa2bb0f02a4ee7b9abb888","tests/custom_errors.rs":"70a03680a51491963ce35db88b4b82963645fb93f28330375c4041db53a4d1a3","tests/escaped.rs":"c25987ea6d9a7dde74d58a49c332d223da3a495569cb79e3fe921bce51729ead","tests/expression_ast.rs":"c6ddae04e679c9b7fab38ac791165a9f6b017765be0d687c2f49ec3d1afe174a","tests/float.rs":"8f1726722408d84d73c0c228ec7030b44a7c6dbafdf64aa9c4ced7ebced3b38c","tests/fnmut.rs":"5a7fc3fc894b1f4ebe59c7e4031c12961127141aeab29b9a94a4c013beabb5fc","tests/ini.rs":"f3abce04662afac6a838dd51aa152f227a0f631690f7149f18aa2c869de90fd9","tests/ini_str.rs":"a72dfd595fbffffd3acd70101a72cd60b91155e5fe13c2f5b4e92b51aa7ea2ab","tests/issues.rs":"1362fe74beb28042b25970010e20727ee0ed73082427c34f6e686bcc4ff3fc0e","tests/json.rs":"5f18e41dc7b798c2e2791704ffaefdc63339b8b9d712abe4a4a02e8db129ff05","tests/mp4.rs":"f51615d6e2d0a91f5a8f047f76d022bc6a47a2c2359d92c3e7d65e5e0ed30610","tests/multiline.rs":"d7367add37522a0f6ee51df2f3b22f2cf17d3edf3eb96ec1761d002e1231bd6e","tests/overflow.rs":"cdcb03394274f18af9931fbe391ac39d40d3c8c58b731b5ca90a02663fea131c","tests/reborrow_fold.rs":"bad74bd77d4ea5b485d0a74ffcdb352f11bdde4666bd1706e9d1fa881896d4c3"},"package":"df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"}

6
vendor/nom/.cargo_vcs_info.json vendored Normal file
View File

@@ -0,0 +1,6 @@
{
"git": {
"sha1": "2cec1b3e4c9ccac62c902d60c00de6d1549ccbe1"
},
"path_in_vcs": ""
}

1607
vendor/nom/CHANGELOG.md vendored Normal file

File diff suppressed because it is too large Load Diff

382
vendor/nom/Cargo.lock generated vendored Normal file
View File

@@ -0,0 +1,382 @@
# 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 = "cc"
version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
[[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 = "errno"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
dependencies = [
"errno-dragonfly",
"libc",
"windows-sys",
]
[[package]]
name = "errno-dragonfly"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
dependencies = [
"cc",
"libc",
]
[[package]]
name = "fastrand"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
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.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "hermit-abi"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
[[package]]
name = "instant"
version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
"cfg-if",
]
[[package]]
name = "io-lifetimes"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
dependencies = [
"hermit-abi",
"libc",
"windows-sys",
]
[[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.146"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
[[package]]
name = "linux-raw-sys"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
[[package]]
name = "memchr"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "nom"
version = "8.0.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.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[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.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
dependencies = [
"bitflags",
]
[[package]]
name = "regex-syntax"
version = "0.6.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
[[package]]
name = "rustix"
version = "0.37.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"windows-sys",
]
[[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.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6"
dependencies = [
"autocfg",
"cfg-if",
"fastrand",
"redox_syscall",
"rustix",
"windows-sys",
]
[[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 = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
dependencies = [
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
[[package]]
name = "windows_i686_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
[[package]]
name = "windows_i686_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"

166
vendor/nom/Cargo.toml vendored Normal file
View File

@@ -0,0 +1,166 @@
# 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 = "2021"
rust-version = "1.65.0"
name = "nom"
version = "8.0.0"
authors = ["contact@geoffroycouprie.com"]
build = false
include = [
"CHANGELOG.md",
"LICENSE",
"README.md",
".gitignore",
"Cargo.toml",
"src/*.rs",
"src/*/*.rs",
"tests/*.rs",
"doc/nom_recipes.md",
]
autobins = false
autoexamples = false
autotests = false
autobenches = false
description = "A byte-oriented, zero-copy, parser combinators library"
documentation = "https://docs.rs/nom"
readme = "README.md"
keywords = [
"parser",
"parser-combinators",
"parsing",
"streaming",
"bit",
]
categories = ["parsing"]
license = "MIT"
repository = "https://github.com/rust-bakery/nom"
[package.metadata.docs.rs]
all-features = true
features = [
"alloc",
"std",
"docsrs",
]
rustdoc-args = ["--generate-link-to-definition"]
[profile.bench]
lto = true
codegen-units = 1
debug = 2
[lib]
name = "nom"
path = "src/lib.rs"
[[test]]
name = "arithmetic"
path = "tests/arithmetic.rs"
[[test]]
name = "arithmetic_ast"
path = "tests/arithmetic_ast.rs"
required-features = ["alloc"]
[[test]]
name = "css"
path = "tests/css.rs"
[[test]]
name = "custom_errors"
path = "tests/custom_errors.rs"
[[test]]
name = "escaped"
path = "tests/escaped.rs"
[[test]]
name = "expression_ast"
path = "tests/expression_ast.rs"
required-features = ["alloc"]
[[test]]
name = "float"
path = "tests/float.rs"
[[test]]
name = "fnmut"
path = "tests/fnmut.rs"
required-features = ["alloc"]
[[test]]
name = "ini"
path = "tests/ini.rs"
required-features = ["alloc"]
[[test]]
name = "ini_str"
path = "tests/ini_str.rs"
required-features = ["alloc"]
[[test]]
name = "issues"
path = "tests/issues.rs"
required-features = ["alloc"]
[[test]]
name = "json"
path = "tests/json.rs"
[[test]]
name = "mp4"
path = "tests/mp4.rs"
required-features = ["alloc"]
[[test]]
name = "multiline"
path = "tests/multiline.rs"
required-features = ["alloc"]
[[test]]
name = "overflow"
path = "tests/overflow.rs"
[[test]]
name = "reborrow_fold"
path = "tests/reborrow_fold.rs"
[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"]
docsrs = []
std = [
"alloc",
"memchr/std",
]
[badges.coveralls]
branch = "main"
repository = "Geal/nom"
service = "github"
[badges.maintenance]
status = "actively-developed"
[badges.travis-ci]
repository = "Geal/nom"

20
vendor/nom/LICENSE vendored Normal file
View File

@@ -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.

345
vendor/nom/README.md vendored Normal file
View File

@@ -0,0 +1,345 @@
# nom, eating data byte by byte
[![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/rust-bakery/nom/actions/workflows/ci.yml/badge.svg)](https://github.com/rust-bakery/nom/actions/workflows/ci.yml)
[![Coverage Status](https://coveralls.io/repos/github/rust-bakery/nom/badge.svg?branch=main)](https://coveralls.io/github/rust-bakery/nom?branch=main)
[![crates.io Version](https://img.shields.io/crates/v/nom.svg)](https://crates.io/crates/nom)
[![Minimum rustc version](https://img.shields.io/badge/rustc-1.56.0+-lightgray.svg)](#rust-version-requirements-msrv)
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 nom::{
bytes::complete::{tag, take_while_m_n},
combinator::map_res,
sequence::Tuple,
IResult,
Parser,
};
#[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> {
map_res(
take_while_m_n(2, 2, is_hex_digit),
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() {
println!("{:?}", hex_color("#2F14DF"))
}
#[test]
fn parse_color() {
assert_eq!(
hex_color("#2F14DF"),
Ok((
"",
Color {
red: 47,
green: 20,
blue: 223,
}
))
);
}
```
## Documentation
- [Reference documentation](https://docs.rs/nom)
- [The Nominomicon: A Guide To Using Nom](https://tfpk.github.io/nominomicon/)
- [Various design documents and tutorials](https://github.com/rust-bakery/nom/tree/main/doc)
- [List of combinators and their behaviour](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md)
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/blob/main/lib/src/protocol/h2/parser.rs)
- [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)
- [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/blob/main/lib/src/protocol/h2/parser.rs)
- [Using nom with generators](https://github.com/rust-bakery/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/rust-bakery/parser_benchmarks).
## Rust version requirements (MSRV)
The 7.0 series of nom supports **Rustc version 1.56 or greater**.
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),
[Email](https://github.com/deuxfleurs-org/eml-codec),
[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/rust-bakery/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-rs/tree/master/vimwiki) & [vimwiki_macros](https://github.com/chipsenkbeil/vimwiki-rs/tree/master/vimwiki_macros),
[Kconfig language](https://github.com/Mcdostone/nom-kconfig), [Askama templates](https://crates.io/crates/askama_parser/)
- 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/rozbb/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-engine/tree/dev/csml_interpreter),
[Wasm](https://github.com/fabrizio-m/wasm-nom),
[Pseudocode](https://github.com/Gungy2/pseudocod),
[Filter for MeiliSearch](https://github.com/meilisearch/meilisearch),
[PotterScript](https://github.com/fmiras/potterscript)
- 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/dust-engine/dot_vox),
[MIDI](https://github.com/derekdreery/nom-midi-rs),
[SWF](https://github.com/open-flash/swf-parser),
[WAVE](https://github.com/Noise-Labs/wave),
[Matroska (MKV)](https://github.com/rust-av/matroska),
[Exif/Metadata parser for JPEG/HEIF/HEIC/MOV/MP4](https://github.com/mindeng/nom-exif)
- 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) ([alt](https://github.com/duesee/imap-codec)),
[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),
[V5, V7, V9, IPFIX / Netflow v10](https://github.com/mikemiles-dev/netflow_parser),
[GTP](https://github.com/fuerstenau/gorrosion-gtp),
[SIP](https://github.com/kurotych/sipcore/tree/master/crates/sipmsg),
[SMTP](https://github.com/Ekleog/kannader),
[Prometheus](https://github.com/vectordotdev/vector/blob/master/lib/prometheus-parser/src/line.rs),
[DNS](https://github.com/adiSuper94/dns-rs)
- Language specifications:
[BNF](https://github.com/shnewto/bnf)
- Misc formats:
[Game Boy 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),
[NBT](https://github.com/phoenixr-codes/mcnbt)
Want to create a new parser using `nom`? A list of not yet implemented formats is available [here](https://github.com/rust-bakery/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/rust-bakery/nom/graphs/contributors">
<img src="https://contributors-img.web.app/image?repo=rust-bakery/nom" />
</a>

401
vendor/nom/doc/nom_recipes.md vendored Normal file
View File

@@ -0,0 +1,401 @@
# Common recipes to build nom parsers
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 nom::{
IResult,
Parser,
error::ParseError,
sequence::delimited,
character::complete::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`.
pub fn ws<'a, O, E: ParseError<&'a str>, F>(
inner: F,
) -> impl Parser<&'a str, Output = O, Error = E>
where
F: Parser<&'a str, Output = O, Error = 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 nom::{
IResult,
Parser,
error::ParseError,
combinator::value,
sequence::pair,
bytes::complete::is_not,
character::complete::char,
};
pub fn peol_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E>
{
value(
(), // Output is thrown away.
pair(char('%'), is_not("\n\r"))
).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 nom::{
IResult,
Parser,
error::ParseError,
combinator::value,
bytes::complete::{tag, take_until},
};
pub fn pinline_comment<'a, E: ParseError<&'a str>>(i: &'a str) -> IResult<&'a str, (), E> {
value(
(), // Output is thrown away.
(
tag("(*"),
take_until("*)"),
tag("*)")
)
).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 nom::{
IResult,
Parser,
branch::alt,
multi::many0_count,
combinator::recognize,
sequence::pair,
character::complete::{alpha1, alphanumeric1},
bytes::complete::tag,
};
pub fn identifier(input: &str) -> IResult<&str, &str> {
recognize(
pair(
alt((alpha1, tag("_"))),
many0_count(alt((alphanumeric1, tag("_"))))
)
).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/rust-bakery/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 hexadecimal 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 nom::{
IResult,
Parser,
branch::alt,
multi::{many0, many1},
combinator::recognize,
sequence::{preceded, terminated},
character::complete::{char, one_of},
bytes::complete::tag,
};
fn hexadecimal(input: &str) -> IResult<&str, &str> { // <'a, E: ParseError<&'a str>>
preceded(
alt((tag("0x"), tag("0X"))),
recognize(
many1(
terminated(one_of("0123456789abcdefABCDEF"), many0(char('_')))
)
)
).parse(input)
}
```
If you want it to return the integer value instead, use map:
```rust
use nom::{
IResult,
Parser,
branch::alt,
multi::{many0, many1},
combinator::{map_res, recognize},
sequence::{preceded, terminated},
character::complete::{char, one_of},
bytes::complete::tag,
};
fn hexadecimal_value(input: &str) -> IResult<&str, i64> {
map_res(
preceded(
alt((tag("0x"), tag("0X"))),
recognize(
many1(
terminated(one_of("0123456789abcdefABCDEF"), many0(char('_')))
)
)
),
|out: &str| i64::from_str_radix(&str::replace(&out, "_", ""), 16)
).parse(input)
}
```
#### Octal
```rust
use nom::{
IResult,
Parser,
branch::alt,
multi::{many0, many1},
combinator::recognize,
sequence::{preceded, terminated},
character::complete::{char, one_of},
bytes::complete::tag,
};
fn octal(input: &str) -> IResult<&str, &str> {
preceded(
alt((tag("0o"), tag("0O"))),
recognize(
many1(
terminated(one_of("01234567"), many0(char('_')))
)
)
).parse(input)
}
```
#### Binary
```rust
use nom::{
IResult,
Parser,
branch::alt,
multi::{many0, many1},
combinator::recognize,
sequence::{preceded, terminated},
character::complete::{char, one_of},
bytes::complete::tag,
};
fn binary(input: &str) -> IResult<&str, &str> {
preceded(
alt((tag("0b"), tag("0B"))),
recognize(
many1(
terminated(one_of("01"), many0(char('_')))
)
)
).parse(input)
}
```
#### Decimal
```rust
use nom::{
IResult,
Parser,
multi::{many0, many1},
combinator::recognize,
sequence::terminated,
character::complete::{char, one_of},
};
fn decimal(input: &str) -> IResult<&str, &str> {
recognize(
many1(
terminated(one_of("0123456789"), many0(char('_')))
)
).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 nom::{
IResult,
Parser,
branch::alt,
multi::{many0, many1},
combinator::{opt, recognize},
sequence::{preceded, terminated},
character::complete::{char, one_of},
};
fn float(input: &str) -> IResult<&str, &str> {
alt((
// Case one: .42
recognize(
(
char('.'),
decimal,
opt((
one_of("eE"),
opt(one_of("+-")),
decimal
))
)
)
, // Case two: 42e42 and 42.42e42
recognize(
(
decimal,
opt(preceded(
char('.'),
decimal,
)),
one_of("eE"),
opt(one_of("+-")),
decimal
)
)
, // Case three: 42. and 42.42
recognize(
(
decimal,
char('.'),
opt(decimal)
)
)
)).parse(input)
}
fn decimal(input: &str) -> IResult<&str, &str> {
recognize(
many1(
terminated(one_of("0123456789"), many0(char('_')))
)
).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 nom::{
IResult, Parser, Finish, error::Error,
bytes::complete::{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, ").parse(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((_remaining, 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>());
}
```

195
vendor/nom/src/bits/complete.rs vendored Normal file
View File

@@ -0,0 +1,195 @@
//! Bit level parsers
//!
use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult};
use crate::lib::std::ops::{AddAssign, Div, Shl, Shr};
use crate::traits::{Input, ToUsize};
/// Generates a parser taking `count` bits
///
/// # Example
/// ```rust
/// # use nom::bits::complete::take;
/// # use nom::IResult;
/// # use nom::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(nom::Err::Error(Error{input: ([0b00010010].as_ref(), 0), code: ErrorKind::Eof })));
/// ```
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
I: Input<Item = u8>,
C: ToUsize,
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
{
let count = count.to_usize();
move |(input, bit_offset): (I, usize)| {
if count == 0 {
Ok(((input, bit_offset), 0u8.into()))
} else if input.input_len() * 8 < count + bit_offset {
Err(Err::Error(E::from_error_kind(
(input, bit_offset),
ErrorKind::Eof,
)))
} else {
let cnt = (count + bit_offset).div(8);
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) >> 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.take_from(cnt), end_offset), acc))
}
}
}
/// Generates a parser taking `count` bits and comparing them to `pattern`
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: Input<Item = u8> + 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)| {
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)))
}
})
}
}
/// Parses one specific bit as a bool.
///
/// # Example
/// ```rust
/// # use nom::bits::complete::bool;
/// # use nom::IResult;
/// # use nom::error::{Error, ErrorKind};
///
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
/// bool(input)
/// }
///
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
/// ```
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
where
I: Input<Item = u8>,
{
let (res, bit): (_, u32) = take(1usize)(input)?;
Ok((res, bit != 0))
}
#[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))
);
}
#[test]
fn test_bool_0() {
let input = [0b10000000].as_ref();
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
assert_eq!(result, Ok(((input, 1), true)));
}
#[test]
fn test_bool_eof() {
let input = [0b10000000].as_ref();
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
assert_eq!(
result,
Err(crate::Err::Error(crate::error::Error {
input: (input, 8),
code: ErrorKind::Eof
}))
);
}
}

174
vendor/nom/src/bits/mod.rs vendored Normal file
View File

@@ -0,0 +1,174 @@
//! Bit level parsers
//!
pub mod complete;
pub mod streaming;
use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult, Needed, Parser};
use crate::traits::ErrorConvert;
use crate::Input;
/// 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 nom::bits::{bits, streaming::take};
/// use nom::error::Error;
/// use nom::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: Input,
P: Parser<(I, usize), Output = O, Error = 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.take_from(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 nom::bits::{bits, bytes, streaming::take};
/// use nom::combinator::rest;
/// use nom::error::Error;
/// use nom::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: Input + Clone,
P: Parser<I, Output = O, Error = E1>,
{
move |(input, offset): (I, usize)| {
let inner = if offset % 8 != 0 {
input.take_from(1 + offset / 8)
} else {
input.take_from(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())),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::bits::streaming::take;
use crate::error::Error;
#[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 = &[0x12];
// Take bit slices with sizes [4, 8].
let result: IResult<&[u8], (u8, u8)> =
bits::<_, _, Error<(&[u8], 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());
}
}

170
vendor/nom/src/bits/streaming.rs vendored Normal file
View File

@@ -0,0 +1,170 @@
//! Bit level parsers
//!
use crate::error::{ErrorKind, ParseError};
use crate::internal::{Err, IResult, Needed};
use crate::lib::std::ops::{AddAssign, Div, Shl, Shr};
use crate::traits::{Input, ToUsize};
/// Generates a parser taking `count` bits
pub fn take<I, O, C, E: ParseError<(I, usize)>>(
count: C,
) -> impl Fn((I, usize)) -> IResult<(I, usize), O, E>
where
I: Input<Item = u8>,
C: ToUsize,
O: From<u8> + AddAssign + Shl<usize, Output = O> + Shr<usize, Output = O>,
{
let count = count.to_usize();
move |(input, bit_offset): (I, usize)| {
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)))
} 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) >> 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.take_from(cnt), end_offset), acc))
}
}
}
}
/// Generates a parser taking `count` bits and comparing them to `pattern`
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: Input<Item = u8> + 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)| {
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)))
}
})
}
}
/// Parses one specific bit as a bool.
///
/// # Example
/// ```rust
/// # use nom::bits::complete::bool;
/// # use nom::IResult;
/// # use nom::error::{Error, ErrorKind};
///
/// fn parse(input: (&[u8], usize)) -> IResult<(&[u8], usize), bool> {
/// bool(input)
/// }
///
/// assert_eq!(parse(([0b10000000].as_ref(), 0)), Ok((([0b10000000].as_ref(), 1), true)));
/// assert_eq!(parse(([0b10000000].as_ref(), 1)), Ok((([0b10000000].as_ref(), 2), false)));
/// ```
pub fn bool<I, E: ParseError<(I, usize)>>(input: (I, usize)) -> IResult<(I, usize), bool, E>
where
I: Input<Item = u8>,
{
let (res, bit): (_, u32) = take(1usize)(input)?;
Ok((res, bit != 0))
}
#[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
}))
);
}
#[test]
fn test_bool_0() {
let input = [0b10000000].as_ref();
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 0));
assert_eq!(result, Ok(((input, 1), true)));
}
#[test]
fn test_bool_eof() {
let input = [0b10000000].as_ref();
let result: crate::IResult<(&[u8], usize), bool> = bool((input, 8));
assert_eq!(result, Err(crate::Err::Incomplete(Needed::new(1))));
}
}

372
vendor/nom/src/branch/mod.rs vendored Normal file
View File

@@ -0,0 +1,372 @@
//! Choice combinators
#[cfg(test)]
mod tests;
use core::marker::PhantomData;
use crate::error::ErrorKind;
use crate::error::ParseError;
use crate::internal::{Err, Mode, Parser};
/// Tests a list of parsers one by one until one succeeds.
///
/// It takes as argument either a tuple or an array of parsers. If using a
/// tuple, there is a maximum of 21 parsers. If you need more, it is possible to
/// use an array.
///
/// ```rust
/// # use nom::error_position;
/// # use nom::{Err,error::ErrorKind, Needed, IResult, Parser};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::alt;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, &str> {
/// alt((alpha1, digit1)).parse(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<List>(l: List) -> Choice<List> {
Choice { parser: l }
}
/// 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 nom::{Err,error::{Error, ErrorKind}, Needed, IResult, Parser};
/// use nom::character::complete::{alpha1, digit1};
/// use nom::branch::permutation;
/// # fn main() {
/// fn parser(input: &str) -> IResult<&str, (&str, &str)> {
/// permutation((alpha1, digit1)).parse(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 nom::{Err, error::{Error, ErrorKind}, IResult, Parser};
/// use nom::branch::permutation;
/// use nom::character::complete::{anychar, char};
///
/// fn parser(input: &str) -> IResult<&str, (char, char)> {
/// permutation((anychar, char('a'))).parse(input)
/// }
///
/// // anychar parses 'b', then char('a') parses 'a'
/// assert_eq!(parser("ba"), Ok(("", ('b', 'a'))));
///
/// // anychar parses 'a', then char('a') fails on 'b',
/// // even though char('a') followed by anychar would succeed
/// assert_eq!(parser("ab"), Err(Err::Error(Error::new("b", ErrorKind::Char))));
/// ```
///
pub fn permutation<I: Clone, E: ParseError<I>, List>(list: List) -> Permutation<List, E> {
Permutation {
parser: list,
e: PhantomData,
}
}
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);
);
);
/// Wrapping structure for the [alt()] combinator implementation
pub struct Choice<T> {
parser: T,
}
macro_rules! alt_trait_impl(
($($id:ident)+) => (
impl<
Input: Clone, Output, Error: ParseError<Input>,
$($id: Parser<Input, Output = Output, Error = Error>),+
> Parser<Input> for Choice< ( $($id),+ )> {
type Output = Output;
type Error = Error;
#[inline(always)]
fn process<OM: crate::OutputMode>(
&mut self,
input: Input,
) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
match self.parser.0.process::<OM>(input.clone()) {
Ok(res) => Ok(res),
Err(Err::Failure(e))=> Err(Err::Failure(e)),
Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)),
Err(Err::Error(e)) => alt_trait_inner!(1, self, input, e, $($id)+),
}
}
}
);
);
macro_rules! alt_trait_inner(
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident $($id:ident)+) => (
match $self.parser.$it.process::<OM>($input.clone()) {
Ok(res) => Ok(res),
Err(Err::Failure(e))=>Err(Err::Failure(e)),
Err(Err::Incomplete(i))=> Err(Err::Incomplete(i)),
Err(Err::Error(e)) => {
succ!($it, alt_trait_inner!($self, $input, <OM::Error as crate::Mode>::combine($err, e, |e1, e2| e1.or(e2)), $($id)+))
}
}
);
($it:tt, $self:expr, $input:expr, $err:expr, $head:ident) => (
Err(Err::Error(<OM::Error as crate::Mode>::map($err, |err| 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 = Output, Error = Error>>
Parser<Input> for Choice<(A,)>
{
type Output = Output;
type Error = Error;
#[inline]
fn process<OM: crate::OutputMode>(
&mut self,
input: Input,
) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
self.parser.0.process::<OM>(input)
}
}
impl<
const N: usize,
Input: Clone,
Output,
Error: ParseError<Input>,
A: Parser<Input, Output = Output, Error = Error>,
> Parser<Input> for Choice<[A; N]>
{
type Output = Output;
type Error = Error;
#[inline]
fn process<OM: crate::OutputMode>(
&mut self,
input: Input,
) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
let mut error = None;
for branch in &mut self.parser {
match branch.process::<OM>(input.clone()) {
Err(Err::Error(e)) => match error {
None => error = Some(e),
Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))),
},
res => return res,
}
}
match error {
Some(e) => Err(Err::Error(OM::Error::map(e, |err| {
Error::append(input, ErrorKind::Alt, err)
}))),
None => Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::Alt)
}))),
}
}
}
impl<
Input: Clone,
Output,
Error: ParseError<Input>,
A: Parser<Input, Output = Output, Error = Error>,
> Parser<Input> for Choice<&mut [A]>
{
type Output = Output;
type Error = Error;
#[inline]
fn process<OM: crate::OutputMode>(
&mut self,
input: Input,
) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
let mut error = None;
for branch in self.parser.iter_mut() {
match branch.process::<OM>(input.clone()) {
Err(Err::Error(e)) => match error {
None => error = Some(e),
Some(err) => error = Some(OM::Error::combine(err, e, |e1, e2| e1.or(e2))),
},
res => return res,
}
}
match error {
Some(e) => Err(Err::Error(OM::Error::map(e, |err| {
Error::append(input, ErrorKind::Alt, err)
}))),
None => Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(input, ErrorKind::Alt)
}))),
}
}
}
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),+);
);
);
/// Wrapping structure for the [permutation] combinator implementation
pub struct Permutation<T, Error> {
parser: T,
e: PhantomData<Error>,
}
macro_rules! permutation_trait_impl(
($($name:ident $ty:ident $item:ident),+) => (
impl<
Input, Error, $($ty),+ , $($name),+
> Parser<Input> for Permutation< ( $($name),+ ), Error>
where
Input: Clone,
Error: ParseError<Input>,
$($name: Parser<Input, Output = $ty, Error = Error>),+
{
type Output = ( $($ty),+ );
type Error = Error;
#[inline(always)]
fn process<OM: crate::OutputMode>(
&mut self,
mut input: Input,
) -> crate::PResult<OM, Input, Self::Output, Self::Error> {
let mut res = OM::Output::bind(|| ($(Option::<$ty>::None),+));
$(let mut $item = false;)+
loop {
let mut err: Option<<OM::Error as Mode>::Output<Error>> = None;
permutation_trait_inner!(0, self, input, res, err, $($item)+);
// 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(OM::Error::map(err, |err| Error::append(input, ErrorKind::Permutation, err))));
}
return Ok((input,OM::Output::map(res, |res| {
// All parsers were applied
match res {
($(Some($item)),+) => ($($item),+),
_ => unreachable!(),
}
})))
}
}
}
);
);
macro_rules! permutation_trait_inner(
($it:tt, $self:expr, $input:ident, $res:expr, $err:expr, $head:ident $($item:ident)*) => (
if !$head {
match $self.parser.$it.process::<OM>($input.clone()) {
Ok((i, o)) => {
$input = i;
$res = OM::Output::combine($res, o, |mut res, o | {res.$it = Some(o);res });
$head = true;
continue;
}
Err(Err::Error(e)) => {
$err = Some(match $err {
None => e,
Some(err) => OM::Error::combine(err, e, |err, e| err.or(e))
});
}
Err(e) => return Err(e),
};
}
succ!($it, permutation_trait_inner!($self, $input, $res, $err, $($item)*));
);
($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
);

178
vendor/nom/src/branch/tests.rs vendored Normal file
View File

@@ -0,0 +1,178 @@
use crate::branch::{alt, permutation};
use crate::bytes::streaming::tag;
use crate::error::ErrorKind;
use crate::internal::{Err, IResult, Needed};
use crate::Parser;
#[cfg(feature = "alloc")]
use crate::{
error::ParseError,
lib::std::{
fmt::Debug,
string::{String, ToString},
},
};
#[cfg(feature = "alloc")]
#[derive(Debug, Clone, Eq, 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() {
use crate::Parser;
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)).parse(i)
}
fn alt2(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
alt((dont_work, work)).parse(i)
}
fn alt3(i: &[u8]) -> IResult<&[u8], &[u8], ErrorStr> {
alt((dont_work, dont_work, work2, dont_work)).parse(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"))).parse(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: &[u8]) -> IResult<&[u8], &[u8]> {
alt((tag("a"), tag("bc"), tag("def"))).parse(i)
}
let a = &b""[..];
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
let a = &b"b"[..];
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
let a = &b"bcd"[..];
assert_eq!(alt1(a), Ok((&b"d"[..], &b"bc"[..])));
let a = &b"cde"[..];
assert_eq!(alt1(a), Err(Err::Error(error_position!(a, ErrorKind::Tag))));
let a = &b"de"[..];
assert_eq!(alt1(a), Err(Err::Incomplete(Needed::new(1))));
let a = &b"defg"[..];
assert_eq!(alt1(a), Ok((&b"g"[..], &b"def"[..])));
}
#[test]
fn alt_array() {
fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> {
alt([tag("a"), tag("bc"), tag("def")]).parse(i)
}
let a = &b"a"[..];
assert_eq!(alt1(a), Ok((&b""[..], (&b"a"[..]))));
let bc = &b"bc"[..];
assert_eq!(alt1(bc), Ok((&b""[..], (&b"bc"[..]))));
let defg = &b"defg"[..];
assert_eq!(alt1(defg), Ok((&b"g"[..], (&b"def"[..]))));
}
#[test]
fn alt_dynamic_array() {
fn alt1(i: &[u8]) -> IResult<&[u8], &[u8]> {
alt(&mut [tag("a"), tag("bc"), tag("def")][..]).parse(i)
}
let a = &b"a"[..];
assert_eq!(alt1(a), Ok((&b""[..], (&b"a"[..]))));
let bc = &b"bc"[..];
assert_eq!(alt1(bc), Ok((&b""[..], (&b"bc"[..]))));
let defg = &b"defg"[..];
assert_eq!(alt1(defg), Ok((&b"g"[..], (&b"def"[..]))));
}
#[test]
fn permutation_test() {
#[allow(clippy::type_complexity)]
fn perm(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8], &[u8])> {
permutation((tag("abcd"), tag("efg"), tag("hi"))).parse(i)
}
let expected = (&b"abcd"[..], &b"efg"[..], &b"hi"[..]);
let a = &b"abcdefghijk"[..];
assert_eq!(perm(a), Ok((&b"jk"[..], expected)));
let b = &b"efgabcdhijk"[..];
assert_eq!(perm(b), Ok((&b"jk"[..], expected)));
let c = &b"hiefgabcdjk"[..];
assert_eq!(perm(c), Ok((&b"jk"[..], expected)));
let d = &b"efgxyzabcdefghi"[..];
assert_eq!(
perm(d),
Err(Err::Error(error_node_position!(
&b"efgxyzabcdefghi"[..],
ErrorKind::Permutation,
error_position!(&b"xyzabcdefghi"[..], ErrorKind::Tag)
)))
);
let e = &b"efgabc"[..];
assert_eq!(perm(e), Err(Err::Incomplete(Needed::new(1))));
}

566
vendor/nom/src/bytes/complete.rs vendored Normal file
View File

@@ -0,0 +1,566 @@
//! Parsers recognizing bytes streams, complete input version
use core::marker::PhantomData;
use crate::error::ParseError;
use crate::internal::{IResult, Parser};
use crate::traits::{Compare, FindSubstring, FindToken, ToUsize};
use crate::Complete;
use crate::Emit;
use crate::Input;
use crate::OutputM;
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
move |i: I| {
let mut parser = super::Tag {
tag: tag.clone(),
e: PhantomData,
};
parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn tag_no_case<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
move |i: I| {
let mut parser = super::TagNoCase {
tag: tag.clone(),
e: PhantomData,
};
parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn is_not<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
let mut parser = super::is_not(arr);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn is_a<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
let mut parser = super::is_a(arr);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::bytes::complete::take_while;
/// use nom::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""[..])));
/// ```
pub fn take_while<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::complete::take_while1;
/// use nom::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))));
/// ```
pub fn take_while1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while1(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::complete::take_while_m_n;
/// use nom::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))));
/// ```
pub fn take_while_m_n<F, I, Error: ParseError<I>>(
m: usize,
n: usize,
cond: F,
) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while_m_n(m, n, cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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(("", "")));
/// ```
#[allow(clippy::redundant_closure)]
pub fn take_till<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_till(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
#[allow(clippy::redundant_closure)]
pub fn take_till1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_till1(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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 nom::error::Error;
/// use nom::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())));
/// ```
pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
C: ToUsize,
{
let mut parser = super::take(count);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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")));
/// ```
pub fn take_until<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input + FindSubstring<T>,
T: Input + Clone,
{
let mut parser = super::take_until(tag);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn take_until1<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input + FindSubstring<T>,
T: Input + Clone,
{
let mut parser = super::take_until1(tag);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// # use nom::character::complete::digit1;
/// use nom::bytes::complete::escaped;
/// use nom::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"#)));
/// ```
///
pub fn escaped<'a, I, Error, F, G>(
normal: F,
control_char: char,
escapable: G,
) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Clone + crate::traits::Offset + Input + 'a,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
let mut parser = super::escaped(normal, control_char, escapable);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// # use std::str::from_utf8;
/// use nom::bytes::complete::{escaped_transform, tag};
/// use nom::character::complete::alpha1;
/// use nom::branch::alt;
/// use nom::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")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn escaped_transform<I, Error, F, G, O1, O2, ExtendItem, Output>(
normal: F,
control_char: char,
transform: G,
) -> impl FnMut(I) -> IResult<I, Output, Error>
where
I: Clone + crate::traits::Offset + Input,
I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Output = O1, Error = Error>,
G: Parser<I, Output = O2, Error = Error>,
Error: ParseError<I>,
{
let mut parser = super::escaped_transform(normal, control_char, transform);
move |i: I| parser.process::<OutputM<Emit, Emit, Complete>>(i)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorKind;
use crate::AsChar;
use crate::Err;
#[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(input: &str) -> IResult<&str, &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('"'),
)
.parse(input)
}
#[test]
fn escaped_hang_1118() {
assert_eq!(unquote(r#""""#), Ok(("", "")));
}
// issue #1630 take_while_m_n is invalid for multi-byte UTF-8 characters
#[test]
fn complete_take_while_m_n_multibyte() {
use crate::error::Error;
fn multi_byte_chars(s: &str, m: usize, n: usize) -> IResult<&str, &str> {
take_while_m_n(m, n, |c: char| c.len() > 1)(s)
}
assert_eq!(multi_byte_chars("€ latin", 0, 64), Ok((" latin", "")));
assert_eq!(multi_byte_chars("𝄠 latin", 0, 1), Ok((" latin", "𝄠")));
assert_eq!(multi_byte_chars("باب latin", 0, 64), Ok((" latin", "باب")));
assert_eq!(
multi_byte_chars("💣💢ᾠ latin", 3, 3),
Ok((" latin", "💣💢ᾠ"))
);
assert_eq!(multi_byte_chars("latin", 0, 64), Ok(("latin", "")));
assert_eq!(multi_byte_chars("باب", 1, 3), Ok(("", "باب")));
assert_eq!(multi_byte_chars("باب", 1, 2), Ok(("ب", "با")));
assert_eq!(
multi_byte_chars("latin", 1, 64),
Err(Err::Error(Error::new("latin", ErrorKind::TakeWhileMN)))
);
}
}

1044
vendor/nom/src/bytes/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff

499
vendor/nom/src/bytes/streaming.rs vendored Normal file
View File

@@ -0,0 +1,499 @@
//! Parsers recognizing bytes streams, streaming version
use core::marker::PhantomData;
use crate::error::ParseError;
use crate::internal::{IResult, Parser};
use crate::traits::{Compare, FindSubstring, FindToken, ToUsize};
use crate::Emit;
use crate::Input;
use crate::OutputM;
use crate::Streaming;
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn tag<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
move |i: I| {
let mut parser = super::Tag {
tag: tag.clone(),
e: PhantomData,
};
parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn tag_no_case<T, I, Error: ParseError<I>>(tag: T) -> impl Fn(I) -> IResult<I, I, Error>
where
I: Input + Compare<T>,
T: Input + Clone,
{
move |i: I| {
let mut parser = super::TagNoCase {
tag: tag.clone(),
e: PhantomData,
};
parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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))));
/// ```
pub fn is_not<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
let mut parser = super::is_not(arr);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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))));
/// ```
pub fn is_a<T, I, Error: ParseError<I>>(arr: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
T: FindToken<<I as Input>::Item>,
{
let mut parser = super::is_a(arr);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::bytes::streaming::take_while;
/// use nom::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))));
/// ```
pub fn take_while<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::streaming::take_while1;
/// use nom::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))));
/// ```
pub fn take_while1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while1(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::bytes::streaming::take_while_m_n;
/// use nom::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))));
/// ```
pub fn take_while_m_n<F, I, Error: ParseError<I>>(
m: usize,
n: usize,
cond: F,
) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_while_m_n(m, n, cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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))));
/// ```
#[allow(clippy::redundant_closure)]
pub fn take_till<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_till(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
#[allow(clippy::redundant_closure)]
pub fn take_till1<F, I, Error: ParseError<I>>(cond: F) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
F: Fn(<I as Input>::Item) -> bool,
{
let mut parser = super::take_till1(cond);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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)));
/// ```
pub fn take<C, I, Error: ParseError<I>>(count: C) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input,
C: ToUsize,
{
let mut parser = super::take(count);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// use nom::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")));
/// ```
pub fn take_until<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
let mut parser = super::take_until(tag);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::{Error, ErrorKind}, Needed, IResult};
/// use nom::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))));
/// ```
pub fn take_until1<T, I, Error: ParseError<I>>(tag: T) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input + FindSubstring<T>,
T: Clone,
{
let mut parser = super::take_until1(tag);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// # use nom::character::complete::digit1;
/// use nom::bytes::streaming::escaped;
/// use nom::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")));
/// ```
///
pub fn escaped<I, Error, F, G>(
normal: F,
control_char: char,
escapable: G,
) -> impl FnMut(I) -> IResult<I, I, Error>
where
I: Input + Clone + crate::traits::Offset,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Error = Error>,
G: Parser<I, Error = Error>,
Error: ParseError<I>,
{
let mut parser = super::escaped(normal, control_char, escapable);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}
/// 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 nom::{Err, error::ErrorKind, Needed, IResult};
/// # use std::str::from_utf8;
/// use nom::bytes::streaming::{escaped_transform, tag};
/// use nom::character::streaming::alpha1;
/// use nom::branch::alt;
/// use nom::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")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn escaped_transform<I, Error, F, G, O1, O2, ExtendItem, Output>(
normal: F,
control_char: char,
transform: G,
) -> impl FnMut(I) -> IResult<I, Output, Error>
where
I: Clone + crate::traits::Offset + Input,
I: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
O1: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
O2: crate::traits::ExtendInto<Item = ExtendItem, Extender = Output>,
<I as Input>::Item: crate::traits::AsChar,
F: Parser<I, Output = O1, Error = Error>,
G: Parser<I, Output = O2, Error = Error>,
Error: ParseError<I>,
{
let mut parser = super::escaped_transform(normal, control_char, transform);
move |i: I| parser.process::<OutputM<Emit, Emit, Streaming>>(i)
}

646
vendor/nom/src/bytes/tests.rs vendored Normal file
View File

@@ -0,0 +1,646 @@
use crate::character::streaming::{
alpha1 as alpha, alphanumeric1 as alphanumeric, bin_digit1 as bin_digit, 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::internal::{Err, IResult, Needed};
use crate::AsChar;
use crate::Parser;
#[cfg(feature = "alloc")]
use crate::{
branch::alt,
bytes::complete::{escaped, escaped_transform, tag},
combinator::{map, value},
lib::std::string::String,
lib::std::vec::Vec,
};
#[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))));
}
#[cfg(feature = "alloc")]
#[allow(unused_variables)]
#[test]
fn escaping() {
use crate::character::streaming::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::streaming::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() {
use crate::Parser;
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,
)
.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> {
map(
escaped_transform(
alpha,
'&',
alt((
value("è".as_bytes(), tag("egrave;")),
value("à".as_bytes(), tag("agrave;")),
)),
),
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 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"))));
}
#[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("-->"))).parse(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).parse(i)
}
let ra = ya(&b"abc;"[..]);
assert_eq!(ra, Ok((semicolon, &b"abc"[..])));
fn yd(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(digit).parse(i)
}
let rd = yd(&b"123;"[..]);
assert_eq!(rd, Ok((semicolon, &b"123"[..])));
fn yhd(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(hex_digit).parse(i)
}
let rhd = yhd(&b"123abcDEF;"[..]);
assert_eq!(rhd, Ok((semicolon, &b"123abcDEF"[..])));
fn yod(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(oct_digit).parse(i)
}
let rod = yod(&b"1234567;"[..]);
assert_eq!(rod, Ok((semicolon, &b"1234567"[..])));
fn ybd(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(bin_digit).parse(i)
}
let rbd = ybd(&b"101010;"[..]);
assert_eq!(rbd, Ok((semicolon, &b"101010"[..])));
fn yan(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(alphanumeric).parse(i)
}
let ran = yan(&b"123abc;"[..]);
assert_eq!(ran, Ok((semicolon, &b"123abc"[..])));
fn ys(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(space).parse(i)
}
let rs = ys(&b" \t;"[..]);
assert_eq!(rs, Ok((semicolon, &b" \t"[..])));
fn yms(i: &[u8]) -> IResult<&[u8], &[u8]> {
recognize(multispace).parse(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"[..], &b"abc"[..])));
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).parse(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::{bytes::streaming::tag, multi::length_data, number::streaming::le_u8};
fn x(i: &[u8]) -> IResult<&[u8], &[u8]> {
length_data(le_u8).parse(i)
}
assert_eq!(x(b"\x02..>>"), Ok((&b">>"[..], &b".."[..])));
assert_eq!(x(b"\x02.."), Ok((&[][..], &b".."[..])));
assert_eq!(x(b"\x02."), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(x(b"\x02"), Err(Err::Incomplete(Needed::new(2))));
fn y(i: &[u8]) -> IResult<&[u8], &[u8]> {
let (i, _) = tag("magic")(i)?;
length_data(le_u8).parse(i)
}
assert_eq!(y(b"magic\x02..>>"), Ok((&b">>"[..], &b".."[..])));
assert_eq!(y(b"magic\x02.."), Ok((&[][..], &b".."[..])));
assert_eq!(y(b"magic\x02."), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(y(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"[..])));
}

1303
vendor/nom/src/character/complete.rs vendored Normal file

File diff suppressed because it is too large Load Diff

402
vendor/nom/src/character/mod.rs vendored Normal file
View File

@@ -0,0 +1,402 @@
//! Character specific parsers and combinators
//!
//! Functions recognizing specific characters
use core::marker::PhantomData;
use crate::error::ErrorKind;
use crate::FindToken;
use crate::IsStreaming;
use crate::Mode;
use crate::{error::ParseError, AsChar, Err, IResult, Input, Needed, Parser};
#[cfg(test)]
mod tests;
pub mod complete;
pub mod streaming;
#[inline]
#[doc(hidden)]
#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alpha`")]
pub fn is_alphabetic(chr: u8) -> bool {
matches!(chr, 0x41..=0x5A | 0x61..=0x7A)
}
#[inline]
#[doc(hidden)]
#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_dec_digit`")]
pub fn is_digit(chr: u8) -> bool {
matches!(chr, 0x30..=0x39)
}
#[inline]
#[doc(hidden)]
#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_hex_digit`")]
pub fn is_hex_digit(chr: u8) -> bool {
matches!(chr, 0x30..=0x39 | 0x41..=0x46 | 0x61..=0x66)
}
#[inline]
#[doc(hidden)]
#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_oct_digit`")]
pub fn is_oct_digit(chr: u8) -> bool {
matches!(chr, 0x30..=0x37)
}
/// Tests if byte is ASCII binary digit: 0-1
///
/// # Example
///
/// ```
/// # use nom::character::is_bin_digit;
/// assert_eq!(is_bin_digit(b'a'), false);
/// assert_eq!(is_bin_digit(b'2'), false);
/// assert_eq!(is_bin_digit(b'0'), true);
/// assert_eq!(is_bin_digit(b'1'), true);
/// ```
#[inline]
pub fn is_bin_digit(chr: u8) -> bool {
matches!(chr, 0x30..=0x31)
}
#[inline]
#[doc(hidden)]
#[deprecated(since = "8.0.0", note = "Replaced with `AsChar::is_alphanum`")]
pub fn is_alphanumeric(chr: u8) -> bool {
AsChar::is_alphanum(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'
}
/// Recognizes one character.
///
/// # Example
///
/// ```
/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult};
/// # use nom::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))));
/// ```
pub fn char<I, Error: ParseError<I>>(c: char) -> impl Parser<I, Output = char, Error = Error>
where
I: Input,
<I as Input>::Item: AsChar,
{
Char { c, e: PhantomData }
}
/// Parser implementation for [char()]
pub struct Char<E> {
c: char,
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>> Parser<I> for Char<Error>
where
I: Input,
<I as Input>::Item: AsChar,
{
type Output = char;
type Error = Error;
#[inline(always)]
fn process<OM: crate::OutputMode>(
&mut self,
i: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match (i).iter_elements().next().map(|t| {
let b = t.as_char() == self.c;
(&self.c, b)
}) {
None => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::new(self.c.len() - i.input_len())))
} else {
Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c))))
}
}
Some((_, false)) => Err(Err::Error(OM::Error::bind(|| Error::from_char(i, self.c)))),
Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
}
}
}
/// Recognizes one character and checks that it satisfies a predicate
///
/// # Example
///
/// ```
/// # use nom::{Err, error::{ErrorKind, Error}, Needed, IResult};
/// # use nom::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))));
/// ```
pub fn satisfy<F, I, Error: ParseError<I>>(
predicate: F,
) -> impl Parser<I, Output = char, Error = Error>
where
I: Input,
<I as Input>::Item: AsChar,
F: Fn(char) -> bool,
{
Satisfy {
predicate,
make_error: |i: I| Error::from_error_kind(i, ErrorKind::Satisfy),
}
}
/// Parser implementation for [satisfy]
pub struct Satisfy<F, MakeError> {
predicate: F,
make_error: MakeError,
}
impl<I, Error: ParseError<I>, F, MakeError> Parser<I> for Satisfy<F, MakeError>
where
I: Input,
<I as Input>::Item: AsChar,
F: Fn(char) -> bool,
MakeError: Fn(I) -> Error,
{
type Output = char;
type Error = Error;
#[inline(always)]
fn process<OM: crate::OutputMode>(
&mut self,
i: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match (i).iter_elements().next().map(|t| {
let c = t.as_char();
let b = (self.predicate)(c);
(c, b)
}) {
None => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::Unknown))
} else {
Err(Err::Error(OM::Error::bind(|| (self.make_error)(i))))
}
}
Some((_, false)) => Err(Err::Error(OM::Error::bind(|| (self.make_error)(i)))),
Some((c, true)) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
}
}
}
/// Recognizes one of the provided characters.
///
/// # Example
///
/// ```
/// # use nom::{Err, error::ErrorKind};
/// # use nom::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))));
/// ```
pub fn one_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error>
where
I: Input,
<I as Input>::Item: AsChar,
T: FindToken<char>,
{
Satisfy {
predicate: move |c: char| list.find_token(c),
make_error: move |i| Error::from_error_kind(i, ErrorKind::OneOf),
}
}
//. Recognizes a character that is not in the provided characters.
///
/// # Example
///
/// ```
/// # use nom::{Err, error::ErrorKind, Needed};
/// # use nom::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::Unknown)));
/// ```
pub fn none_of<I, T, Error: ParseError<I>>(list: T) -> impl Parser<I, Output = char, Error = Error>
where
I: Input,
<I as Input>::Item: AsChar,
T: FindToken<char>,
{
Satisfy {
predicate: move |c: char| !list.find_token(c),
make_error: move |i| Error::from_error_kind(i, ErrorKind::NoneOf),
}
}
// Matches one byte as a character. Note that the input type will
/// accept a `str`, but not a `&[u8]`, unlike many other nom parsers.
///
/// # Example
///
/// ```
/// # use nom::{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))));
/// ```
pub fn anychar<T, E: ParseError<T>>(input: T) -> IResult<T, char, E>
where
T: Input,
<T as Input>::Item: AsChar,
{
let mut it = input.iter_elements();
match it.next() {
None => Err(Err::Error(E::from_error_kind(input, ErrorKind::Eof))),
Some(c) => Ok((input.take_from(c.len()), c.as_char())),
}
}
/// Parser implementation for char
pub struct AnyChar<E> {
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>> Parser<I> for AnyChar<Error>
where
I: Input,
<I as Input>::Item: AsChar,
{
type Output = char;
type Error = Error;
fn process<OM: crate::OutputMode>(
&mut self,
i: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
match (i).iter_elements().next() {
None => {
if OM::Incomplete::is_streaming() {
Err(Err::Incomplete(Needed::new(1)))
} else {
Err(Err::Error(OM::Error::bind(|| {
Error::from_error_kind(i, ErrorKind::Eof)
})))
}
}
Some(c) => Ok((i.take_from(c.len()), OM::Output::bind(|| c.as_char()))),
}
}
}
/// Recognizes one or more ASCII numerical characters: 0-9
///
/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data,
/// or if no terminating token is found (a non digit character).
/// # Example
///
/// ```
/// # use nom::{Err, error::ErrorKind, IResult, Needed};
/// # use nom::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))));
/// ```
pub fn digit1<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E>
where
T: Input,
<T as Input>::Item: AsChar,
{
Digit1 { e: PhantomData }
}
/// Parser implementation for [digit1]
pub struct Digit1<E> {
e: PhantomData<E>,
}
impl<I: Input, E: ParseError<I>> Parser<I> for Digit1<E>
where
<I as Input>::Item: AsChar,
{
type Output = I;
type Error = E;
#[inline]
fn process<OM: crate::OutputMode>(
&mut self,
input: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
input.split_at_position_mode1::<OM, _, _>(|item| !item.is_dec_digit(), ErrorKind::Digit)
}
}
/// Recognizes zero or more spaces, tabs, carriage returns and line feeds.
///
/// *Streaming version*: Will return `Err(nom::Err::Incomplete(_))` if there's not enough input data,
/// or if no terminating token is found (a non space character).
/// # Example
///
/// ```
/// # use nom::{Err, error::ErrorKind, IResult, Needed};
/// # use nom::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))));
/// ```
pub fn multispace0<T, E: ParseError<T>>() -> impl Parser<T, Output = T, Error = E>
where
T: Input,
<T as Input>::Item: AsChar,
{
MultiSpace0 { e: PhantomData }
/*input.split_at_position(|item| {
let c = item.as_char();
!(c == ' ' || c == '\t' || c == '\r' || c == '\n')
})*/
}
/// Parser implementation for [multispace0()]
pub struct MultiSpace0<E> {
e: PhantomData<E>,
}
impl<I, Error: ParseError<I>> Parser<I> for MultiSpace0<Error>
where
I: Input,
<I as Input>::Item: AsChar,
{
type Output = I;
type Error = Error;
fn process<OM: crate::OutputMode>(
&mut self,
i: I,
) -> crate::PResult<OM, I, Self::Output, Self::Error> {
i.split_at_position_mode::<OM, _, _>(|item| {
let c = item.as_char();
!(c == ' ' || c == '\t' || c == '\r' || c == '\n')
})
}
}

1256
vendor/nom/src/character/streaming.rs vendored Normal file

File diff suppressed because it is too large Load Diff

62
vendor/nom/src/character/tests.rs vendored Normal file
View File

@@ -0,0 +1,62 @@
use super::streaming::*;
use crate::error::ErrorKind;
use crate::internal::{Err, IResult};
#[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')));
}

1044
vendor/nom/src/combinator/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff

284
vendor/nom/src/combinator/tests.rs vendored Normal file
View File

@@ -0,0 +1,284 @@
use super::*;
use crate::bytes::complete::take;
use crate::bytes::streaming::tag;
use crate::error::ErrorKind;
use crate::error::ParseError;
use crate::internal::{Err, IResult, Needed};
#[cfg(feature = "alloc")]
use crate::lib::std::boxed::Box;
use crate::number::complete::u8;
macro_rules! assert_parse(
($left: expr, $right: expr) => {
let res: $crate::IResult<_, _, (_, ErrorKind)> = $left;
assert_eq!(res, $right);
};
);
/*#[test]
fn t1() {
let v1:Vec<u8> = vec![1,2,3];
let v2:Vec<u8> = vec![4,5,6];
let d = Ok((&v1[..], &v2[..]));
let res = d.flat_map(print);
assert_eq!(res, Ok((&v2[..], ())));
}*/
#[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 end_of_input() {
let not_over = &b"Hello, world!"[..];
let is_over = &b""[..];
named!(eof_test, eof!());
let res_not_over = eof_test(not_over);
assert_eq!(res_not_over, Err(Err::Error(error_position!(not_over, ErrorKind::Eof))));
let res_over = eof_test(is_over);
assert_eq!(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::streaming::alphanumeric1(input)
}
#[test]
fn test_flat_map() {
let input: &[u8] = &[3, 100, 101, 102, 103, 104][..];
assert_parse!(
flat_map(u8, take).parse(input),
Ok((&[103, 104][..], &[100, 101, 102][..]))
);
}
#[test]
fn test_map_opt() {
let input: &[u8] = &[50][..];
assert_parse!(
map_opt(u8, |u| if u < 20 { Some(u) } else { None }).parse(input),
Err(Err::Error((&[50][..], ErrorKind::MapOpt)))
);
assert_parse!(
map_opt(u8, |u| if u > 20 { Some(u) } else { None }).parse(input),
Ok((&[][..], 50))
);
}
#[test]
fn test_map_parser() {
let input: &[u8] = &[100, 101, 102, 103, 104][..];
assert_parse!(
map_parser(take(4usize), 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)).parse(input),
Err(Err::Error((&[102][..], ErrorKind::Eof)))
);
assert_parse!(
all_consuming(take(3usize)).parse(input),
Ok((&[][..], &[100, 101, 102][..]))
);
}
#[test]
#[allow(unused)]
fn test_verify_ref() {
use crate::bytes::complete::take;
let mut parser1 = verify(take(3u8), |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> {
verify(crate::number::streaming::be_u32, |val: &u32| *val < 3).parse(i)
}
}
#[test]
#[cfg(feature = "alloc")]
fn test_verify_alloc() {
use crate::bytes::complete::take;
let mut parser1 = verify(map(take(3u8), |s: &[u8]| s.to_vec()), |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]
#[cfg(feature = "std")]
fn test_into() {
use crate::bytes::complete::take;
use crate::{
error::{Error, ParseError},
Err,
};
let mut parser = into(take::<_, _, Error<_>>(3u8));
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: &[u8]) -> IResult<&[u8], Option<&[u8]>> {
opt(tag("abcd")).parse(i)
}
let a = &b"abcdef"[..];
let b = &b"bcdefg"[..];
let c = &b"ab"[..];
assert_eq!(opt_abcd(a), Ok((&b"ef"[..], Some(&b"abcd"[..]))));
assert_eq!(opt_abcd(b), Ok((&b"bcdefg"[..], None)));
assert_eq!(opt_abcd(c), Err(Err::Incomplete(Needed::new(2))));
}
#[test]
fn peek_test() {
fn peek_tag(i: &[u8]) -> IResult<&[u8], &[u8]> {
peek(tag("abcd")).parse(i)
}
assert_eq!(peek_tag(&b"abcdef"[..]), Ok((&b"abcdef"[..], &b"abcd"[..])));
assert_eq!(peek_tag(&b"ab"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(
peek_tag(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn not_test() {
fn not_aaa(i: &[u8]) -> IResult<&[u8], ()> {
not(tag("aaa")).parse(i)
}
assert_eq!(
not_aaa(&b"aaa"[..]),
Err(Err::Error(error_position!(&b"aaa"[..], ErrorKind::Not)))
);
assert_eq!(not_aaa(&b"aa"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(not_aaa(&b"abcd"[..]), Ok((&b"abcd"[..], ())));
}
#[test]
fn verify_test() {
use crate::bytes::streaming::take;
fn test(i: &[u8]) -> IResult<&[u8], &[u8]> {
verify(take(5u8), |slice: &[u8]| slice[0] == b'a').parse(i)
}
assert_eq!(test(&b"bcd"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(
test(&b"bcdefg"[..]),
Err(Err::Error(error_position!(
&b"bcdefg"[..],
ErrorKind::Verify
)))
);
assert_eq!(test(&b"abcdefg"[..]), Ok((&b"fg"[..], &b"abcde"[..])));
}
#[test]
fn fail_test() {
let a = "string";
let b = "another string";
assert_eq!(
fail::<_, &str, _>().parse(a),
Err(Err::Error((a, ErrorKind::Fail)))
);
assert_eq!(
fail::<_, &str, _>().parse(b),
Err(Err::Error((b, ErrorKind::Fail)))
);
}

802
vendor/nom/src/error.rs vendored Normal file
View File

@@ -0,0 +1,802 @@
//! Error management
//!
//! Parsers are generic over their error type, requiring that it implements
//! the `error::ParseError<Input>` trait.
use crate::internal::{Err, Mode, OutputMode, PResult, Parser};
use crate::lib::std::fmt;
#[cfg(feature = "alloc")]
use crate::alloc::borrow::ToOwned;
#[cfg(feature = "std")]
use crate::internal::IResult;
/// This trait must be implemented by the error type of a nom parser.
///
/// There are already implementations of it for `(Input, ErrorKind)`
/// and `Error<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
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>: 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: &'static str, 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's location and code
#[derive(Clone, Debug, Eq, 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> ContextError<I> 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 = "alloc")]
impl<I: ToOwned + ?Sized> Error<&I> {
/// Converts `Error<&I>` into `Error<I::Owned>` by cloning.
pub fn cloned(self) -> Error<I::Owned> {
Error {
input: self.input.to_owned(),
code: self.code,
}
}
}
#[cfg(feature = "alloc")]
impl<I: ToOwned + ?Sized> Error<&mut I> {
/// Converts `Error<&mut I>` into `Error<I::Owned>` by cloning.
pub fn cloned(self) -> Error<I::Owned> {
Error {
input: self.input.to_owned(),
code: self.code,
}
}
}
impl<I: Copy> Error<&I> {
/// Converts `Error<&I>` into `Error<I>` by copying.
pub fn copied(self) -> Error<I> {
Error {
input: *self.input,
code: self.code,
}
}
}
impl<I: Copy> Error<&mut I> {
/// Converts `Error<&mut I>` into `Error<I>` by copying.
pub fn copied(self) -> Error<I> {
Error {
input: *self.input,
code: self.code,
}
}
}
#[cfg(feature = "std")]
impl<I: fmt::Debug + fmt::Display> std::error::Error for Error<I> {}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
impl From<Error<&[u8]>> for Error<crate::lib::std::vec::Vec<u8>> {
fn from(value: Error<&[u8]>) -> Self {
Error {
input: value.input.to_owned(),
code: value.code,
}
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
impl From<Error<&str>> for Error<crate::lib::std::string::String> {
fn from(value: Error<&str>) -> Self {
Error {
input: value.input.to_owned(),
code: value.code,
}
}
}
// 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> ContextError<I> 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> ContextError<I> 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]
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
pub fn append_error<I, E: ParseError<I>>(input: I, kind: ErrorKind, other: E) -> E {
E::append(input, kind, other)
}
/// 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
pub fn context<F>(context: &'static str, parser: F) -> Context<F> {
Context { context, parser }
}
/// Parser implementation for [context]
pub struct Context<F> {
context: &'static str,
parser: F,
}
impl<I, F> Parser<I> for Context<F>
where
I: Clone,
F: Parser<I>,
<F as Parser<I>>::Error: ContextError<I>,
{
type Output = <F as Parser<I>>::Output;
type Error = <F as Parser<I>>::Error;
fn process<OM: OutputMode>(&mut self, input: I) -> PResult<OM, I, Self::Output, Self::Error> {
match self.parser.process::<OM>(input.clone()) {
Err(Err::Error(e)) => Err(Err::Error(OM::Error::map(e, |e| {
<F as Parser<I>>::Error::add_context(input, self.context, e)
}))),
Err(Err::Failure(e)) => Err(Err::Failure(<F as Parser<I>>::Error::add_context(
input,
self.context,
e,
))),
x => x,
}
}
}
/// 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,
BinDigit,
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,
Many,
Fold,
Precedence,
}
#[rustfmt::skip]
#[allow(deprecated)]
/// Converts an ErrorKind to a number
pub fn error_to_u32(e: &ErrorKind) -> u32 {
match *e {
ErrorKind::Tag => 1,
ErrorKind::MapRes => 2,
ErrorKind::MapOpt => 3,
ErrorKind::Alt => 4,
ErrorKind::IsNot => 5,
ErrorKind::IsA => 6,
ErrorKind::SeparatedList => 7,
ErrorKind::SeparatedNonEmptyList => 8,
ErrorKind::Many1 => 9,
ErrorKind::Count => 10,
ErrorKind::TakeUntil => 12,
ErrorKind::LengthValue => 15,
ErrorKind::TagClosure => 16,
ErrorKind::Alpha => 17,
ErrorKind::Digit => 18,
ErrorKind::AlphaNumeric => 19,
ErrorKind::Space => 20,
ErrorKind::MultiSpace => 21,
ErrorKind::LengthValueFn => 22,
ErrorKind::Eof => 23,
ErrorKind::Switch => 27,
ErrorKind::TagBits => 28,
ErrorKind::OneOf => 29,
ErrorKind::NoneOf => 30,
ErrorKind::Char => 40,
ErrorKind::CrLf => 41,
ErrorKind::RegexpMatch => 42,
ErrorKind::RegexpMatches => 43,
ErrorKind::RegexpFind => 44,
ErrorKind::RegexpCapture => 45,
ErrorKind::RegexpCaptures => 46,
ErrorKind::TakeWhile1 => 47,
ErrorKind::Complete => 48,
ErrorKind::Fix => 49,
ErrorKind::Escaped => 50,
ErrorKind::EscapedTransform => 51,
ErrorKind::NonEmpty => 56,
ErrorKind::ManyMN => 57,
ErrorKind::HexDigit => 59,
ErrorKind::OctDigit => 61,
ErrorKind::Many0 => 62,
ErrorKind::Not => 63,
ErrorKind::Permutation => 64,
ErrorKind::ManyTill => 65,
ErrorKind::Verify => 66,
ErrorKind::TakeTill1 => 67,
ErrorKind::TakeWhileMN => 69,
ErrorKind::TooLarge => 70,
ErrorKind::Many0Count => 71,
ErrorKind::Many1Count => 72,
ErrorKind::Float => 73,
ErrorKind::Satisfy => 74,
ErrorKind::Fail => 75,
ErrorKind::Many => 76,
ErrorKind::Fold => 77,
ErrorKind::BinDigit => 78,
ErrorKind::Precedence => 79,
}
}
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::BinDigit => "Binary 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",
ErrorKind::Many => "Many",
ErrorKind::Fold => "Fold",
ErrorKind::Precedence => "Precedence",
}
}
}
/// Creates a parse error from a `nom::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::make_error($input, $code)
});
);
/// Creates a parse error from a `nom::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::append_error($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
///
/// ```rust
/// use nom::{IResult, error::dbg_dmp, bytes::complete::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);
/// ```
#[cfg(feature = "std")]
#[cfg_attr(feature = "docsrs", doc(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::HexDisplay;
move |i: &'a [u8]| match f(i) {
Err(e) => {
println!("{}: Error({:?}) at:\n{}", context, e, i.to_hex(8));
Err(e)
}
a => a,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn context_test() {
use crate::{character::char, combinator::cut, internal::Needed};
#[derive(Debug, PartialEq)]
struct Error<I> {
input: I,
ctx: Option<&'static str>,
}
impl<I> ParseError<I> for Error<I> {
fn from_error_kind(input: I, _kind: ErrorKind) -> Self {
Self { input, ctx: None }
}
fn append(input: I, _kind: ErrorKind, other: Self) -> Self {
Self {
input,
ctx: other.ctx,
}
}
}
impl<I> ContextError<I> for Error<I> {
fn add_context(input: I, ctx: &'static str, _other: Self) -> Self {
Self {
input,
ctx: Some(ctx),
}
}
}
assert_eq!(
context("ctx", char::<_, Error<_>>('a')).parse("abcd"),
Ok(("bcd", 'a'))
);
assert_eq!(
context("ctx", char::<_, Error<_>>('a')).parse(""),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
context("ctx", char::<_, Error<_>>('a')).parse_complete(""),
Err(Err::Error(Error {
input: "",
ctx: Some("ctx")
}))
);
assert_eq!(
context("ctx", cut(char::<_, Error<_>>('a'))).parse("bcd"),
Err(Err::Failure(Error {
input: "bcd",
ctx: Some("ctx")
}))
);
}
#[cfg(feature = "alloc")]
#[test]
fn clone_error() {
use crate::lib::std::string::String;
let err = Error {
code: ErrorKind::Eof,
input: "test",
};
let _err: Error<String> = err.cloned();
}
#[test]
fn copy_error() {
let err = Error {
code: ErrorKind::Eof,
input: &0_u8,
};
let _err: Error<u8> = err.copied();
}
}
/*
#[cfg(feature = "alloc")]
use lib::std::{vec::Vec, collections::HashMap};
#[cfg(feature = "std")]
use lib::std::hash::Hash;
#[cfg(feature = "std")]
pub fn add_error_pattern<'a, I: Clone + Hash + Eq, O, E: Clone + Hash + Eq>(
h: &mut HashMap<VerboseError<I>, &'a str>,
e: VerboseError<I>,
message: &'a str,
) -> bool {
h.insert(e, message);
true
}
pub fn slice_to_offsets(input: &[u8], s: &[u8]) -> (usize, usize) {
let start = input.as_ptr();
let off1 = s.as_ptr() as usize - start as usize;
let off2 = off1 + s.len();
(off1, off2)
}
#[cfg(feature = "std")]
pub fn prepare_errors<O, E: Clone>(input: &[u8], e: VerboseError<&[u8]>) -> Option<Vec<(ErrorKind, usize, usize)>> {
let mut v: Vec<(ErrorKind, usize, usize)> = Vec::new();
for (p, kind) in e.errors.drain(..) {
let (o1, o2) = slice_to_offsets(input, p);
v.push((kind, o1, o2));
}
v.reverse();
Some(v)
}
#[cfg(feature = "std")]
pub fn print_error<O, E: Clone>(input: &[u8], res: VerboseError<&[u8]>) {
if let Some(v) = prepare_errors(input, res) {
let colors = generate_colors(&v);
println!("parser codes: {}", print_codes(&colors, &HashMap::new()));
println!("{}", print_offsets(input, 0, &v));
} else {
println!("not an error");
}
}
#[cfg(feature = "std")]
pub fn generate_colors<E>(v: &[(ErrorKind, usize, usize)]) -> HashMap<u32, u8> {
let mut h: HashMap<u32, u8> = HashMap::new();
let mut color = 0;
for &(ref c, _, _) in v.iter() {
h.insert(error_to_u32(c), color + 31);
color = color + 1 % 7;
}
h
}
pub fn code_from_offset(v: &[(ErrorKind, usize, usize)], offset: usize) -> Option<u32> {
let mut acc: Option<(u32, usize, usize)> = None;
for &(ref ek, s, e) in v.iter() {
let c = error_to_u32(ek);
if s <= offset && offset <= e {
if let Some((_, start, end)) = acc {
if start <= s && e <= end {
acc = Some((c, s, e));
}
} else {
acc = Some((c, s, e));
}
}
}
if let Some((code, _, _)) = acc {
return Some(code);
} else {
return None;
}
}
#[cfg(feature = "alloc")]
pub fn reset_color(v: &mut Vec<u8>) {
v.push(0x1B);
v.push(b'[');
v.push(0);
v.push(b'm');
}
#[cfg(feature = "alloc")]
pub fn write_color(v: &mut Vec<u8>, color: u8) {
v.push(0x1B);
v.push(b'[');
v.push(1);
v.push(b';');
let s = color.to_string();
let bytes = s.as_bytes();
v.extend(bytes.iter().cloned());
v.push(b'm');
}
#[cfg(feature = "std")]
#[cfg_attr(feature = "cargo-clippy", allow(implicit_hasher))]
pub fn print_codes(colors: &HashMap<u32, u8>, names: &HashMap<u32, &str>) -> String {
let mut v = Vec::new();
for (code, &color) in colors {
if let Some(&s) = names.get(code) {
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
} else {
let s = code.to_string();
let bytes = s.as_bytes();
write_color(&mut v, color);
v.extend(bytes.iter().cloned());
}
reset_color(&mut v);
v.push(b' ');
}
reset_color(&mut v);
String::from_utf8_lossy(&v[..]).into_owned()
}
#[cfg(feature = "std")]
pub fn print_offsets(input: &[u8], from: usize, offsets: &[(ErrorKind, usize, usize)]) -> String {
let mut v = Vec::with_capacity(input.len() * 3);
let mut i = from;
let chunk_size = 8;
let mut current_code: Option<u32> = None;
let mut current_code2: Option<u32> = None;
let colors = generate_colors(&offsets);
for chunk in input.chunks(chunk_size) {
let s = format!("{:08x}", i);
for &ch in s.as_bytes().iter() {
v.push(ch);
}
v.push(b'\t');
let mut k = i;
let mut l = i;
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, k) {
if let Some(current) = current_code {
if current != code {
reset_color(&mut v);
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
v.push(CHARS[(byte >> 4) as usize]);
v.push(CHARS[(byte & 0xf) as usize]);
v.push(b' ');
k = k + 1;
}
reset_color(&mut v);
if chunk_size > chunk.len() {
for _ in 0..(chunk_size - chunk.len()) {
v.push(b' ');
v.push(b' ');
v.push(b' ');
}
}
v.push(b'\t');
for &byte in chunk {
if let Some(code) = code_from_offset(&offsets, l) {
if let Some(current) = current_code2 {
if current != code {
reset_color(&mut v);
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
} else {
current_code2 = Some(code);
if let Some(&color) = colors.get(&code) {
write_color(&mut v, color);
}
}
}
if (byte >= 32 && byte <= 126) || byte >= 128 {
v.push(byte);
} else {
v.push(b'.');
}
l = l + 1;
}
reset_color(&mut v);
v.push(b'\n');
i = i + chunk_size;
}
String::from_utf8_lossy(&v[..]).into_owned()
}
*/

859
vendor/nom/src/internal.rs vendored Normal file
View File

@@ -0,0 +1,859 @@
//! Basic types to build the parsers
use self::Needed::*;
use crate::error::{self, ErrorKind, FromExternalError, ParseError};
use crate::lib::std::fmt;
use core::marker::PhantomData;
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, nom::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 `nom::Err`.
///
/// Outside of the parsing code, you can use the [Finish::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>>;
/// Helper trait to convert a parser's result to a more manageable type
pub trait Finish<I, O, E> {
/// converts the parser's result to a type that is more consumable by error
/// management libraries. It keeps the same `Ok` branch, and merges `Err::Error`
/// and `Err::Failure` into the `Err` side.
///
/// *warning*: 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()` on the parser's result
fn finish(self) -> Result<(I, O), E>;
}
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")
}
}
}
}
/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
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. For example, when a prefix has been
/// recognised and the next parser has been confirmed, if that parser fails, then the
/// entire process fails; there are no more parsers to try.
///
/// Distinguishing `Failure` this from `Error` is only relevant inside the parser's code. For
/// external consumers, both mean that parsing failed.
///
/// See also: [`Finish`].
///
#[derive(Debug, Clone, PartialEq)]
pub enum Err<Failure, Error = Failure> {
/// There was not enough data
Incomplete(Needed),
/// The parser had an error (recoverable)
Error(Error),
/// 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(Failure),
}
impl<E> Err<E> {
/// Tests if the result is Incomplete
pub fn is_incomplete(&self) -> bool {
matches!(self, Err::Incomplete(..))
}
/// 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};
#[cfg(feature = "alloc")]
impl Err<(&[u8], ErrorKind)> {
/// Obtaining ownership
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<(Vec<u8>, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<(&str, ErrorKind)> {
/// Obtaining ownership
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<(String, ErrorKind)> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<error::Error<&[u8]>> {
/// Obtaining ownership
#[cfg_attr(feature = "docsrs", doc(cfg(feature = "alloc")))]
pub fn to_owned(self) -> Err<error::Error<Vec<u8>>> {
self.map_input(ToOwned::to_owned)
}
}
#[cfg(feature = "alloc")]
impl Err<error::Error<&str>> {
/// Obtaining ownership
#[cfg_attr(feature = "docsrs", doc(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
}
}
/// Parser mode: influences how combinators build values
///
/// the [Parser] trait is generic over types implementing [Mode]. Its method are
/// called to produce and manipulate output values or errors.
///
/// The main implementations of this trait are:
/// * [Emit]: produce a value
/// * [Check]: apply the parser but do not generate a value
pub trait Mode {
/// The output type that may be generated
type Output<T>;
/// Produces a value
fn bind<T, F: FnOnce() -> T>(f: F) -> Self::Output<T>;
/// Applies a function over the produced value
fn map<T, U, F: FnOnce(T) -> U>(x: Self::Output<T>, f: F) -> Self::Output<U>;
/// Combines two values generated by previous parsers
fn combine<T, U, V, F: FnOnce(T, U) -> V>(
x: Self::Output<T>,
y: Self::Output<U>,
f: F,
) -> Self::Output<V>;
}
/// Produces a value. This is the default behaviour for parsers
pub struct Emit;
impl Mode for Emit {
type Output<T> = T;
#[inline(always)]
fn bind<T, F: FnOnce() -> T>(f: F) -> Self::Output<T> {
f()
}
#[inline(always)]
fn map<T, U, F: FnOnce(T) -> U>(x: Self::Output<T>, f: F) -> Self::Output<U> {
f(x)
}
#[inline(always)]
fn combine<T, U, V, F: FnOnce(T, U) -> V>(
x: Self::Output<T>,
y: Self::Output<U>,
f: F,
) -> Self::Output<V> {
f(x, y)
}
}
/// Applies the parser, but do not a produce a value
///
/// This has the effect of greatly reducing the amount of code generated and the
/// parser memory usage. Some combinators check for an error in a child parser but
/// discard the error, and for those, using [Check] makes sure the error is not
/// even generated, only the fact that an error happened remains
pub struct Check;
impl Mode for Check {
type Output<T> = ();
#[inline(always)]
fn bind<T, F: FnOnce() -> T>(_: F) -> Self::Output<T> {}
#[inline(always)]
fn map<T, U, F: FnOnce(T) -> U>(_: Self::Output<T>, _: F) -> Self::Output<U> {}
#[inline(always)]
fn combine<T, U, V, F: FnOnce(T, U) -> V>(
_: Self::Output<T>,
_: Self::Output<U>,
_: F,
) -> Self::Output<V> {
}
}
/// Parser result type
///
/// * `Ok` branch: a tuple of the remaining input data, and the output value.
/// The output value is of the `O` type if the output mode was [Emit], and `()`
/// if the mode was [Check]
/// * `Err` branch: an error of the `E` type if the erroor mode was [Emit], and `()`
/// if the mode was [Check]
pub type PResult<OM, I, O, E> = Result<
(I, <<OM as OutputMode>::Output as Mode>::Output<O>),
Err<E, <<OM as OutputMode>::Error as Mode>::Output<E>>,
>;
/// Trait Defining the parser's execution
///
/// The same parser implementation can vary in behaviour according to the chosen
/// output mode
pub trait OutputMode {
/// Defines the [Mode] for the output type. [Emit] will generate the value, [Check] will
/// apply the parser but will only generate `()` if successful. This can be used when
/// verifying that the input data conforms to the format without having to generate any
/// output data
type Output: Mode;
/// Defines the [Mode] for the output type. [Emit] will generate the value, [Check] will
/// apply the parser but will only generate `()` if an error happened. [Emit] should be
/// used when we want to handle the error and extract useful information from it. [Check]
/// is used when we just want to know if parsing failed and reject the data quickly.
type Error: Mode;
/// Indicates whether the input data is "complete", ie we already have the entire data in the
/// buffer, or if it is "streaming", where more data can be added later in the buffer. In
/// streaming mode, the parser will understand that a failure may mean that we are missing
/// data, and will return a specific error branch, [Err::Incomplete] to signal it. In complete
/// mode, the parser will generate a normal error
type Incomplete: IsStreaming;
}
/// Specifies the behaviour when a parser encounters an error that could be due to partial ata
pub trait IsStreaming {
/// called by parsers on partial data errors
/// * `needed` can hold the amount of additional data the parser would need to decide
/// * `err_f`: produces the error when in "complete" mode
fn incomplete<E, F: FnOnce() -> E>(needed: Needed, err_f: F) -> Err<E>;
/// Indicates whether the data is in streaming mode or not
fn is_streaming() -> bool;
}
/// Indicates that the input data is streaming: more data may be available later
pub struct Streaming;
impl IsStreaming for Streaming {
fn incomplete<E, F: FnOnce() -> E>(needed: Needed, _err_f: F) -> Err<E> {
Err::Incomplete(needed)
}
#[inline]
fn is_streaming() -> bool {
true
}
}
/// Indicates that the input data is complete: no more data may be added later
pub struct Complete;
impl IsStreaming for Complete {
fn incomplete<E, F: FnOnce() -> E>(_needed: Needed, err_f: F) -> Err<E> {
Err::Error(err_f())
}
#[inline]
fn is_streaming() -> bool {
false
}
}
/// Holds the parser execution modifiers: output [Mode], error [Mode] and
/// streaming behaviour for input data
pub struct OutputM<M: Mode, EM: Mode, S: IsStreaming> {
m: PhantomData<M>,
em: PhantomData<EM>,
s: PhantomData<S>,
}
impl<M: Mode, EM: Mode, S: IsStreaming> OutputMode for OutputM<M, EM, S> {
type Output = M;
type Error = EM;
type Incomplete = S;
}
/// All nom parsers implement this trait
pub trait Parser<Input> {
/// Type of the produced value
type Output;
/// Error type of this parser
type Error: ParseError<Input>;
/// A parser takes in input type, and returns a `Result` containing
/// either the remaining input and the output value, or an error
#[inline]
fn parse(&mut self, input: Input) -> IResult<Input, Self::Output, Self::Error> {
self.process::<OutputM<Emit, Emit, Streaming>>(input)
}
/// A parser takes in input type, and returns a `Result` containing
/// either the remaining input and the output value, or an error
#[inline]
fn parse_complete(&mut self, input: Input) -> IResult<Input, Self::Output, Self::Error> {
self.process::<OutputM<Emit, Emit, Complete>>(input)
}
/// A parser takes in input type, and returns a `Result` containing
/// either the remaining input and the output value, or an error
fn process<OM: OutputMode>(
&mut self,
input: Input,
) -> PResult<OM, Input, Self::Output, Self::Error>;
/// Maps a function over the result of a parser
fn map<G, O2>(self, g: G) -> Map<Self, G>
where
G: FnMut(Self::Output) -> O2,
Self: core::marker::Sized,
{
Map { f: self, g }
}
/// Applies a function returning a `Result` over the result of a parser.
fn map_res<G, O2, E2>(self, g: G) -> MapRes<Self, G>
where
G: FnMut(Self::Output) -> Result<O2, E2>,
Self::Error: FromExternalError<Input, E2>,
Self: core::marker::Sized,
{
MapRes { f: self, g }
}
/// Applies a function returning an `Option` over the result of a parser.
fn map_opt<G, O2>(self, g: G) -> MapOpt<Self, G>
where
G: FnMut(Self::Output) -> Option<O2>,
Self: core::marker::Sized,
{
MapOpt { f: self, g }
}
/// Creates a second parser from the output of the first one, then apply over the rest of the input
fn flat_map<G, H>(self, g: G) -> FlatMap<Self, G>
where
G: FnMut(Self::Output) -> H,
H: Parser<Input, Error = Self::Error>,
Self: core::marker::Sized,
{
FlatMap { f: self, g }
}
/// Applies a second parser over the output of the first one
fn and_then<G>(self, g: G) -> AndThen<Self, G>
where
G: Parser<Self::Output, Error = Self::Error>,
Self: core::marker::Sized,
{
AndThen { f: self, g }
}
/// Applies a second parser after the first one, return their results as a tuple
fn and<G, O2>(self, g: G) -> And<Self, G>
where
G: Parser<Input, Output = O2, Error = Self::Error>,
Self: core::marker::Sized,
{
And { f: self, g }
}
/// Applies a second parser over the input if the first one failed
fn or<G>(self, g: G) -> Or<Self, G>
where
G: Parser<Input, Output = Self::Output, Error = Self::Error>,
Self: core::marker::Sized,
{
Or { f: self, g }
}
/// automatically converts the parser's output and error values to another type, as long as they
/// implement the `From` trait
fn into<O2: From<Self::Output>, E2: From<Self::Error>>(self) -> Into<Self, O2, E2>
where
Self: core::marker::Sized,
{
Into {
f: self,
phantom_out2: core::marker::PhantomData,
phantom_err2: core::marker::PhantomData,
}
}
}
impl<I, O, E: ParseError<I>, F> Parser<I> for F
where
F: FnMut(I) -> IResult<I, O, E>,
{
type Output = O;
type Error = E;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (i, o) = self(i).map_err(|e| match e {
Err::Incomplete(i) => Err::Incomplete(i),
Err::Error(e) => Err::Error(OM::Error::bind(|| e)),
Err::Failure(e) => Err::Failure(e),
})?;
Ok((i, OM::Output::bind(|| o)))
}
}
macro_rules! impl_parser_for_tuple {
($($parser:ident $output:ident),+) => (
#[allow(non_snake_case)]
impl<I, $($output),+, E: ParseError<I>, $($parser),+> Parser<I> for ($($parser),+,)
where
$($parser: Parser<I, Output = $output, Error = E>),+
{
type Output = ($($output),+,);
type Error = E;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let ($(ref mut $parser),+,) = *self;
// FIXME: is there a way to avoid producing the output values?
$(let(i, $output) = $parser.process::<OutputM<Emit, OM::Error, OM::Incomplete>>(i)?;)+
// ???
Ok((i, OM::Output::bind(|| ($($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<I, O, E: ParseError<I>> Parser<I> for Box<dyn Parser<I, Output = O, Error = E>> {
type Output = O;
type Error = E;
fn process<OM: OutputMode>(&mut self, input: I) -> PResult<OM, I, Self::Output, Self::Error> {
(**self).process(input)
}
}
*/
/// Implementation of `Parser::map`
pub struct Map<F, G> {
f: F,
g: G,
}
impl<I, O2, E: ParseError<I>, F: Parser<I, Error = E>, G: FnMut(<F as Parser<I>>::Output) -> O2>
Parser<I> for Map<F, G>
{
type Output = O2;
type Error = E;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
match self.f.process::<OM>(i) {
Err(e) => Err(e),
Ok((i, o)) => Ok((i, OM::Output::map(o, |o| (self.g)(o)))),
}
}
}
/// Implementation of `Parser::map_res`
pub struct MapRes<F, G> {
f: F,
g: G,
}
impl<I, O2, E2, F, G> Parser<I> for MapRes<F, G>
where
I: Clone,
<F as Parser<I>>::Error: FromExternalError<I, E2>,
F: Parser<I>,
G: FnMut(<F as Parser<I>>::Output) -> Result<O2, E2>,
{
type Output = O2;
type Error = <F as Parser<I>>::Error;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (input, o1) = self
.f
.process::<OutputM<Emit, OM::Error, OM::Incomplete>>(i.clone())?;
match (self.g)(o1) {
Ok(o2) => Ok((input, OM::Output::bind(|| o2))),
Err(e) => Err(Err::Error(OM::Error::bind(|| {
<F as Parser<I>>::Error::from_external_error(i, ErrorKind::MapRes, e)
}))),
}
}
}
/// Implementation of `Parser::map_opt`
pub struct MapOpt<F, G> {
f: F,
g: G,
}
impl<I, O2, F, G> Parser<I> for MapOpt<F, G>
where
I: Clone,
F: Parser<I>,
G: FnMut(<F as Parser<I>>::Output) -> Option<O2>,
{
type Output = O2;
type Error = <F as Parser<I>>::Error;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (input, o1) = self
.f
.process::<OutputM<Emit, OM::Error, OM::Incomplete>>(i.clone())?;
match (self.g)(o1) {
Some(o2) => Ok((input, OM::Output::bind(|| o2))),
None => Err(Err::Error(OM::Error::bind(|| {
<F as Parser<I>>::Error::from_error_kind(i, ErrorKind::MapOpt)
}))),
}
}
}
/// Implementation of `Parser::flat_map`
pub struct FlatMap<F, G> {
f: F,
g: G,
}
impl<
I,
E: ParseError<I>,
F: Parser<I, Error = E>,
G: FnMut(<F as Parser<I>>::Output) -> H,
H: Parser<I, Error = E>,
> Parser<I> for FlatMap<F, G>
{
type Output = <H as Parser<I>>::Output;
type Error = E;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (input, o1) = self
.f
.process::<OutputM<Emit, OM::Error, OM::Incomplete>>(i)?;
(self.g)(o1).process::<OM>(input)
}
}
/// Implementation of `Parser::and_then`
pub struct AndThen<F, G> {
f: F,
g: G,
}
impl<I, F: Parser<I>, G: Parser<<F as Parser<I>>::Output, Error = <F as Parser<I>>::Error>>
Parser<I> for AndThen<F, G>
{
type Output = <G as Parser<<F as Parser<I>>::Output>>::Output;
type Error = <F as Parser<I>>::Error;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (input, o1) = self
.f
.process::<OutputM<Emit, OM::Error, OM::Incomplete>>(i)?;
let (_, o2) = self.g.process::<OM>(o1)?;
Ok((input, o2))
}
}
/// Implementation of `Parser::and`
pub struct And<F, G> {
f: F,
g: G,
}
impl<I, E: ParseError<I>, F: Parser<I, Error = E>, G: Parser<I, Error = E>> Parser<I>
for And<F, G>
{
type Output = (<F as Parser<I>>::Output, <G as Parser<I>>::Output);
type Error = E;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (i, o1) = self.f.process::<OM>(i)?;
let (i, o2) = self.g.process::<OM>(i)?;
Ok((i, OM::Output::combine(o1, o2, |o1, o2| (o1, o2))))
}
}
/// Implementation of `Parser::or`
pub struct Or<F, G> {
f: F,
g: G,
}
impl<
I: Clone,
O,
E: ParseError<I>,
F: Parser<I, Output = O, Error = E>,
G: Parser<I, Output = O, Error = E>,
> Parser<I> for Or<F, G>
{
type Output = <F as Parser<I>>::Output;
type Error = <F as Parser<I>>::Error;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
match self.f.process::<OM>(i.clone()) {
Err(Err::Error(e1)) => match self.g.process::<OM>(i) {
Err(Err::Error(e2)) => Err(Err::Error(OM::Error::combine(e1, e2, |e1, e2| e1.or(e2)))),
res => res,
},
res => res,
}
}
}
/// Implementation of `Parser::into`
pub struct Into<F, O2, E2> {
f: F,
phantom_out2: core::marker::PhantomData<O2>,
phantom_err2: core::marker::PhantomData<E2>,
}
impl<
I,
O2: From<<F as Parser<I>>::Output>,
E2: crate::error::ParseError<I> + From<<F as Parser<I>>::Error>,
F: Parser<I>,
> Parser<I> for Into<F, O2, E2>
{
type Output = O2;
type Error = E2;
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
match self.f.process::<OM>(i) {
Ok((i, o)) => Ok((i, OM::Output::map(o, |o| o.into()))),
Err(Err::Error(e)) => Err(Err::Error(OM::Error::map(e, |e| e.into()))),
Err(Err::Failure(e)) => Err(Err::Failure(e.into())),
Err(Err::Incomplete(e)) => Err(Err::Incomplete(e)),
}
}
}
/// Alternate between two Parser implementations with the same result type.
pub(crate) enum Either<F, G> {
Left(F),
Right(G),
}
impl<
I,
F: Parser<I>,
G: Parser<I, Output = <F as Parser<I>>::Output, Error = <F as Parser<I>>::Error>,
> Parser<I> for Either<F, G>
{
type Output = <F as Parser<I>>::Output;
type Error = <F as Parser<I>>::Error;
#[inline]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
match self {
Either::Left(f) => f.process::<OM>(i),
Either::Right(g) => g.process::<OM>(i),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::error::ErrorKind;
use crate::bytes::streaming::{tag, take};
use crate::number::streaming::be_u16;
use crate::sequence::terminated;
#[doc(hidden)]
#[macro_export]
macro_rules! assert_size (
($t:ty, $sz:expr) => (
assert_eq!($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);
//FIXME: since rust 1.65, this is now 32 bytes, likely thanks to https://github.com/rust-lang/rust/pull/94075
// deactivating that test for now because it'll have different values depending on the rust version
// 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 native_tuple_test() {
fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8])> {
terminated((be_u16, take(3u8)), tag("fg")).parse(i)
}
assert_eq!(
tuple_3(&b"abcdefgh"[..]),
Ok((&b"h"[..], (0x6162u16, &b"cde"[..])))
);
assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(
tuple_3(&b"abcdejk"[..]),
Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
);
}
}

460
vendor/nom/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,460 @@
//! # nom, eating data byte by byte
//!
//! nom is a parser combinator library with a focus on safe parsing,
//! streaming patterns, and as much as possible zero copy.
//!
//! ## Example
//!
//! ```rust
//! use nom::{
//! IResult,
//! Parser,
//! bytes::complete::{tag, take_while_m_n},
//! combinator::map_res
//! };
//!
//! #[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> {
//! map_res(
//! take_while_m_n(2, 2, is_hex_digit),
//! 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() {
//! assert_eq!(hex_color("#2F14DF"), Ok(("", Color {
//! red: 47,
//! green: 20,
//! blue: 223,
//! })));
//! }
//! ```
//!
//! The code is available on [GitHub](https://github.com/rust-bakery/nom)
//!
//! There are a few [guides](https://github.com/rust-bakery/nom/tree/main/doc) with more details
//! about [how to write parsers](https://github.com/rust-bakery/nom/blob/main/doc/making_a_new_parser_from_scratch.md),
//! or the [error management system](https://github.com/rust-bakery/nom/blob/main/doc/error_management.md).
//! You can also check out the [recipes] module that contains examples of common patterns.
//!
//! **Looking for a specific combinator? Read the
//! ["choose a combinator" guide](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md)**
//!
//! If you are upgrading to nom 5.0, please read the
//! [migration document](https://github.com/rust-bakery/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 nom::{
//! IResult,
//! Parser,
//! sequence::delimited,
//! // see the "streaming/complete" paragraph lower for an explanation of these submodules
//! character::complete::char,
//! bytes::complete::is_not
//! };
//!
//! fn parens(input: &str) -> IResult<&str, &str> {
//! delimited(char('('), is_not(")"), char(')')).parse(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 nom::{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 nom::{IResult, bytes::streaming::take};
//! fn take4(input: &str) -> IResult<&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 nom::{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](https://github.com/rust-bakery/nom/blob/main/doc/choosing_a_combinator.md) for an exhaustive list of parsers.
//! See also the rest of the documentation [here](https://github.com/rust-bakery/nom/tree/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 nom::IResult;
//! use nom::bytes::complete::{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 nom::{IResult, Parser};
//! use nom::branch::alt;
//! use nom::bytes::complete::tag;
//!
//! let mut alt_tags = alt((tag("abcd"), tag("efgh")));
//!
//! assert_eq!(alt_tags.parse(&b"abcdxxx"[..]), Ok((&b"xxx"[..], &b"abcd"[..])));
//! assert_eq!(alt_tags.parse(&b"efghxxx"[..]), Ok((&b"xxx"[..], &b"efgh"[..])));
//! assert_eq!(alt_tags.parse(&b"ijklxxx"[..]), Err(nom::Err::Error((&b"ijklxxx"[..], nom::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 nom::{IResult, Parser, combinator::opt, bytes::complete::tag};
//! fn abcd_opt(i: &[u8]) -> IResult<&[u8], Option<&[u8]>> {
//! opt(tag("abcd")).parse(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 nom::{IResult, Parser, multi::many0, bytes::complete::tag};
//! use std::str;
//!
//! fn multi(i: &str) -> IResult<&str, Vec<&str>> {
//! many0(tag("abcd")).parse(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 are
//! used to apply a series of parsers then assemble their results.
//!
//! Example with a tuple of parsers:
//!
//! ```rust
//! # fn main() {
//! use nom::{
//! error::ErrorKind,
//! Needed,
//! Parser,
//! number::streaming::be_u16,
//! bytes::streaming::{tag, take}};
//!
//! let mut tpl = (be_u16, take(3u8), tag("fg"));
//!
//! assert_eq!(
//! tpl.parse(&b"abcdefgh"[..]),
//! Ok((
//! &b"h"[..],
//! (0x6162u16, &b"cde"[..], &b"fg"[..])
//! ))
//! );
//! assert_eq!(tpl.parse(&b"abcde"[..]), Err(nom::Err::Incomplete(Needed::new(2))));
//! let input = &b"abcdejk"[..];
//! assert_eq!(tpl.parse(input), Err(nom::Err::Error((&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 nom::{IResult, bytes::complete::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})));
//! # }
//! ```
//!
//! ## Streaming / Complete
//!
//! Some of nom's modules have `streaming` or `complete` submodules. They hold
//! different variants of the same combinators.
//!
//! A streaming parser assumes that we might not have all of the input 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.
//!
//! A complete parser assumes that we already have all of the input data.
//! This will be the common case with small files that can be read entirely to
//! memory.
//!
//! Here is how it works in practice:
//!
//! ```rust
//! use nom::{IResult, Err, Needed, error::{Error, ErrorKind}, bytes, character};
//!
//! fn take_streaming(i: &[u8]) -> IResult<&[u8], &[u8]> {
//! bytes::streaming::take(4u8)(i)
//! }
//!
//! fn take_complete(i: &[u8]) -> IResult<&[u8], &[u8]> {
//! bytes::complete::take(4u8)(i)
//! }
//!
//! // both parsers will take 4 bytes as expected
//! assert_eq!(take_streaming(&b"abcde"[..]), Ok((&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(&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: &str) -> IResult<&str, &str> {
//! character::streaming::alpha0(i)
//! }
//!
//! fn alpha0_complete(i: &str) -> IResult<&str, &str> {
//! character::complete::alpha0(i)
//! }
//!
//! // if there's a clear limit to the recognized characters, both parsers work the same way
//! assert_eq!(alpha0_streaming("abcd;"), Ok((";", "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("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")));
//! ```
//! **Going further:** Read the [guides](https://github.com/rust-bakery/nom/tree/main/doc),
//! check out the [recipes]!
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(feature = "docsrs", feature(doc_cfg))]
#![allow(clippy::doc_markdown)]
#![deny(missing_docs)]
#[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.
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"))]
/// 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, num, ops, option, result, slice, str};
/// internal reproduction of std prelude
#[doc(hidden)]
pub mod prelude {
pub use core::prelude as v1;
}
}
#[cfg(feature = "std")]
/// 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, num, 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::internal::*;
pub use self::traits::*;
#[macro_use]
mod macros;
#[macro_use]
pub mod error;
pub mod branch;
pub mod combinator;
mod internal;
pub mod multi;
pub mod sequence;
mod traits;
pub mod bits;
pub mod bytes;
pub mod character;
mod str;
pub mod number;
#[cfg(all(feature = "std", any(doc, doctest, feature = "docsrs")))]
#[cfg_attr(any(doc, doctest, feature = "docsrs"), doc = include_str!("../doc/nom_recipes.md"))]
pub mod recipes {}

23
vendor/nom/src/macros.rs vendored Normal file
View File

@@ -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)*));
);

1870
vendor/nom/src/multi/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff

859
vendor/nom/src/multi/tests.rs vendored Normal file
View File

@@ -0,0 +1,859 @@
use super::{length_data, length_value, many0_count, many1_count};
use crate::{
bytes::streaming::tag,
character::streaming::digit1 as digit,
error::{ErrorKind, ParseError},
internal::{Err, IResult, Needed},
lib::std::str::{self, FromStr},
number::streaming::{be_u16, be_u8},
sequence::pair,
Parser,
};
#[cfg(feature = "alloc")]
use crate::{
lib::std::vec::Vec,
multi::{
count, fold, fold_many0, fold_many1, fold_many_m_n, length_count, many, many0, many1, many_m_n,
many_till, separated_list0, separated_list1,
},
};
#[test]
#[cfg(feature = "alloc")]
fn separated_list0_test() {
use core::num::NonZeroUsize;
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(","), tag("abcd")).parse(i)
}
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(","), tag("")).parse(i)
}
fn empty_sep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(""), tag("abc")).parse(i)
}
fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(".."), tag("abcd")).parse(i)
}
fn empty_both(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(""), tag("")).parse(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(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
assert_eq!(multi(c), Ok((&b"azerty"[..], Vec::new())));
let res3 = vec![&b""[..], &b""[..], &b""[..]];
assert_eq!(multi_empty(d), Ok((&b"abc"[..], res3)));
assert_eq!(
empty_sep(i),
Err(Err::Incomplete(Needed::Size(NonZeroUsize::new(3).unwrap())))
);
assert_eq!(
empty_both(i),
Err(Err::Error(error_position!(i, ErrorKind::SeparatedList)))
);
let res4 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(e), Ok((&b",ef"[..], res4)));
assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
}
#[test]
#[cfg(feature = "alloc")]
fn separated_list1_test() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list1(tag(","), tag("abcd")).parse(i)
}
fn multi_longsep(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list1(tag(".."), tag("abcd")).parse(i)
}
fn empty_both(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
separated_list0(tag(""), tag("")).parse(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(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(b), Ok((&b"ef"[..], res2)));
assert_eq!(
multi(c),
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
);
assert_eq!(
empty_both(f),
Err(Err::Error(error_position!(f, ErrorKind::SeparatedList)))
);
let res3 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(d), Ok((&b",ef"[..], res3)));
assert_eq!(multi(f), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(multi_longsep(g), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(multi(h), Err(Err::Incomplete(Needed::new(1))));
}
#[test]
#[cfg(feature = "alloc")]
fn many0_test() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many0(tag("abcd")).parse(i)
}
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many0(tag("")).parse(i)
}
assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
assert_eq!(
multi(&b"abcdabcdefgh"[..]),
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
);
assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(
multi_empty(&b"abcdef"[..]),
Err(Err::Error(error_position!(
&b"abcdef"[..],
ErrorKind::Many0
)))
);
}
#[test]
#[cfg(feature = "alloc")]
fn many1_test() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many1(tag("abcd")).parse(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(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
assert_eq!(
multi(c),
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
);
assert_eq!(multi(d), Err(Err::Incomplete(Needed::new(2))));
}
#[test]
#[cfg(feature = "alloc")]
fn many_till_test() {
#[allow(clippy::type_complexity)]
fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
many_till(tag("abcd"), tag("efgh")).parse(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]> {
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).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(multi0(a), Ok((a, Vec::new())));
fn multi1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many1(tst).parse(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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many_m_n(2, 4, tag("Abcd")).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
let e = &b"AbcdAb"[..];
assert_eq!(
multi(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
}
#[test]
#[cfg(feature = "alloc")]
fn count_test() {
const TIMES: usize = 2;
fn cnt_2(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
count(tag("abc"), TIMES).parse(i)
}
assert_eq!(
cnt_2(&b"abcabcabcdef"[..]),
Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
);
assert_eq!(cnt_2(&b"ab"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(cnt_2(&b"abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(
cnt_2(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
cnt_2(&b"xxxabcabcdef"[..]),
Err(Err::Error(error_position!(
&b"xxxabcabcdef"[..],
ErrorKind::Tag
)))
);
assert_eq!(
cnt_2(&b"abcxxxabcdef"[..]),
Err(Err::Error(error_position!(
&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).parse(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, Eq, 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
}
}
fn number(i: &[u8]) -> IResult<&[u8], u32> {
use crate::combinator::map_res;
map_res(map_res(digit, str::from_utf8), FromStr::from_str).parse(i)
}
#[test]
#[cfg(feature = "alloc")]
fn length_count_test() {
fn cnt(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
length_count(number, tag("abc")).parse(i)
}
assert_eq!(
cnt(&b"2abcabcabcdef"[..]),
Ok((&b"abcdef"[..], vec![&b"abc"[..], &b"abc"[..]]))
);
assert_eq!(cnt(&b"2ab"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(cnt(&b"3abcab"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(
cnt(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
);
assert_eq!(
cnt(&b"2abcxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn length_data_test() {
fn take(i: &[u8]) -> IResult<&[u8], &[u8]> {
length_data(number).parse(i)
}
assert_eq!(
take(&b"6abcabcabcdef"[..]),
Ok((&b"abcdef"[..], &b"abcabc"[..]))
);
assert_eq!(take(&b"3ab"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(
take(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Digit)))
);
assert_eq!(take(&b"2abcxxx"[..]), Ok((&b"cxxx"[..], &b"ab"[..])));
}
#[test]
fn length_value_test() {
fn length_value_1(i: &[u8]) -> IResult<&[u8], u16> {
length_value(be_u8, be_u16).parse(i)
}
fn length_value_2(i: &[u8]) -> IResult<&[u8], (u8, u8)> {
length_value(be_u8, (be_u8, be_u8)).parse(i)
}
let i1 = [0, 5, 6];
assert_eq!(
length_value_1(&i1),
Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
);
assert_eq!(
length_value_2(&i1),
Err(Err::Error(error_position!(&b""[..], ErrorKind::Complete)))
);
let i2 = [1, 5, 6, 3];
assert_eq!(
length_value_1(&i2),
Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
);
assert_eq!(
length_value_2(&i2),
Err(Err::Error(error_position!(&i2[1..2], ErrorKind::Complete)))
);
let i3 = [2, 5, 6, 3, 4, 5, 7];
assert_eq!(length_value_1(&i3), Ok((&i3[3..], 1286)));
assert_eq!(length_value_2(&i3), Ok((&i3[3..], (5, 6))));
let i4 = [3, 5, 6, 3, 4, 5];
assert_eq!(length_value_1(&i4), Ok((&i4[4..], 1286)));
assert_eq!(length_value_2(&i4), Ok((&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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold_many0(tag("abcd"), Vec::new, fold_into_vec).parse(i)
}
fn multi_empty(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold_many0(tag(""), Vec::new, fold_into_vec).parse(i)
}
assert_eq!(multi(&b"abcdef"[..]), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
assert_eq!(
multi(&b"abcdabcdefgh"[..]),
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
);
assert_eq!(multi(&b"azerty"[..]), Ok((&b"azerty"[..], Vec::new())));
assert_eq!(multi(&b"abcdab"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(multi(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(multi(&b""[..]), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(
multi_empty(&b"abcdef"[..]),
Err(Err::Error(error_position!(
&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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold_many1(tag("abcd"), Vec::new, fold_into_vec).parse(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(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(multi(b), Ok((&b"efgh"[..], res2)));
assert_eq!(
multi(c),
Err(Err::Error(error_position!(c, ErrorKind::Many1)))
);
assert_eq!(multi(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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold_many_m_n(2, 4, tag("Abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
let e = &b"AbcdAb"[..];
assert_eq!(
multi(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(c), Ok((&b"efgh"[..], res2)));
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(multi(d), Ok((&b"Abcdefgh"[..], res3)));
assert_eq!(multi(e), Err(Err::Incomplete(Needed::new(2))));
}
#[test]
fn many0_count_test() {
fn count0_nums(i: &[u8]) -> IResult<&[u8], usize> {
many0_count(pair(digit, tag(","))).parse(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(pair(digit, tag(","))).parse(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
)))
);
}
#[test]
#[cfg(feature = "alloc")]
fn many_test() {
// should not go into an infinite loop
fn many_error_0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
Err(Err::Error(error_position!(input, ErrorKind::Tag)))
}
many(0.., tst).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(many_error_0(a), Ok((a, Vec::new())));
fn many_error_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
Err(Err::Error(error_position!(input, ErrorKind::Tag)))
}
many(1.., tst).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(
many_error_1(a),
Err(Err::Error(error_position!(a, ErrorKind::Tag)))
);
fn many_error(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0.., tag("")).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(
many_error(a),
Err(Err::Error(error_position!(a, ErrorKind::Many)))
);
fn many_invalid(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(crate::lib::std::ops::Range::default(), tag("a")).parse(i)
}
let a = &b"a"[..];
let b = &b"b"[..];
assert_eq!(
many_invalid(a),
Err(Err::Failure(error_position!(a, ErrorKind::Many)))
);
assert_eq!(
many_invalid(b),
Err(Err::Failure(error_position!(b, ErrorKind::Many)))
);
fn many_any(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0.., tag("abcd")).parse(i)
}
let a = &b"abcdef"[..];
let b = &b"abcdabcdefgh"[..];
let c = &b"azerty"[..];
let d = &b"abcdab"[..];
let e = &b"abcd"[..];
let f = &b""[..];
assert_eq!(many_any(a), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
assert_eq!(
many_any(b),
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
);
assert_eq!(many_any(c), Ok((&b"azerty"[..], Vec::new())));
assert_eq!(many_any(d), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(many_any(e), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(many_any(f), Err(Err::Incomplete(Needed::new(4))));
fn many_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(1.., tag("abcd")).parse(i)
}
let a = &b"abcdef"[..];
let b = &b"abcdabcdefgh"[..];
let c = &b"azerty"[..];
let d = &b"abcdab"[..];
let res1 = vec![&b"abcd"[..]];
assert_eq!(many_1(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(many_1(b), Ok((&b"efgh"[..], res2)));
assert_eq!(
many_1(c),
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
);
assert_eq!(many_1(d), Err(Err::Incomplete(Needed::new(2))));
fn many_m_n(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(2..=4, tag("Abcd")).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
let e = &b"AbcdAb"[..];
assert_eq!(
many_m_n(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(many_m_n(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(many_m_n(c), Ok((&b"efgh"[..], res2)));
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(many_m_n(d), Ok((&b"Abcdefgh"[..], res3)));
assert_eq!(many_m_n(e), Err(Err::Incomplete(Needed::new(2))));
fn many_fixed(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(2, tag("Abcd")).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAb"[..];
assert_eq!(
many_fixed(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(many_fixed(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(many_fixed(c), Ok((&b"AbcdAbcdefgh"[..], res2)));
assert_eq!(many_fixed(d), Err(Err::Incomplete(Needed::new(2))));
fn multi_exclusive(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0..2, tag("Abcd")).parse(i)
}
let a = &b"AbcdAbcdAbcd"[..];
let b = &b"AAA"[..];
let res1 = vec![&b"Abcd"[..]];
assert_eq!(multi_exclusive(a), Ok((&b"AbcdAbcd"[..], res1)));
let res2 = vec![];
assert_eq!(multi_exclusive(b), Ok((&b"AAA"[..], res2)));
fn many_never(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0..=0, tag("A")).parse(i)
}
let a = &b"AA"[..];
let b = &b"B"[..];
assert_eq!(many_never(a), Ok((&b"AA"[..], Vec::new())));
assert_eq!(many_never(b), Ok((&b"B"[..], Vec::new())));
}
#[test]
#[cfg(feature = "alloc")]
fn fold_test() {
fn fold_into_vec<T>(mut acc: Vec<T>, item: T) -> Vec<T> {
acc.push(item);
acc
}
// should not go into an infinite loop
fn fold_error_0(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
Err(Err::Error(error_position!(input, ErrorKind::Tag)))
}
fold(0.., tst, Vec::new, fold_into_vec).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(fold_error_0(a), Ok((a, Vec::new())));
fn fold_error_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fn tst(input: &[u8]) -> IResult<&[u8], &[u8]> {
Err(Err::Error(error_position!(input, ErrorKind::Tag)))
}
fold(1.., tst, Vec::new, fold_into_vec).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(
fold_error_1(a),
Err(Err::Error(error_position!(a, ErrorKind::Tag)))
);
fn fold_error(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(0.., tag(""), Vec::new, fold_into_vec).parse(i)
}
let a = &b"abcdef"[..];
assert_eq!(
fold_error(a),
Err(Err::Error(error_position!(a, ErrorKind::Fold)))
);
fn fold_invalid(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(
crate::lib::std::ops::Range::default(),
tag("a"),
Vec::new,
fold_into_vec,
)
.parse(i)
}
let a = &b"a"[..];
let b = &b"b"[..];
assert_eq!(
fold_invalid(a),
Err(Err::Failure(error_position!(a, ErrorKind::Fold)))
);
assert_eq!(
fold_invalid(b),
Err(Err::Failure(error_position!(b, ErrorKind::Fold)))
);
fn fold_any(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(0.., tag("abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"abcdef"[..];
let b = &b"abcdabcdefgh"[..];
let c = &b"azerty"[..];
let d = &b"abcdab"[..];
let e = &b"abcd"[..];
let f = &b""[..];
assert_eq!(fold_any(a), Ok((&b"ef"[..], vec![&b"abcd"[..]])));
assert_eq!(
fold_any(b),
Ok((&b"efgh"[..], vec![&b"abcd"[..], &b"abcd"[..]]))
);
assert_eq!(fold_any(c), Ok((c, Vec::new())));
assert_eq!(fold_any(d), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(fold_any(e), Err(Err::Incomplete(Needed::new(4))));
assert_eq!(fold_any(f), Err(Err::Incomplete(Needed::new(4))));
fn fold_1(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(1.., tag("abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"abcdef"[..];
let b = &b"abcdabcdefgh"[..];
let c = &b"azerty"[..];
let d = &b"abcdab"[..];
let res1 = vec![&b"abcd"[..]];
assert_eq!(fold_1(a), Ok((&b"ef"[..], res1)));
let res2 = vec![&b"abcd"[..], &b"abcd"[..]];
assert_eq!(fold_1(b), Ok((&b"efgh"[..], res2)));
assert_eq!(
fold_1(c),
Err(Err::Error(error_position!(c, ErrorKind::Tag)))
);
assert_eq!(fold_1(d), Err(Err::Incomplete(Needed::new(2))));
fn fold_m_n(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(2..=4, tag("Abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAbcdAbcdAbcdAbcdefgh"[..];
let e = &b"AbcdAb"[..];
assert_eq!(
fold_m_n(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(fold_m_n(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(fold_m_n(c), Ok((&b"efgh"[..], res2)));
let res3 = vec![&b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(fold_m_n(d), Ok((&b"Abcdefgh"[..], res3)));
assert_eq!(fold_m_n(e), Err(Err::Incomplete(Needed::new(2))));
fn fold_fixed(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(2, tag("Abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"Abcdef"[..];
let b = &b"AbcdAbcdefgh"[..];
let c = &b"AbcdAbcdAbcdAbcdefgh"[..];
let d = &b"AbcdAb"[..];
assert_eq!(
fold_fixed(a),
Err(Err::Error(error_position!(&b"ef"[..], ErrorKind::Tag)))
);
let res1 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(fold_fixed(b), Ok((&b"efgh"[..], res1)));
let res2 = vec![&b"Abcd"[..], &b"Abcd"[..]];
assert_eq!(fold_fixed(c), Ok((&b"AbcdAbcdefgh"[..], res2)));
assert_eq!(fold_fixed(d), Err(Err::Incomplete(Needed::new(2))));
fn fold_exclusive(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(0..2, tag("Abcd"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"AbcdAbcdAbcd"[..];
let b = &b"AAA"[..];
let res1 = vec![&b"Abcd"[..]];
assert_eq!(fold_exclusive(a), Ok((&b"AbcdAbcd"[..], res1)));
let res2 = vec![];
assert_eq!(fold_exclusive(b), Ok((&b"AAA"[..], res2)));
fn fold_never(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
fold(0..=0, tag("A"), Vec::new, fold_into_vec).parse(i)
}
let a = &b"AAA"[..];
let b = &b"B"[..];
assert_eq!(fold_never(a), Ok((&b"AAA"[..], Vec::new())));
assert_eq!(fold_never(b), Ok((&b"B"[..], Vec::new())));
}

1970
vendor/nom/src/number/complete.rs vendored Normal file

File diff suppressed because it is too large Load Diff

1482
vendor/nom/src/number/mod.rs vendored Normal file

File diff suppressed because it is too large Load Diff

2066
vendor/nom/src/number/streaming.rs vendored Normal file

File diff suppressed because it is too large Load Diff

321
vendor/nom/src/sequence/mod.rs vendored Normal file
View File

@@ -0,0 +1,321 @@
//! Combinators applying parsers in sequence
#[cfg(test)]
mod tests;
use crate::error::ParseError;
use crate::internal::{IResult, Parser};
use crate::{Check, OutputM, OutputMode, PResult};
/// Gets an object from the first parser,
/// then gets another object from the second parser.
///
/// # Arguments
/// * `first` The first parser to apply.
/// * `second` The second parser to apply.
///
/// # Example
/// ```rust
/// use nom::sequence::pair;
/// use nom::bytes::complete::tag;
/// use nom::{error::ErrorKind, Err, Parser};
///
/// let mut parser = pair(tag("abc"), tag("efg"));
///
/// assert_eq!(parser.parse("abcefg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn pair<I, O1, O2, E: ParseError<I>, F, G>(
first: F,
second: G,
) -> impl Parser<I, Output = (O1, O2), Error = E>
where
F: Parser<I, Output = O1, Error = E>,
G: Parser<I, Output = O2, Error = E>,
{
first.and(second)
}
/// 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 nom::{Err, error::ErrorKind, Needed, Parser};
/// # use nom::Needed::Size;
/// use nom::sequence::preceded;
/// use nom::bytes::complete::tag;
///
/// let mut parser = preceded(tag("abc"), tag("efg"));
///
/// assert_eq!(parser.parse("abcefg"), Ok(("", "efg")));
/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", "efg")));
/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn preceded<I, O, E: ParseError<I>, F, G>(
first: F,
second: G,
) -> impl Parser<I, Output = O, Error = E>
where
F: Parser<I, Error = E>,
G: Parser<I, Output = O, Error = E>,
{
Preceded {
f: first,
g: second,
}
}
/// a
pub struct Preceded<F, G> {
f: F,
g: G,
}
impl<I, E: ParseError<I>, F: Parser<I, Error = E>, G: Parser<I, Error = E>> Parser<I>
for Preceded<F, G>
{
type Output = <G as Parser<I>>::Output;
type Error = E;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (i, _) = self
.f
.process::<OutputM<Check, OM::Error, OM::Incomplete>>(i)?;
let (i, o2) = self.g.process::<OM>(i)?;
Ok((i, o2))
}
}
/// 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 nom::{Err, error::ErrorKind, Needed, Parser};
/// # use nom::Needed::Size;
/// use nom::sequence::terminated;
/// use nom::bytes::complete::tag;
///
/// let mut parser = terminated(tag("abc"), tag("efg"));
///
/// assert_eq!(parser.parse("abcefg"), Ok(("", "abc")));
/// assert_eq!(parser.parse("abcefghij"), Ok(("hij", "abc")));
/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn terminated<I, O, E: ParseError<I>, F, G>(
first: F,
second: G,
) -> impl Parser<I, Output = O, Error = E>
where
F: Parser<I, Output = O, Error = E>,
G: Parser<I, Error = E>,
{
Terminated {
f: first,
g: second,
}
}
/// a
pub struct Terminated<F, G> {
f: F,
g: G,
}
impl<I, E: ParseError<I>, F: Parser<I, Error = E>, G: Parser<I, Error = E>> Parser<I>
for Terminated<F, G>
{
type Output = <F as Parser<I>>::Output;
type Error = E;
#[inline(always)]
fn process<OM: OutputMode>(&mut self, i: I) -> PResult<OM, I, Self::Output, Self::Error> {
let (i, o1) = self.f.process::<OM>(i)?;
let (i, _) = self
.g
.process::<OutputM<Check, OM::Error, OM::Incomplete>>(i)?;
Ok((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 nom::{Err, error::ErrorKind, Needed, Parser};
/// # use nom::Needed::Size;
/// use nom::sequence::separated_pair;
/// use nom::bytes::complete::tag;
///
/// let mut parser = separated_pair(tag("abc"), tag("|"), tag("efg"));
///
/// assert_eq!(parser.parse("abc|efg"), Ok(("", ("abc", "efg"))));
/// assert_eq!(parser.parse("abc|efghij"), Ok(("hij", ("abc", "efg"))));
/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn separated_pair<I, O1, O2, E: ParseError<I>, F, G, H>(
first: F,
sep: G,
second: H,
) -> impl Parser<I, Output = (O1, O2), Error = E>
where
F: Parser<I, Output = O1, Error = E>,
G: Parser<I, Error = E>,
H: Parser<I, Output = O2, Error = E>,
{
first.and(preceded(sep, second))
}
/// 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 nom::{Err, error::ErrorKind, Needed, Parser};
/// # use nom::Needed::Size;
/// use nom::sequence::delimited;
/// use nom::bytes::complete::tag;
///
/// let mut parser = delimited(tag("("), tag("abc"), tag(")"));
///
/// assert_eq!(parser.parse("(abc)"), Ok(("", "abc")));
/// assert_eq!(parser.parse("(abc)def"), Ok(("def", "abc")));
/// assert_eq!(parser.parse(""), Err(Err::Error(("", ErrorKind::Tag))));
/// assert_eq!(parser.parse("123"), Err(Err::Error(("123", ErrorKind::Tag))));
/// ```
pub fn delimited<I, O, E: ParseError<I>, F, G, H>(
first: F,
second: G,
third: H,
) -> impl Parser<I, Output = O, Error = E>
where
F: Parser<I, Error = E>,
G: Parser<I, Output = O, Error = E>,
H: Parser<I, Error = E>,
{
preceded(first, terminated(second, third))
}
/// 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 = "`Parser` is directly implemented for tuples")]
#[allow(deprecated)]
pub trait Tuple<I, O, E> {
/// Parses the input and returns a tuple of results of each parser.
fn parse_tuple(&mut self, input: I) -> IResult<I, O, E>;
}
#[allow(deprecated)]
impl<Input, Output, Error: ParseError<Input>, F: Parser<Input, Output = Output, Error = Error>>
Tuple<Input, (Output,), Error> for (F,)
{
fn parse_tuple(&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, Output = $ty, Error = Error>),+
> Tuple<Input, ( $($ty),+ ), Error> for ( $($name),+ ) {
fn parse_tuple(&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)?;
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)?;
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)?;
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_tuple(&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
/// ```rust
/// # use nom::{Err, error::ErrorKind};
/// use nom::sequence::tuple;
/// use nom::character::complete::{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_tuple(i)
}

283
vendor/nom/src/sequence/tests.rs vendored Normal file
View File

@@ -0,0 +1,283 @@
use super::*;
use crate::bytes::streaming::{tag, take};
use crate::error::{Error, ErrorKind};
use crate::internal::{Err, IResult, Needed};
use crate::number::streaming::be_u16;
#[test]
fn single_element_tuples() {
use crate::character::complete::alpha1;
use crate::{error::ErrorKind, Err};
let mut parser = (alpha1,);
assert_eq!(
crate::Parser::parse(&mut parser, "abc123def"),
Ok(("123def", ("abc",)))
);
assert_eq!(
crate::Parser::parse(&mut parser, "123def"),
Err(Err::Error(("123def", ErrorKind::Alpha)))
);
}
/*FIXME: convert code examples to new error management
use util::{add_error_pattern, error_to_list, print_error};
#[cfg(feature = "std")]
#[rustfmt::skip]
fn error_to_string<P: Clone + PartialEq>(e: &Context<P, u32>) -> &'static str {
let v: Vec<(P, ErrorKind<u32>)> = error_to_list(e);
// do it this way if you can use slice patterns
//match &v[..] {
// [ErrorKind::Custom(42), ErrorKind::Tag] => "missing `ijkl` tag",
// [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] => "missing `mnop` tag after `ijkl`",
// _ => "unrecognized error"
//}
let collected: Vec<ErrorKind<u32>> = v.iter().map(|&(_, ref e)| e.clone()).collect();
if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Tag] {
"missing `ijkl` tag"
} else if &collected[..] == [ErrorKind::Custom(42), ErrorKind::Custom(128), ErrorKind::Tag] {
"missing `mnop` tag after `ijkl`"
} else {
"unrecognized error"
}
}
// do it this way if you can use box patterns
//use $crate::lib::std::str;
//fn error_to_string(e:Err) -> String
// match e {
// NodePosition(ErrorKind::Custom(42), i1, box Position(ErrorKind::Tag, i2)) => {
// format!("missing `ijkl` tag, found '{}' instead", str::from_utf8(i2).unwrap())
// },
// NodePosition(ErrorKind::Custom(42), i1, box NodePosition(ErrorKind::Custom(128), i2, box Position(ErrorKind::Tag, i3))) => {
// format!("missing `mnop` tag after `ijkl`, found '{}' instead", str::from_utf8(i3).unwrap())
// },
// _ => "unrecognized error".to_string()
// }
//}
*/
#[test]
fn complete() {
use crate::bytes::complete::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() {
fn pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
pair(tag("abc"), tag("def")).parse(i)
}
assert_eq!(
pair_abc_def(&b"abcdefghijkl"[..]),
Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
);
assert_eq!(
pair_abc_def(&b"ab"[..]),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
pair_abc_def(&b"abcd"[..]),
Err(Err::Incomplete(Needed::new(2)))
);
assert_eq!(
pair_abc_def(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
pair_abc_def(&b"xxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
pair_abc_def(&b"abcxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn separated_pair_test() {
fn sep_pair_abc_def(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
separated_pair(tag("abc"), tag(","), tag("def")).parse(i)
}
assert_eq!(
sep_pair_abc_def(&b"abc,defghijkl"[..]),
Ok((&b"ghijkl"[..], (&b"abc"[..], &b"def"[..])))
);
assert_eq!(
sep_pair_abc_def(&b"ab"[..]),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
sep_pair_abc_def(&b"abc,d"[..]),
Err(Err::Incomplete(Needed::new(2)))
);
assert_eq!(
sep_pair_abc_def(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
sep_pair_abc_def(&b"xxx,def"[..]),
Err(Err::Error(error_position!(&b"xxx,def"[..], ErrorKind::Tag)))
);
assert_eq!(
sep_pair_abc_def(&b"abc,xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn preceded_test() {
fn preceded_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
preceded(tag("abcd"), tag("efgh")).parse(i)
}
assert_eq!(
preceded_abcd_efgh(&b"abcdefghijkl"[..]),
Ok((&b"ijkl"[..], &b"efgh"[..]))
);
assert_eq!(
preceded_abcd_efgh(&b"ab"[..]),
Err(Err::Incomplete(Needed::new(2)))
);
assert_eq!(
preceded_abcd_efgh(&b"abcde"[..]),
Err(Err::Incomplete(Needed::new(3)))
);
assert_eq!(
preceded_abcd_efgh(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
preceded_abcd_efgh(&b"xxxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
preceded_abcd_efgh(&b"abcdxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn terminated_test() {
fn terminated_abcd_efgh(i: &[u8]) -> IResult<&[u8], &[u8]> {
terminated(tag("abcd"), tag("efgh")).parse(i)
}
assert_eq!(
terminated_abcd_efgh(&b"abcdefghijkl"[..]),
Ok((&b"ijkl"[..], &b"abcd"[..]))
);
assert_eq!(
terminated_abcd_efgh(&b"ab"[..]),
Err(Err::Incomplete(Needed::new(2)))
);
assert_eq!(
terminated_abcd_efgh(&b"abcde"[..]),
Err(Err::Incomplete(Needed::new(3)))
);
assert_eq!(
terminated_abcd_efgh(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
terminated_abcd_efgh(&b"xxxxdef"[..]),
Err(Err::Error(error_position!(&b"xxxxdef"[..], ErrorKind::Tag)))
);
assert_eq!(
terminated_abcd_efgh(&b"abcdxxxx"[..]),
Err(Err::Error(error_position!(&b"xxxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn delimited_test() {
fn delimited_abc_def_ghi(i: &[u8]) -> IResult<&[u8], &[u8]> {
delimited(tag("abc"), tag("def"), tag("ghi")).parse(i)
}
assert_eq!(
delimited_abc_def_ghi(&b"abcdefghijkl"[..]),
Ok((&b"jkl"[..], &b"def"[..]))
);
assert_eq!(
delimited_abc_def_ghi(&b"ab"[..]),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcde"[..]),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcdefgh"[..]),
Err(Err::Incomplete(Needed::new(1)))
);
assert_eq!(
delimited_abc_def_ghi(&b"xxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
assert_eq!(
delimited_abc_def_ghi(&b"xxxdefghi"[..]),
Err(Err::Error(error_position!(
&b"xxxdefghi"[..],
ErrorKind::Tag
),))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcxxxghi"[..]),
Err(Err::Error(error_position!(&b"xxxghi"[..], ErrorKind::Tag)))
);
assert_eq!(
delimited_abc_def_ghi(&b"abcdefxxx"[..]),
Err(Err::Error(error_position!(&b"xxx"[..], ErrorKind::Tag)))
);
}
#[test]
fn tuple_test() {
#[allow(clippy::type_complexity)]
fn tuple_3(i: &[u8]) -> IResult<&[u8], (u16, &[u8], &[u8])> {
crate::Parser::parse(&mut (be_u16, take(3u8), tag("fg")), i)
}
assert_eq!(
tuple_3(&b"abcdefgh"[..]),
Ok((&b"h"[..], (0x6162u16, &b"cde"[..], &b"fg"[..])))
);
assert_eq!(tuple_3(&b"abcd"[..]), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(tuple_3(&b"abcde"[..]), Err(Err::Incomplete(Needed::new(2))));
assert_eq!(
tuple_3(&b"abcdejk"[..]),
Err(Err::Error(error_position!(&b"jk"[..], ErrorKind::Tag)))
);
}
#[test]
#[allow(deprecated)]
fn unit_type() {
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(("", ()))
);
}

526
vendor/nom/src/str.rs vendored Normal file
View File

@@ -0,0 +1,526 @@
#[cfg(test)]
mod test {
#[cfg(feature = "alloc")]
use crate::{branch::alt, bytes::complete::tag_no_case, combinator::recognize, multi::many};
use crate::{
bytes::complete::{is_a, is_not, tag, take, take_till, take_until},
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::streaming::tag;
const INPUT: &str = "Hello";
const TAG: &str = "Hello World!";
let res: IResult<_, _, error::Error<_>> = tag(TAG)(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::streaming::take;
const INPUT: &str = "βèƒôřèÂßÇá";
let res: IResult<_, _, (_, ErrorKind)> = take(13_usize)(INPUT);
match res {
Err(Err::Incomplete(_)) => (),
other => panic!(
"Parser `take` didn't require more input when it should have. \
Got `{:?}`.",
other
),
}
}
use crate::internal::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::streaming::take_while;
fn f(i: &str) -> IResult<&str, &str> {
take_while(is_alphabetic)(i)
}
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "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: &str) -> IResult<&str, &str> {
take_while1(is_alphabetic)(i)
}
let a = "";
let b = "abcd";
let c = "abcd123";
let d = "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(("123", b)));
assert_eq!(
f(d),
Err(Err::Error(error_position!(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::complete::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> {
is_not(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::complete::take_while;
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &str = "βèƒôřèÂßÇ";
const LEFTOVER: &str = "áƒƭèř";
fn while_s(c: char) -> bool {
matches!(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> {
is_not(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::complete::take_while1;
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
const CONSUMED: &str = "βèƒôřèÂßÇ";
const LEFTOVER: &str = "áƒƭèř";
fn while1_s(c: char) -> bool {
matches!(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::streaming::take_until;
const INPUT: &str = "βèƒôřè";
const FIND: &str = "βèƒôřèÂßÇ";
let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(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> {
is_a(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::complete::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> {
is_a(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::streaming::take_until;
const INPUT: &str = "βèƒôřèÂßÇáƒƭèř";
const FIND: &str = "Ráñδô₥";
let res: IResult<_, _, (_, ErrorKind)> = take_until(FIND)(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() {
use crate::{lib::std::vec::Vec, Parser};
let a = "aabbab";
let b = "ababcd";
fn f(i: &str) -> IResult<&str, &str> {
recognize(many::<_, _, Vec<&str>, _, _>(
1..,
alt((tag("a"), tag("b"))),
))
.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")));
}
}

1681
vendor/nom/src/traits.rs vendored Normal file

File diff suppressed because it is too large Load Diff

99
vendor/nom/tests/arithmetic.rs vendored Normal file
View File

@@ -0,0 +1,99 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::char,
character::complete::{digit1 as digit, space0 as space},
combinator::map_res,
multi::fold,
sequence::{delimited, pair},
IResult, Parser,
};
// 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(tag("("), expr, tag(")")), space).parse(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((
map_res(delimited(space, digit, space), FromStr::from_str),
parens,
))
.parse(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(
0..,
pair(alt((char('*'), char('/'))), factor),
move || init,
|acc, (op, val): (char, i64)| {
if op == '*' {
acc * val
} else {
acc / val
}
},
)
.parse(i)
}
fn expr(i: &str) -> IResult<&str, i64> {
let (i, init) = term(i)?;
fold(
0..,
pair(alt((char('+'), char('-'))), term),
move || init,
|acc, (op, val): (char, i64)| {
if op == '+' {
acc + val
} else {
acc - val
}
},
)
.parse(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)));
}

172
vendor/nom/tests/arithmetic_ast.rs vendored Normal file
View File

@@ -0,0 +1,172 @@
use std::fmt;
use std::fmt::{Debug, Display, Formatter};
use std::str::FromStr;
use nom::Parser;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{digit1 as digit, multispace0 as multispace},
combinator::{map, map_res},
multi::many,
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(tag("("), map(expr, |e| Expr::Paren(Box::new(e))), tag(")")),
multispace,
)
.parse(i)
}
fn factor(i: &str) -> IResult<&str, Expr> {
alt((
map(
map_res(delimited(multispace, digit, multispace), FromStr::from_str),
Expr::Value,
),
parens,
))
.parse(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) = many(
0..,
alt((
|i| {
let (i, mul) = preceded(tag("*"), factor).parse(i)?;
Ok((i, (Oper::Mul, mul)))
},
|i| {
let (i, div) = preceded(tag("/"), factor).parse(i)?;
Ok((i, (Oper::Div, div)))
},
)),
)
.parse(i)?;
Ok((i, fold_exprs(initial, remainder)))
}
fn expr(i: &str) -> IResult<&str, Expr> {
let (i, initial) = term(i)?;
let (i, remainder) = many(
0..,
alt((
|i| {
let (i, add) = preceded(tag("+"), term).parse(i)?;
Ok((i, (Oper::Add, add)))
},
|i| {
let (i, sub) = preceded(tag("-"), term).parse(i)?;
Ok((i, (Oper::Sub, sub)))
},
)),
)
.parse(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)")))
);
}

44
vendor/nom/tests/css.rs vendored Normal file
View File

@@ -0,0 +1,44 @@
use nom::bytes::complete::{tag, take_while_m_n};
use nom::combinator::map_res;
use nom::{IResult, Parser};
#[derive(Debug, Eq, 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_ascii_hexdigit()
}
fn hex_primary(input: &str) -> IResult<&str, u8> {
map_res(take_while_m_n(2, 2, is_hex_digit), 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,
}
))
);
}

48
vendor/nom/tests/custom_errors.rs vendored Normal file
View File

@@ -0,0 +1,48 @@
#![allow(dead_code)]
use nom::bytes::streaming::tag;
use nom::character::streaming::digit1 as digit;
use nom::combinator::verify;
use nom::error::{ErrorKind, ParseError};
#[cfg(feature = "alloc")]
use nom::multi::count;
use nom::sequence::terminated;
use nom::{IResult, Parser};
#[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<&'a str> for CustomError {
fn from_error_kind(_: &'a str, kind: ErrorKind) -> Self {
CustomError(format!("error code was: {:?}", kind))
}
fn append(_: &'a str, kind: ErrorKind, other: CustomError) -> Self {
CustomError(format!("{:?}\nerror code was: {:?}", other, kind))
}
}
fn test1(input: &str) -> IResult<&str, &str, CustomError> {
//fix_error!(input, CustomError, tag!("abcd"))
tag("abcd")(input)
}
fn test2(input: &str) -> IResult<&str, &str, CustomError> {
//terminated!(input, test1, fix_error!(CustomError, digit))
terminated(test1, digit).parse(input)
}
fn test3(input: &str) -> IResult<&str, &str, CustomError> {
verify(test1, |s: &str| s.starts_with("abcd")).parse(input)
}
#[cfg(feature = "alloc")]
fn test4(input: &str) -> IResult<&str, Vec<&str>, CustomError> {
count(test1, 4).parse(input)
}

28
vendor/nom/tests/escaped.rs vendored Normal file
View File

@@ -0,0 +1,28 @@
use nom::bytes::complete::escaped;
use nom::character::complete::digit1;
use nom::character::complete::one_of;
use nom::{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 nom::bytes::complete::{escaped_transform, tag};
escaped_transform(digit1, '\\', tag("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)))
);
}

169
vendor/nom/tests/expression_ast.rs vendored Normal file
View File

@@ -0,0 +1,169 @@
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{alphanumeric1 as alphanumeric, digit1 as digit},
combinator::{map, map_res},
multi::separated_list0,
sequence::delimited,
IResult, Parser,
};
use nom_language::precedence::{binary_op, precedence, unary_op, Assoc, Operation};
// Elements of the abstract syntax tree (ast) that represents an expression.
#[derive(Debug)]
pub enum Expr {
// A number literal.
Num(i64),
// An identifier.
Iden(String),
// Arithmetic operations. Each have a left hand side (lhs) and a right hand side (rhs).
Add(Box<Expr>, Box<Expr>),
Sub(Box<Expr>, Box<Expr>),
Mul(Box<Expr>, Box<Expr>),
Div(Box<Expr>, Box<Expr>),
// The function call operation. Left is the expression the function is called on, right is the list of parameters.
Call(Box<Expr>, Vec<Expr>),
// The ternary operator, the expressions from left to right are: The condition, the true case, the false case.
Tern(Box<Expr>, Box<Expr>, Box<Expr>),
}
// Prefix operators.
enum PrefixOp {
Identity, // +
Negate, // -
}
// Postfix operators.
enum PostfixOp {
// The function call operator. In addition to its own representation "()" it carries additional information that we need to keep here.
// Specifically the vector of expressions that make up the parameters.
Call(Vec<Expr>), // ()
}
// Binary operators.
enum BinaryOp {
Addition, // +
Subtraction, // -
Multiplication, // *
Division, // /
// The ternary operator can contain a single expression.
Ternary(Expr), // ?:
}
// Parser for function calls.
fn function_call(i: &str) -> IResult<&str, PostfixOp> {
map(
delimited(
tag("("),
// Subexpressions are evaluated by recursing back into the expression parser.
separated_list0(tag(","), expression),
tag(")"),
),
|v: Vec<Expr>| PostfixOp::Call(v),
)
.parse(i)
}
// The ternary operator is actually just a binary operator that contains another expression. So it can be
// handled similarly to the function call operator except its in a binary position and can only contain
// a single expression.
//
// For example the expression "a<b ? a : b" is handled similarly to the function call operator, the
// "?" is treated like an opening bracket and the ":" is treated like a closing bracket.
//
// For the outer expression the result looks like "a<b ?: b". Where "?:" is a single operator. The
// subexpression is contained within the operator in the same way that the function call operator
// contains subexpressions.
fn ternary_operator(i: &str) -> IResult<&str, BinaryOp> {
map(delimited(tag("?"), expression, tag(":")), |e: Expr| {
BinaryOp::Ternary(e)
})
.parse(i)
}
// The actual expression parser .
fn expression(i: &str) -> IResult<&str, Expr> {
precedence(
alt((
unary_op(2, map(tag("+"), |_| PrefixOp::Identity)),
unary_op(2, map(tag("-"), |_| PrefixOp::Negate)),
)),
// Function calls are implemented as postfix unary operators.
unary_op(1, function_call),
alt((
binary_op(
3,
Assoc::Left,
alt((
map(tag("*"), |_| BinaryOp::Multiplication),
map(tag("/"), |_| BinaryOp::Division),
)),
),
binary_op(
4,
Assoc::Left,
alt((
map(tag("+"), |_| BinaryOp::Addition),
map(tag("-"), |_| BinaryOp::Subtraction),
)),
),
// Ternary operators are just binary operators with a subexpression.
binary_op(5, Assoc::Right, ternary_operator),
)),
alt((
map_res(digit, |s: &str| match s.parse::<i64>() {
Ok(s) => Ok(Expr::Num(s)),
Err(e) => Err(e),
}),
map(alphanumeric, |s: &str| Expr::Iden(s.to_string())),
delimited(tag("("), expression, tag(")")),
)),
|op: Operation<PrefixOp, PostfixOp, BinaryOp, Expr>| -> Result<Expr, ()> {
use nom_language::precedence::Operation::*;
use BinaryOp::*;
use PostfixOp::*;
use PrefixOp::*;
match op {
// The identity operator (prefix +) is ignored.
Prefix(Identity, e) => Ok(e),
// Unary minus gets evaluated to the same representation as a multiplication with -1.
Prefix(Negate, e) => Ok(Expr::Mul(Expr::Num(-1).into(), e.into())),
// The list of parameters are taken from the operator and placed into the ast.
Postfix(e, Call(p)) => Ok(Expr::Call(e.into(), p)),
// Meaning is assigned to the expressions of the ternary operator during evaluation.
// The lhs becomes the condition, the contained expression is the true case, rhs the false case.
Binary(lhs, Ternary(e), rhs) => Ok(Expr::Tern(lhs.into(), e.into(), rhs.into())),
// Raw operators get turned into their respective ast nodes.
Binary(lhs, Multiplication, rhs) => Ok(Expr::Mul(lhs.into(), rhs.into())),
Binary(lhs, Division, rhs) => Ok(Expr::Div(lhs.into(), rhs.into())),
Binary(lhs, Addition, rhs) => Ok(Expr::Add(lhs.into(), rhs.into())),
Binary(lhs, Subtraction, rhs) => Ok(Expr::Sub(lhs.into(), rhs.into())),
}
},
)(i)
}
#[test]
fn expression_test() {
assert_eq!(
expression("-2*max(2,3)-2").map(|(i, x)| (i, format!("{:?}", x))),
Ok((
"",
String::from("Sub(Mul(Mul(Num(-1), Num(2)), Call(Iden(\"max\"), [Num(2), Num(3)])), Num(2))")
))
);
assert_eq!(
expression("a?2+c:-2*2").map(|(i, x)| (i, format!("{:?}", x))),
Ok((
"",
String::from(
"Tern(Iden(\"a\"), Add(Num(2), Iden(\"c\")), Mul(Mul(Num(-1), Num(2)), Num(2)))"
)
))
);
}

107
vendor/nom/tests/float.rs vendored Normal file
View File

@@ -0,0 +1,107 @@
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::streaming::digit1 as digit;
use nom::combinator::{map, map_res, opt, recognize};
use nom::error::ErrorKind;
use nom::number::complete::f32;
use nom::number::complete::f64;
use nom::number::Endianness;
use nom::sequence::{delimited, pair};
use nom::Err;
use nom::{IResult, Parser};
use std::str;
use std::str::FromStr;
fn unsigned_float(i: &[u8]) -> IResult<&[u8], f32> {
let float_bytes = recognize(alt((
delimited(digit, tag("."), opt(digit)),
delimited(opt(digit), tag("."), digit),
)));
let float_str = map_res(float_bytes, str::from_utf8);
map_res(float_str, FromStr::from_str).parse(i)
}
fn float(i: &[u8]) -> IResult<&[u8], f32> {
map(
pair(opt(alt((tag("+"), tag("-")))), unsigned_float),
|(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)));
}
#[test]
fn test_f32_big_endian() {
let be_f32 = |s| f32::<_, (_, ErrorKind)>(Endianness::Big)(s);
assert_eq!(
be_f32(&[0x41, 0x48, 0x00, 0x00][..]),
Ok((&[] as &[u8], 12.5))
);
}
#[test]
fn test_f32_little_endian() {
let le_f32 = |s| f32::<_, (_, ErrorKind)>(Endianness::Little)(s);
assert_eq!(
le_f32(&[0x00, 0x00, 0x48, 0x41][..]),
Ok((&[] as &[u8], 12.5))
);
}
#[test]
fn test_f64_big_endian() {
let be_f64 = |s| f64::<&[u8], (&[u8], ErrorKind)>(Endianness::Big)(s);
let input = &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00][..];
let expected = 12.5f64;
match be_f64(input) {
Ok((rest, value)) => {
assert!(rest.is_empty());
assert_eq!(value, expected);
}
Err(_) => assert!(false, "Failed to parse big-endian f64"),
}
let incomplete_input = &b"abc"[..];
assert!(matches!(be_f64(incomplete_input), Err(Err::Error(_))));
}
#[test]
fn test_f64_little_endian() {
let le_f64 = |s| f64::<&[u8], (&[u8], ErrorKind)>(Endianness::Little)(s);
let input = &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40][..];
let expected = 12.5f64;
match le_f64(input) {
Ok((rest, value)) => {
assert!(rest.is_empty());
assert_eq!(value, expected);
}
Err(_) => assert!(false, "Failed to parse little-endian f64"),
}
let incomplete_input = &b"abc"[..];
assert!(matches!(le_f64(incomplete_input), Err(Err::Error(_))));
}

40
vendor/nom/tests/fnmut.rs vendored Normal file
View File

@@ -0,0 +1,40 @@
use nom::{
bytes::complete::tag,
multi::{many, many0_count},
Parser,
};
#[test]
fn parse() {
let mut counter = 0;
let res = {
let mut parser = many::<_, (), Vec<&str>, _, _>(0.., |i| {
counter += 1;
tag("abc")(i)
});
parser.parse("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.parse("abcabcabcabc").unwrap()
};
println!("v: {:?}", v);
assert_eq!(count, 4);
assert_eq!(v.len(), 4);
}

210
vendor/nom/tests/ini.rs vendored Normal file
View File

@@ -0,0 +1,210 @@
use nom::{
bytes::complete::take_while,
character::complete::{
alphanumeric1 as alphanumeric, char, multispace0 as multispace, space0 as space,
},
combinator::{map, map_res, opt},
multi::many,
sequence::{delimited, pair, separated_pair, terminated},
IResult, Parser,
};
use std::collections::HashMap;
use std::str;
fn category(i: &[u8]) -> IResult<&[u8], &str> {
map_res(
delimited(char('['), take_while(|c| c != b']'), char(']')),
str::from_utf8,
)
.parse(i)
}
fn key_value(i: &[u8]) -> IResult<&[u8], (&str, &str)> {
let (i, key) = map_res(alphanumeric, str::from_utf8).parse(i)?;
let (i, _) = (opt(space), char('='), opt(space)).parse(i)?;
let (i, val) = map_res(take_while(|c| c != b'\n' && c != b';'), str::from_utf8).parse(i)?;
let (i, _) = opt(pair(char(';'), take_while(|c| c != b'\n'))).parse(i)?;
Ok((i, (key, val)))
}
fn keys_and_values(i: &[u8]) -> IResult<&[u8], HashMap<&str, &str>> {
many(0.., terminated(key_value, opt(multispace))).parse(i)
}
fn category_and_keys(i: &[u8]) -> IResult<&[u8], (&str, HashMap<&str, &str>)> {
let (i, category) = terminated(category, opt(multispace)).parse(i)?;
let (i, keys) = keys_and_values(i)?;
Ok((i, (category, keys)))
}
fn categories(i: &[u8]) -> IResult<&[u8], HashMap<&str, HashMap<&str, &str>>> {
map(
many(
0..,
separated_pair(
category,
opt(multispace),
map(
many(0.., terminated(key_value, opt(multispace))),
|vec: Vec<_>| vec.into_iter().collect(),
),
),
),
|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)));
}

219
vendor/nom/tests/ini_str.rs vendored Normal file
View File

@@ -0,0 +1,219 @@
use nom::{
bytes::complete::{is_a, tag, take_till, take_while},
character::complete::{alphanumeric1 as alphanumeric, char, space0 as space},
combinator::opt,
multi::many,
sequence::{delimited, pair, terminated},
IResult, Parser,
};
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> {
is_a(" \r\n")(i)
}
fn category(i: &str) -> IResult<&str, &str> {
terminated(
delimited(char('['), take_while(|c| c != ']'), char(']')),
opt(is_a(" \r\n")),
)
.parse(i)
}
fn key_value(i: &str) -> IResult<&str, (&str, &str)> {
let (i, key) = alphanumeric(i)?;
let (i, _) = (opt(space), tag("="), opt(space)).parse(i)?;
let (i, val) = take_till(is_line_ending_or_comment)(i)?;
let (i, _) = opt(space).parse(i)?;
let (i, _) = opt(pair(tag(";"), not_line_ending)).parse(i)?;
let (i, _) = opt(space_or_line_ending).parse(i)?;
Ok((i, (key, val)))
}
fn keys_and_values_aggregator(i: &str) -> IResult<&str, Vec<(&str, &str)>> {
many(0.., key_value).parse(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>)> {
pair(category, keys_and_values).parse(i)
}
#[allow(clippy::type_complexity)]
fn categories_aggregator(i: &str) -> IResult<&str, Vec<(&str, HashMap<&str, &str>)>> {
many(0.., category_and_keys).parse(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)));
}

271
vendor/nom/tests/issues.rs vendored Normal file
View File

@@ -0,0 +1,271 @@
//#![feature(trace_macros)]
#![allow(dead_code)]
#![allow(clippy::redundant_closure)]
use nom::{error::ErrorKind, Err, IResult, Needed, Parser};
#[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 nom::{
character::streaming::{digit1 as digit, space1 as space},
combinator::{complete, map, opt},
multi::many,
IResult,
};
use nom::{HexDisplay, Parser};
use std::str;
fn parse_ints(input: &[u8]) -> IResult<&[u8], Vec<i32>> {
many(0.., spaces_or_int).parse(input)
}
fn spaces_or_int(input: &[u8]) -> IResult<&[u8], i32> {
println!("{}", input.to_hex(8));
let (i, _) = opt(complete(space)).parse(input)?;
let (i, res) = map(complete(digit), |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(&b"12 34 5689a"[..]);
let expected = Ok((&b"a"[..], vec![12, 34, 5689]));
assert_eq!(subject, expected);
let subject = parse_ints(&b"12 34 5689 "[..]);
let expected = Ok((&b" "[..], vec![12, 34, 5689]));
assert_eq!(subject, expected)
}
}
#[test]
fn usize_length_bytes_issue() {
use nom::multi::length_data;
use nom::number::streaming::be_u16;
let _: IResult<&[u8], &[u8], (&[u8], ErrorKind)> = length_data(be_u16).parse(b"012346");
}
#[test]
fn take_till_issue() {
use nom::bytes::streaming::take_till;
fn nothing(i: &[u8]) -> IResult<&[u8], &[u8]> {
take_till(|_| true)(i)
}
assert_eq!(nothing(b""), Err(Err::Incomplete(Needed::new(1))));
assert_eq!(nothing(b"abc"), Ok((&b"abc"[..], &b""[..])));
}
#[test]
fn issue_655() {
use nom::character::streaming::{line_ending, not_line_ending};
fn twolines(i: &str) -> IResult<&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("foo\nbar\n"), Ok(("", ("foo", "bar"))));
assert_eq!(twolines("féo\nbar\n"), Ok(("", ("féo", "bar"))));
assert_eq!(twolines("foé\nbar\n"), Ok(("", ("foé", "bar"))));
assert_eq!(twolines("foé\r\nbar\n"), Ok(("", ("foé", "bar"))));
}
#[cfg(feature = "alloc")]
fn issue_717(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
use nom::bytes::complete::{is_not, tag};
use nom::multi::separated_list0;
separated_list0(tag(&[0x0][..]), is_not([0x0u8])).parse(i)
}
mod issue_647 {
use nom::bytes::streaming::tag;
use nom::combinator::complete;
use nom::multi::separated_list0;
use nom::Parser;
use nom::{error::Error, number::streaming::be_f64, Err, IResult};
pub type Input<'a> = &'a [u8];
#[derive(PartialEq, Debug, Clone)]
struct Data {
c: f64,
v: Vec<f64>,
}
#[allow(clippy::type_complexity)]
fn list<'a>(
input: Input<'a>,
_cs: &'_ f64,
) -> Result<(Input<'a>, Vec<f64>), Err<Error<&'a [u8]>>> {
separated_list0(complete(tag(",")), complete(be_f64)).parse(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: &[u8]) -> IResult<&[u8], &[u8]> {
use nom::bytes::streaming::take;
take(0x2000000000000000_usize)(i)
}
fn parser(i: &[u8]) -> IResult<&[u8], &[u8]> {
use nom::bits::{bits, bytes};
bits(bytes(take))(i)
}
assert_eq!(
parser(&b""[..]),
Err(Err::Failure(nom::error_position!(
&b""[..],
ErrorKind::TooLarge
)))
);
}
#[test]
fn issue_942() {
use nom::error::{ContextError, ParseError};
pub fn parser<'a, E: ParseError<&'a str> + ContextError<&'a str>>(
i: &'a str,
) -> IResult<&'a str, usize, E> {
use nom::{character::complete::char, error::context, multi::many0_count};
many0_count(context("char_a", char('a'))).parse(i)
}
assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
}
#[test]
fn issue_many_m_n_with_zeros() {
use nom::character::complete::char;
use nom::multi::many;
let mut parser = many::<_, (), Vec<char>, _, _>(0..=0, char('a'));
assert_eq!(parser.parse("aaa"), Ok(("aaa", vec!())));
}
#[test]
fn issue_1231_bits_expect_fn_closure() {
use nom::bits::{bits, complete::take};
use nom::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 nom::character::complete::one_of;
use nom::error::Error;
let mut parser = one_of::<_, _, Error<_>>(&['a', 'b', 'c'][..]);
assert_eq!(parser("aaa"), Ok(("aa", 'a')));
}
#[test]
fn issue_x_looser_fill_bounds() {
use nom::{
bytes::streaming::tag, character::streaming::digit1, error_position, multi::fill,
sequence::terminated,
};
fn fill_pair(i: &[u8]) -> IResult<&[u8], [&[u8]; 2]> {
let mut buf = [&[][..], &[][..]];
let (i, _) = fill(terminated(digit1, tag(",")), &mut buf).parse(i)?;
Ok((i, buf))
}
assert_eq!(
fill_pair(b"123,456,"),
Ok((&b""[..], [&b"123"[..], &b"456"[..]]))
);
assert_eq!(
fill_pair(b"123,456,789"),
Ok((&b"789"[..], [&b"123"[..], &b"456"[..]]))
);
assert_eq!(
fill_pair(b"123,,"),
Err(Err::Error(error_position!(&b","[..], ErrorKind::Digit)))
);
}
#[test]
fn issue_1459_clamp_capacity() {
use nom::character::complete::char;
// shouldn't panic
use nom::multi::many_m_n;
let mut parser = many_m_n::<_, (), _>(usize::MAX, usize::MAX, char('a'));
assert_eq!(parser.parse("a"), Err(nom::Err::Error(())));
// shouldn't panic
use nom::multi::count;
let mut parser = count(char('a'), usize::MAX);
assert_eq!(parser.parse("a"), Err(nom::Err::Error(())));
}
#[test]
fn issue_1617_count_parser_returning_zero_size() {
use nom::{bytes::complete::tag, combinator::map, error::Error, multi::count};
// previously, `count()` panicked if the parser had type `O = ()`
let parser = map(tag::<_, _, Error<&str>>("abc"), |_| ());
// shouldn't panic
let result = count(parser, 3)
.parse("abcabcabcdef")
.expect("parsing should succeed");
assert_eq!(result, ("def", vec![(), (), ()]));
}
#[test]
fn issue_1586_parser_iterator_impl() {
use nom::{
character::complete::{digit1, newline},
combinator::{iterator, opt},
sequence::terminated,
IResult,
};
fn parse_line(i: &str) -> IResult<&str, &str> {
terminated(digit1, opt(newline)).parse(i)
}
fn parse_input(i: &str) -> impl Iterator<Item = i32> + '_ {
iterator(i, parse_line).map(|x| x.parse::<i32>().unwrap())
}
assert_eq!(parse_input("123\n456").collect::<Vec<_>>(), vec![123, 456]);
}

244
vendor/nom/tests/json.rs vendored Normal file
View File

@@ -0,0 +1,244 @@
#![cfg(feature = "alloc")]
use nom::{
branch::alt,
bytes::complete::{tag, take},
character::complete::{anychar, char, multispace0, none_of},
combinator::{map, map_opt, map_res, value, verify},
error::ParseError,
multi::{fold, separated_list0},
number::complete::double,
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((value(false, tag("false")), value(true, tag("true")))).parse(input)
}
fn u16_hex(input: &str) -> IResult<&str, u16> {
map_res(take(4usize), |s| u16::from_str_radix(s, 16)).parse(input)
}
fn unicode_escape(input: &str) -> IResult<&str, char> {
map_opt(
alt((
// Not a surrogate
map(verify(u16_hex, |cp| !(0xD800..0xE000).contains(cp)), |cp| {
cp as u32
}),
// See https://en.wikipedia.org/wiki/UTF-16#Code_points_from_U+010000_to_U+10FFFF for details
map(
verify(
separated_pair(u16_hex, tag("\\u"), u16_hex),
|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low),
),
|(high, low)| {
let high_ten = (high as u32) - 0xD800;
let low_ten = (low as u32) - 0xDC00;
(high_ten << 10) + low_ten + 0x10000
},
),
)),
// 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((
map_res(anychar, |c| {
Ok(match c {
'"' | '\\' | '/' => c,
'b' => '\x08',
'f' => '\x0C',
'n' => '\n',
'r' => '\r',
't' => '\t',
_ => return Err(()),
})
}),
preceded(char('u'), unicode_escape),
))
.parse(input)
} else {
Ok((input, c))
}
}
fn string(input: &str) -> IResult<&str, String> {
delimited(
char('"'),
fold(0.., character, String::new, |mut string, c| {
string.push(c);
string
}),
char('"'),
)
.parse(input)
}
fn ws<'a, O, E: ParseError<&'a str>, F: Parser<&'a str, Output = O, Error = E>>(
f: F,
) -> impl Parser<&'a str, Output = O, Error = E> {
delimited(multispace0, f, multispace0)
}
fn array(input: &str) -> IResult<&str, Vec<JsonValue>> {
delimited(
char('['),
ws(separated_list0(ws(char(',')), json_value)),
char(']'),
)
.parse(input)
}
fn object(input: &str) -> IResult<&str, HashMap<String, JsonValue>> {
map(
delimited(
char('{'),
ws(separated_list0(
ws(char(',')),
separated_pair(string, ws(char(':')), json_value),
)),
char('}'),
),
|key_values| key_values.into_iter().collect(),
)
.parse(input)
}
fn json_value(input: &str) -> IResult<&str, JsonValue> {
use JsonValue::*;
alt((
value(Null, tag("null")),
map(boolean, Bool),
map(string, Str),
map(double, Num),
map(array, Array),
map(object, Object),
))
.parse(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()
)
))
);
}

322
vendor/nom/tests/mp4.rs vendored Normal file
View File

@@ -0,0 +1,322 @@
#![allow(dead_code)]
use nom::{
branch::alt,
bytes::streaming::{tag, take},
combinator::{map, map_res},
error::ErrorKind,
multi::many,
number::streaming::{be_f32, be_u16, be_u32, be_u64},
Err, IResult, Needed, Parser,
};
use std::str;
fn mp4_box(input: &[u8]) -> IResult<&[u8], &[u8]> {
match be_u32(input) {
Ok((i, offset)) => {
let sz: usize = offset as usize;
if i.len() >= sz - 4 {
Ok((&i[(sz - 4)..], &i[0..(sz - 4)]))
} else {
Err(Err::Incomplete(Needed::new(offset as usize + 4)))
}
}
Err(e) => Err(e),
}
}
#[rustfmt::skip]
#[derive(PartialEq,Eq,Debug)]
struct FileType<'a> {
major_brand: &'a str,
major_brand_version: &'a [u8],
compatible_brands: Vec<&'a str>
}
#[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
}
#[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
}
#[rustfmt::skip]
fn mvhd32(i: &[u8]) -> IResult<&[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))
}
#[rustfmt::skip]
fn mvhd64(i: &[u8]) -> IResult<&[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: &[u8]) -> IResult<&[u8], &str> {
map_res(take(4_usize), str::from_utf8).parse(input)
}
fn filetype_parser(input: &[u8]) -> IResult<&[u8], FileType<'_>> {
let (i, name) = brand_name(input)?;
let (i, version) = take(4_usize)(i)?;
let (i, brands) = many(0.., brand_name).parse(i)?;
let ft = FileType {
major_brand: name,
major_brand_version: version,
compatible_brands: brands,
};
Ok((i, ft))
}
fn mvhd_box(input: &[u8]) -> IResult<&[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(nom::error_position!(input, ErrorKind::TooLarge)))
};
println!("res: {:?}", res);
res
}
fn unknown_box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
Ok((input, MP4BoxType::Unknown))
}
fn box_type(input: &[u8]) -> IResult<&[u8], MP4BoxType> {
alt((
map(tag("ftyp"), |_| MP4BoxType::Ftyp),
map(tag("moov"), |_| MP4BoxType::Moov),
map(tag("mdat"), |_| MP4BoxType::Mdat),
map(tag("free"), |_| MP4BoxType::Free),
map(tag("skip"), |_| MP4BoxType::Skip),
map(tag("wide"), |_| MP4BoxType::Wide),
unknown_box_type,
))
.parse(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: &[u8]) -> IResult<&[u8], MP4BoxType> {
alt((
map(tag("mdra"), |_| MP4BoxType::Mdra),
map(tag("dref"), |_| MP4BoxType::Dref),
map(tag("cmov"), |_| MP4BoxType::Cmov),
map(tag("rmra"), |_| MP4BoxType::Rmra),
map(tag("iods"), |_| MP4BoxType::Iods),
map(tag("mvhd"), |_| MP4BoxType::Mvhd),
map(tag("clip"), |_| MP4BoxType::Clip),
map(tag("trak"), |_| MP4BoxType::Trak),
map(tag("udta"), |_| MP4BoxType::Udta),
))
.parse(input)
}
fn box_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> {
let (i, length) = be_u32(input)?;
let (i, tag) = box_type(i)?;
Ok((i, MP4BoxHeader { length, tag }))
}
fn moov_header(input: &[u8]) -> IResult<&[u8], MP4BoxHeader> {
let (i, length) = be_u32(input)?;
let (i, tag) = moov_type(i)?;
Ok((i, MP4BoxHeader { length, tag }))
}

31
vendor/nom/tests/multiline.rs vendored Normal file
View File

@@ -0,0 +1,31 @@
use nom::{
character::complete::{alphanumeric1 as alphanumeric, line_ending as eol},
multi::many,
sequence::terminated,
IResult, Parser,
};
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).parse(input)
}
pub fn read_lines(input: &str) -> IResult<&str, Vec<&str>> {
many(0.., read_line).parse(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);
}

141
vendor/nom/tests/overflow.rs vendored Normal file
View File

@@ -0,0 +1,141 @@
#![allow(clippy::unreadable_literal)]
#![cfg(target_pointer_width = "64")]
use nom::bytes::streaming::take;
#[cfg(feature = "alloc")]
use nom::multi::{length_data, many};
#[cfg(feature = "alloc")]
use nom::number::streaming::be_u64;
use nom::{Err, IResult, Needed, Parser};
// Parser definition
// We request a length that would trigger an overflow if computing consumed + requested
fn parser02(i: &[u8]) -> IResult<&[u8], (&[u8], &[u8])> {
(take(1_usize), take(18446744073709551615_usize)).parse(i)
}
#[test]
fn overflow_incomplete_tuple() {
assert_eq!(
parser02(&b"3"[..]),
Err(Err::Incomplete(Needed::new(18446744073709551615)))
);
}
#[test]
#[cfg(feature = "alloc")]
fn overflow_incomplete_length_bytes() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0.., length_data(be_u64)).parse(i)
}
// Trigger an overflow in length_data
assert_eq!(
multi(&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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0.., length_data(be_u64)).parse(i)
}
// Trigger an overflow in many0
assert_eq!(
multi(&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() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(1.., length_data(be_u64)).parse(i)
}
// Trigger an overflow in many1
assert_eq!(
multi(&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 nom::{bytes::complete::tag, multi::many_till};
#[allow(clippy::type_complexity)]
fn multi(i: &[u8]) -> IResult<&[u8], (Vec<&[u8]>, &[u8])> {
many_till(length_data(be_u64), tag("abc")).parse(i)
}
// Trigger an overflow in many_till
assert_eq!(
multi(&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() {
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(2..=4, length_data(be_u64)).parse(i)
}
// Trigger an overflow in many_m_n
assert_eq!(
multi(&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 nom::multi::count;
fn counter(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
count(length_data(be_u64), 2).parse(i)
}
assert_eq!(
counter(&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 nom::multi::length_count;
use nom::number::streaming::be_u8;
fn multi(i: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
length_count(be_u8, length_data(be_u64)).parse(i)
}
assert_eq!(
multi(&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: &[u8]) -> IResult<&[u8], Vec<&[u8]>> {
many(0.., length_data(be_u64)).parse(i)
}
assert_eq!(
multi(&b"\x00\x00\x00\x00\x00\x00\x00\x01\xaa\xff\xff\xff\xff\xff\xff\xff\xff"[..]),
Err(Err::Incomplete(Needed::new(18446744073709551615)))
);
}

33
vendor/nom/tests/reborrow_fold.rs vendored Normal file
View File

@@ -0,0 +1,33 @@
#![allow(dead_code)]
// #![allow(unused_variables)]
use std::str;
use nom::bytes::complete::is_not;
use nom::character::complete::char;
use nom::combinator::{map, map_res};
use nom::multi::fold;
use nom::sequence::delimited;
use nom::{IResult, Parser};
fn atom(_tomb: &mut ()) -> impl for<'a> FnMut(&'a [u8]) -> IResult<&'a [u8], String> {
move |input| {
map(
map_res(is_not(" \t\r\n"), str::from_utf8),
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: &mut ()) -> IResult<&'a [u8], String> {
delimited(
char('('),
fold(0.., atom(tomb), String::new, |acc: String, next: String| {
acc + next.as_str()
}),
char(')'),
)
.parse(i)
}