summaryrefslogtreecommitdiffstats
path: root/vendor/winnow
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-19 09:26:03 +0000
commit9918693037dce8aa4bb6f08741b6812923486c18 (patch)
tree21d2b40bec7e6a7ea664acee056eb3d08e15a1cf /vendor/winnow
parentReleasing progress-linux version 1.75.0+dfsg1-5~progress7.99u1. (diff)
downloadrustc-9918693037dce8aa4bb6f08741b6812923486c18.tar.xz
rustc-9918693037dce8aa4bb6f08741b6812923486c18.zip
Merging upstream version 1.76.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/winnow')
-rw-r--r--vendor/winnow/.cargo-checksum.json2
-rw-r--r--vendor/winnow/Cargo.lock9
-rw-r--r--vendor/winnow/Cargo.toml10
-rw-r--r--vendor/winnow/README.md2
-rw-r--r--vendor/winnow/benches/contains_token.rs32
-rw-r--r--vendor/winnow/benches/find_slice.rs50
-rw-r--r--vendor/winnow/examples/arithmetic/bench.rs26
-rw-r--r--vendor/winnow/examples/arithmetic/main.rs47
-rw-r--r--vendor/winnow/examples/arithmetic/parser.rs81
-rw-r--r--vendor/winnow/examples/arithmetic/parser_ast.rs216
-rw-r--r--vendor/winnow/examples/arithmetic/parser_lexer.rs297
-rw-r--r--vendor/winnow/examples/http/parser.rs2
-rw-r--r--vendor/winnow/examples/http/parser_streaming.rs2
-rw-r--r--vendor/winnow/examples/ini/parser_str.rs4
-rw-r--r--vendor/winnow/examples/json/parser.rs14
-rw-r--r--vendor/winnow/examples/json/parser_dispatch.rs14
-rw-r--r--vendor/winnow/examples/json/parser_partial.rs14
-rw-r--r--vendor/winnow/examples/json_iterator.rs6
-rw-r--r--vendor/winnow/examples/ndjson/parser.rs14
-rw-r--r--vendor/winnow/examples/s_expression/parser.rs2
-rw-r--r--vendor/winnow/examples/string/parser.rs8
-rw-r--r--vendor/winnow/src/_topic/arithmetic.rs6
-rw-r--r--vendor/winnow/src/_topic/mod.rs3
-rw-r--r--vendor/winnow/src/_topic/partial.rs6
-rw-r--r--vendor/winnow/src/_topic/performance.rs6
-rw-r--r--vendor/winnow/src/_topic/stream.rs32
-rw-r--r--vendor/winnow/src/_topic/why.rs10
-rw-r--r--vendor/winnow/src/_tutorial/chapter_0.rs2
-rw-r--r--vendor/winnow/src/_tutorial/chapter_1.rs12
-rw-r--r--vendor/winnow/src/_tutorial/chapter_2.rs10
-rw-r--r--vendor/winnow/src/_tutorial/chapter_3.rs6
-rw-r--r--vendor/winnow/src/_tutorial/chapter_4.rs3
-rw-r--r--vendor/winnow/src/_tutorial/chapter_5.rs16
-rw-r--r--vendor/winnow/src/_tutorial/chapter_6.rs4
-rw-r--r--vendor/winnow/src/_tutorial/mod.rs1
-rw-r--r--vendor/winnow/src/ascii/mod.rs41
-rw-r--r--vendor/winnow/src/binary/bits/mod.rs2
-rw-r--r--vendor/winnow/src/combinator/core.rs2
-rw-r--r--vendor/winnow/src/combinator/mod.rs95
-rw-r--r--vendor/winnow/src/combinator/multi.rs590
-rw-r--r--vendor/winnow/src/combinator/parser.rs2
-rw-r--r--vendor/winnow/src/combinator/tests.rs53
-rw-r--r--vendor/winnow/src/error.rs66
-rw-r--r--vendor/winnow/src/lib.rs2
-rw-r--r--vendor/winnow/src/parser.rs108
-rw-r--r--vendor/winnow/src/stream/impls.rs8
-rw-r--r--vendor/winnow/src/stream/mod.rs529
-rw-r--r--vendor/winnow/src/stream/tests.rs32
-rw-r--r--vendor/winnow/src/token/mod.rs148
-rw-r--r--vendor/winnow/src/token/tests.rs15
-rw-r--r--vendor/winnow/src/trace/mod.rs5
51 files changed, 2106 insertions, 561 deletions
diff --git a/vendor/winnow/.cargo-checksum.json b/vendor/winnow/.cargo-checksum.json
index 9dc595f45..bd4af0262 100644
--- a/vendor/winnow/.cargo-checksum.json
+++ b/vendor/winnow/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.lock":"fbba351eeeef7391bab2512e3078a5dfe5be94742eef876eacbbd70d3b901769","Cargo.toml":"77ca17f5cffc130edd52c3894d0f23947c3b08e6bec4b1a9ab8b0b7d6973b979","LICENSE-MIT":"cb5aedb296c5246d1f22e9099f925a65146f9f0d6b4eebba97fd27a6cdbbab2d","README.md":"b66d0e430d8a5f5391f1f51b2d7959c3881fca59fdf76a075129591b396c1c62","benches/contains_token.rs":"cd1ce72b8e1c92f8bd9539b1933e3337fedbc2e22f98959adb18b1a215f3cd70","benches/iter.rs":"bede3f156b87ffb8b901b092bcbb2717b7adf9a461a2fecdfad86025aad3e587","benches/number.rs":"f4b54895ed523c462ce327a5205b0b99591eb7056fe9de9abe3f809eff287386","examples/arithmetic/bench.rs":"ff0220a18c6004cca8b56583072fbb7290f022cc069f2d24be132f261ac55f18","examples/arithmetic/main.rs":"aab0793c96add893bbaacea331bc05de8f6b59e47c5bccca67bfd30e924cd790","examples/arithmetic/parser.rs":"ddb86007e2c6be97acd08788f30a13083e0615bf5314a625d74e6a72d69da43f","examples/arithmetic/parser_ast.rs":"748d238fac2fe83b6ab9dfad5d6a2bb5f1863f6c2a2757e17271053291da3990","examples/css/main.rs":"3127f259af57aaaa8363bfa6e0a64c9719173cc1dcc5a293771a2c8a7f31982e","examples/css/parser.rs":"7175cfdc36d228b3130f0cfc8565063554167998045a07f62644bbd90c2772b2","examples/custom_error.rs":"5ebf88007ed2ce998fdb16cd4326b1573e83f0c420e2f6561c10b6dd8ebf69a2","examples/http/bench.rs":"b6d3e9e5833b53ac58f8336617cc42a2f3f4c5e5ce88feb23184fcdbb36843f6","examples/http/main.rs":"95d3c73953cd76ea462d886ade2ab34e987239bae3abb0349c434fb01b80467d","examples/http/parser.rs":"55a5894ab8e211a17f2eb9db72503579704d85376a6631a741eede2bfcd4bdbd","examples/http/parser_streaming.rs":"1300486af4dfcfe9b1b396436ef58927663624b0184b9c70a636e639c09c4552","examples/ini/bench.rs":"c8fd1aed25ce2878c0f440d765779d7877e83ca202cf071f8f4c57566596bf89","examples/ini/main.rs":"d771aa8aae11e53f4f5453ac39e10ae3a1de210408dfd31ca7d1ce58d14c3fb9","examples/ini/parser.rs":"c554286e8f2077f999d607902e7a63ce3945939118bccf830a68b22bfe24c775","examples/ini/parser_str.rs":"8f5bce75153ae98d5e76f884fec4746a73c44c4fb9a3c4c2efdf77913baf3bec","examples/iterator.rs":"21fb0480749116407689162f0d3e9957e3e7b6863f9dda08ee01af675409b06e","examples/json/bench.rs":"9479248ccef46e0741e0eebf9fb3b307b343ba665925481adc4554d8e65f9d39","examples/json/json.rs":"48cf6c114098113c9767bebe430682f55f7c1a227e6486131ca58c00770711f2","examples/json/main.rs":"7ab1f6eefd4eb61153cf05991e593fd10827ac09f66af45d3019f94c39c5b84e","examples/json/parser.rs":"6a49d300a323bfab9deb9221c92c44ea4b5738788077f712cc8d12d082583127","examples/json/parser_dispatch.rs":"370ae21b2c1f9fe848a8ca0d9f821109ab0995c78575d01a0abe32715429eb41","examples/json/parser_partial.rs":"4f944c45223161fcbb6025fb8e71306e549ab39bf62d26bcbf85c61d124b18e2","examples/json_iterator.rs":"070f7ade176b04b70b026b1915601a52fbb462ec0cc7b9d6684d1e0a04c2d031","examples/ndjson/example.ndjson":"c44c130731008bca76181348d40f46b183577949b5a4d229e0e1a56e1e405e5d","examples/ndjson/main.rs":"dc92dd5d76b5d43edf947b6455d552f0212e46d59c926d95f97f5d159b14e361","examples/ndjson/parser.rs":"e10c0940da97def0a9c628916433cb867ea1a8cc6ecc0dff58bc98d13ec47ccd","examples/s_expression/main.rs":"5a2de0b477807c7d6ab8bb72579f03692e8f5ea89d5b6f3a8342cfdbe4d84b96","examples/s_expression/parser.rs":"a98fa7a2230d3c2aa77206bed66d7c4167707464bdb790f2ab25d803813589e3","examples/string/main.rs":"e6362f957d532d41bcd96476e55ac4c253eb04fa25ee88b48d872661a46a5bb5","examples/string/parser.rs":"111c8b67d9e51eef8b980f4efb9264d76598cb09e820b74f9ea8dfec5176abb4","src/_topic/arithmetic.rs":"94920a9572ed6deac58abb337a7be57b93cf37440f0cc3eaf514cb9ad9b9e077","src/_topic/error.rs":"69c972c609a91e078ddb4e01da8f3d35f29d8dbcb077614e9b156c033c9f5dd7","src/_topic/fromstr.rs":"01abdab296cd30067ae5f508b2b21ebe97c0571ace58e7817876eb2110e8d23a","src/_topic/http.rs":"19b9ec78a031fe5b3086fb34d04d6c13308c50b6e7bfe30229f5b682d3605ac8","src/_topic/ini.rs":"b2b04d48eac3158f4e26ee9dce748a699d02acaa0b12ae8d54421cad0fdc4ad7","src/_topic/json.rs":"bde39ee6b1c5fab2d2da480822b737674aed877f92c3f748d6932bec313b5661","src/_topic/language.rs":"437814054d4a0a19ffccd74ff9189677e6a8e9df45dc395861fc75d5bd23719b","src/_topic/mod.rs":"7e871bc9f8838ab2b7bf35db6800e17a19bf8132675e305087cb6dd1e841cbec","src/_topic/partial.rs":"5b795d1a8f2fa5a378c4974f9862acd479392a645b93c5dc4da2c4b1384c0d0d","src/_topic/performance.rs":"1f2f56fb70a70d5f8890deea25fa6a5df9a97d489380db0e0cf84eaa1b7806df","src/_topic/s_expression.rs":"6ca9a22a5c3344e120421f2ab353a1e822777aebfa1faa0acffc9632f7668cb2","src/_topic/stream.rs":"5ae58b8a53e7ffe60df4fbe862fbc2319f5c36f798767b7b650dd6441332042b","src/_topic/why.rs":"7805a9f27b64d253982b32ecf16963f2acc092f507da929766db5e4a554feaed","src/_tutorial/chapter_0.rs":"a86301c783ff7f3f5d7a870963fc9557347c1e1819b5acae04cc70510ada4d0d","src/_tutorial/chapter_1.rs":"c42f66bb480862dd5e46b5a992529ec354befd54aa167c24291a2e63d4f20631","src/_tutorial/chapter_2.rs":"402335520bc1303de310a0f60729816f1899af9613457676b723ad1940dfe9c3","src/_tutorial/chapter_3.rs":"8e9eca4a742c86da8edc084b873ef915acd5f97ee32e13ea1eaa0b93c90734ad","src/_tutorial/chapter_4.rs":"15d19c9ebb53f7a4ad7effb49a086be60b0bbe210d3aa65d161edf83c13d3608","src/_tutorial/chapter_5.rs":"bdf668e5121b5c8d7c4658d5d8360781cc93279f451a5e00b6c3d0cf8c3634a1","src/_tutorial/chapter_6.rs":"0ade4cfdab6f01e2f7c20be273ce6379728a2f4ee6f855fb29f8c2efc391d030","src/_tutorial/chapter_7.rs":"0767623ca13b97ab32df54c3d0b1d58c55b97d7aad25259687bdc59bf62cfef4","src/_tutorial/mod.rs":"69dc414df5be09f176c36ecee72605203c3aaa1bde77b55af012d9fd8c57a789","src/ascii/mod.rs":"9891ba592aa3a1ca188a2da3e1fb0bccf85b670f5a0a2cd154b546fa12e4a1e7","src/ascii/tests.rs":"cbd0d7db9eb795762de305fde5204ee70396cb384ac7826bde91bf9c69cbec74","src/binary/bits/mod.rs":"104b9f4435369c83f3def181eeb2a4bd8795a49738453013732ed49aebf3076a","src/binary/bits/tests.rs":"1ce1707a8ab2300d601f67fb3cb9c4b8ba7528564477e65ff25d8542c3e0f6e7","src/binary/mod.rs":"6447ddb0d1f87ee653c4cc629fbc60714228d236fb6dad68ff0994df2c239d84","src/binary/tests.rs":"bc8c383d345e9d63f09d3edb6e4ff76b8e6d422f2359f7e7b2b29c56082d3b93","src/combinator/branch.rs":"49714533de587e11a9a3dbd7a8d86a554b76681bf0911ea6f8f98e9181607995","src/combinator/core.rs":"632201f917e732b80c8dbe88c43f33e868df5261449b22b18e60424a795e0f45","src/combinator/mod.rs":"a3eb82c52c4b707a84d60c6d9da85da76b3a9004b1d5f0e0029844d45143322c","src/combinator/multi.rs":"7a7acdbb667617627c1af7fb601bf1ec48df589e89744023ea32ce0eff1e4eaa","src/combinator/parser.rs":"1ee72502cf05c476aa77ef20744abe2bf1ea9d04504cf6d13a3f9f91d2c78cf5","src/combinator/sequence.rs":"f913aec935bbdb1fd496e76dbc14d697d8e7e48c163856e062c5ded2f3170905","src/combinator/tests.rs":"b404f2047e717e073a8a45cf33db996ef69df8759ab14e9aa8d32613d0cd3beb","src/error.rs":"2ab9bdbca725625c6d2dad0b277127cd88e16c9137c2f8a3cc6e09f273fba04e","src/lib.rs":"3436ea3a7ca6375c49a62c674ad348b3601eb5d969b7376aeb19d395a24d2c63","src/macros.rs":"401a510f19ee4acc180c8dc1fd3c0a0c0e7bc50d69ffc4a925439e88f3299547","src/parser.rs":"1299d12c3facbbfb0336c53412b5c14d1dca6708e83ba847383b969bad6a24d9","src/stream/impls.rs":"99f69fdb8c32ad1f759bcc414ebfd2428eac5997887ce2b6946a2fcfcd174082","src/stream/mod.rs":"ff2cd9b3e145c029f3a1d348d0559c747516584301624e3d18b4b4790bcd8359","src/stream/tests.rs":"e351ea68ba3fbeaeeac147ac7c186d8ee3a17ff09c78c016dd294eb0719d54f2","src/token/mod.rs":"99689541315f795e57983566aab3c641ccf711492a2e397af15213a63b6cb702","src/token/tests.rs":"65819246fac1c10abe4abeeb79e30fb03b06a9a5ef6fde3edec003ad1f034f78","src/trace/internals.rs":"3480e946ba22390ac84046487728fd89d78cb3bc5547305162ed925e2437802f","src/trace/mod.rs":"7614deec7a51082464ae6ff99302bf9d8d1b11d4c6d509254cae045a913c1571"},"package":"7c2e3184b9c4e92ad5167ca73039d0c42476302ab603e2fec4487511f38ccefc"} \ No newline at end of file
+{"files":{"Cargo.lock":"dd16728417bc64167c83aecb80ad25367fd7cdb8d635d6bbda2f4f569fe344d6","Cargo.toml":"21e2eac70534f919d2dd269e8c0a6860b7a53ac1670edf0256890bfb95158645","LICENSE-MIT":"cb5aedb296c5246d1f22e9099f925a65146f9f0d6b4eebba97fd27a6cdbbab2d","README.md":"0b7e4cad5ef0cbb47dc1c1c34ff3b5d090aaba2cc3b3c5401539e5c4a22b7938","benches/contains_token.rs":"20e765de27f0ad9bf549e250bdb67d73714d23bc10bb67be240a258dcf8b6ed7","benches/find_slice.rs":"c140d235fb94997b365e5e66c6caf77ef8b782f80cfce580ef68aa8e300fdb70","benches/iter.rs":"bede3f156b87ffb8b901b092bcbb2717b7adf9a461a2fecdfad86025aad3e587","benches/number.rs":"f4b54895ed523c462ce327a5205b0b99591eb7056fe9de9abe3f809eff287386","examples/arithmetic/bench.rs":"a162e4f91ce2ed19b5b53f79d77c92eb52278f0788da9af8fee3ee62cebfe0a9","examples/arithmetic/main.rs":"b7f2090beefa76ca324d23bc62e06ef97df8c7d02934998f4ddce1ac45e0b852","examples/arithmetic/parser.rs":"c219b2ff9a4f9bb4db97899203294765e72024fe4324b3d46d0b464258757da6","examples/arithmetic/parser_ast.rs":"5897edec836e91d0fcb6764894d0cb67898990a0c3cbde3ffc1fc43777127fa6","examples/arithmetic/parser_lexer.rs":"a0f79926cc06c9581ca73071355d6d44a070e40773a0c92271edcd5ed80bb93f","examples/css/main.rs":"3127f259af57aaaa8363bfa6e0a64c9719173cc1dcc5a293771a2c8a7f31982e","examples/css/parser.rs":"7175cfdc36d228b3130f0cfc8565063554167998045a07f62644bbd90c2772b2","examples/custom_error.rs":"5ebf88007ed2ce998fdb16cd4326b1573e83f0c420e2f6561c10b6dd8ebf69a2","examples/http/bench.rs":"b6d3e9e5833b53ac58f8336617cc42a2f3f4c5e5ce88feb23184fcdbb36843f6","examples/http/main.rs":"95d3c73953cd76ea462d886ade2ab34e987239bae3abb0349c434fb01b80467d","examples/http/parser.rs":"23682838bdce549beddf9c8c869a9f1b7531d651198989b03df68058b1f75bfc","examples/http/parser_streaming.rs":"56e7088ed5a32ef9b6ff114f67da33479edb3a5b673f88f3b851d7f504cbc6e5","examples/ini/bench.rs":"c8fd1aed25ce2878c0f440d765779d7877e83ca202cf071f8f4c57566596bf89","examples/ini/main.rs":"d771aa8aae11e53f4f5453ac39e10ae3a1de210408dfd31ca7d1ce58d14c3fb9","examples/ini/parser.rs":"c554286e8f2077f999d607902e7a63ce3945939118bccf830a68b22bfe24c775","examples/ini/parser_str.rs":"5eb333cd192aff09138fa1578628f76c19a9b48375c9f13860deb34cf1a6df37","examples/iterator.rs":"21fb0480749116407689162f0d3e9957e3e7b6863f9dda08ee01af675409b06e","examples/json/bench.rs":"9479248ccef46e0741e0eebf9fb3b307b343ba665925481adc4554d8e65f9d39","examples/json/json.rs":"48cf6c114098113c9767bebe430682f55f7c1a227e6486131ca58c00770711f2","examples/json/main.rs":"7ab1f6eefd4eb61153cf05991e593fd10827ac09f66af45d3019f94c39c5b84e","examples/json/parser.rs":"747e6d206cf72a471c3fef7a7a6df102c9b907e9b642057ba010b1a805eaa011","examples/json/parser_dispatch.rs":"e430b5fdfa8c9f4a2312657e8f4451101b5492019404bcbe0950c0c6007f959b","examples/json/parser_partial.rs":"a22a908248082f61b6d30c6a7a0d9d31147ce15cc850a9f117657b9e59f16260","examples/json_iterator.rs":"2a8a842b43fdea12a6b5c4927cede23cbd0eb96bb1cbf42a794103fc9be9ff3a","examples/ndjson/example.ndjson":"c44c130731008bca76181348d40f46b183577949b5a4d229e0e1a56e1e405e5d","examples/ndjson/main.rs":"dc92dd5d76b5d43edf947b6455d552f0212e46d59c926d95f97f5d159b14e361","examples/ndjson/parser.rs":"7699f08c0dc5d8e3a4ef488d5f9eb8de996046669ec988bd9dc7aa322168e57d","examples/s_expression/main.rs":"5a2de0b477807c7d6ab8bb72579f03692e8f5ea89d5b6f3a8342cfdbe4d84b96","examples/s_expression/parser.rs":"2a468bf61e4aed9aa5c556fb19c479060d121f60671865324675ab9fd92f0ddd","examples/string/main.rs":"e6362f957d532d41bcd96476e55ac4c253eb04fa25ee88b48d872661a46a5bb5","examples/string/parser.rs":"5a08324b3054fb4cc3a29164e91bdf4811f9f85deb38418603c22f4931a540b5","src/_topic/arithmetic.rs":"28d61dd492b308209d534c54813ea48ac1862a39196527042180de7718f915d0","src/_topic/error.rs":"69c972c609a91e078ddb4e01da8f3d35f29d8dbcb077614e9b156c033c9f5dd7","src/_topic/fromstr.rs":"01abdab296cd30067ae5f508b2b21ebe97c0571ace58e7817876eb2110e8d23a","src/_topic/http.rs":"19b9ec78a031fe5b3086fb34d04d6c13308c50b6e7bfe30229f5b682d3605ac8","src/_topic/ini.rs":"b2b04d48eac3158f4e26ee9dce748a699d02acaa0b12ae8d54421cad0fdc4ad7","src/_topic/json.rs":"bde39ee6b1c5fab2d2da480822b737674aed877f92c3f748d6932bec313b5661","src/_topic/language.rs":"437814054d4a0a19ffccd74ff9189677e6a8e9df45dc395861fc75d5bd23719b","src/_topic/mod.rs":"00e7cd3580584270652890193653ded7791211a4568469260ce0214d68de35fd","src/_topic/partial.rs":"9edb967fcda9392cb417370bd34cd946f5eceb5f02f0812ba769c2782e7a9ced","src/_topic/performance.rs":"115b636769c307bd80ecc5b89ffad47877352bc93ef47bf664093d3d7a2562cc","src/_topic/s_expression.rs":"6ca9a22a5c3344e120421f2ab353a1e822777aebfa1faa0acffc9632f7668cb2","src/_topic/stream.rs":"acc1e8942e27fec3911c562934be6bf9b096d436593af50a4418d9e0fe607535","src/_topic/why.rs":"7c328fcdce718ba342052a652440105f7191416005a7ed23925297db4edd141b","src/_tutorial/chapter_0.rs":"c0512cb9857edb9df0ac1d327fccb1e950019b9a417959c802714039038b8bce","src/_tutorial/chapter_1.rs":"743847b36faab89235f7e4d36076b5090d1dff7c0f5f38f9c3387aaff80bbec2","src/_tutorial/chapter_2.rs":"3671bfd14e7a9c6c630daac8bc2c8128938fd0f830a5524c33a800d06d4cd205","src/_tutorial/chapter_3.rs":"268d0fa4d799480653cc025b7c4af206345f9d45fe014776dbcfbb85bf5b893a","src/_tutorial/chapter_4.rs":"4390d7ec2a67a726bd8df7f62ebd3fc26df926e79c014b8a2e623ec3e4c1ca25","src/_tutorial/chapter_5.rs":"25656769ea285f9d6d3780294a24491b27918cecd754b430220b56ac2047a10c","src/_tutorial/chapter_6.rs":"51fae6d7479288f518d04d43b3e987aa0f26f83ff0620ca4bdcfe7ec92e2e0cb","src/_tutorial/chapter_7.rs":"0767623ca13b97ab32df54c3d0b1d58c55b97d7aad25259687bdc59bf62cfef4","src/_tutorial/mod.rs":"afbc50be8c274db7b3963b74865c527e85f8b90b83e18c32edc1baca952c0957","src/ascii/mod.rs":"673e2b5463c4c84fec23aea0e8f5380b0abc4e08893ae1d1fdd5bd84e5cbc58d","src/ascii/tests.rs":"cbd0d7db9eb795762de305fde5204ee70396cb384ac7826bde91bf9c69cbec74","src/binary/bits/mod.rs":"5f64c2badc4de4e336e6fcdf6bf0c051b1b1d1acce1ca8da8f841b3ca7681762","src/binary/bits/tests.rs":"1ce1707a8ab2300d601f67fb3cb9c4b8ba7528564477e65ff25d8542c3e0f6e7","src/binary/mod.rs":"6447ddb0d1f87ee653c4cc629fbc60714228d236fb6dad68ff0994df2c239d84","src/binary/tests.rs":"bc8c383d345e9d63f09d3edb6e4ff76b8e6d422f2359f7e7b2b29c56082d3b93","src/combinator/branch.rs":"49714533de587e11a9a3dbd7a8d86a554b76681bf0911ea6f8f98e9181607995","src/combinator/core.rs":"7fe951f5b5084338ea4f8387b344c297b96a177249ceea7ed65d1ef17ba27bb5","src/combinator/mod.rs":"640334814dbdca048178c50e8fe9a9984c4a025c0d371dfd5ed42dac9f959d6d","src/combinator/multi.rs":"5e7575fc085b91afbe610dbc90c46538a4620a67c0bc51c8a88f4de441fc3dab","src/combinator/parser.rs":"79889d727ea81cb276845df08d3ae80aea0915c6941dd961f33509da995a7c3e","src/combinator/sequence.rs":"f913aec935bbdb1fd496e76dbc14d697d8e7e48c163856e062c5ded2f3170905","src/combinator/tests.rs":"b13fd6e0516d73d4ec2733813dea763d1599a19c5ce2f7309b7e5e3d4acabc0b","src/error.rs":"64e43d63db6c5a5c64270b61d94719199c9ea9d329a13042b01a1bf35b1fa2e8","src/lib.rs":"472b0ffc01ba9551b7e46e8eb93300c225f0ad8a58f70b9dce54b029a7bbf79d","src/macros.rs":"401a510f19ee4acc180c8dc1fd3c0a0c0e7bc50d69ffc4a925439e88f3299547","src/parser.rs":"71c9ddca1fa704189cb5c0f68b5bede0dfd77c985b9fa61e9efa63a70c57aa3b","src/stream/impls.rs":"139025ed7c350c86e14b3a23019b1e5569cfee98c5f3e07d5a7dc69f411a8730","src/stream/mod.rs":"a787a62cf7a1ac2f6bdf6197c58c8ce3def4757fd5b6e0508f623fc24db7532d","src/stream/tests.rs":"48b73121ca32e6357f080e66915b7697028d0c807e3908df4fde9758f9f679e5","src/token/mod.rs":"0509c5a93870f20957d0be31a45021438b17aa25004eaf1db9898028c536edcd","src/token/tests.rs":"e6505392a729962bcda559bc21176eb5d77811f63169203eae03e36df71683ed","src/trace/internals.rs":"3480e946ba22390ac84046487728fd89d78cb3bc5547305162ed925e2437802f","src/trace/mod.rs":"767e5ac4dd698f17a61494eea288cf216f9920919a9b8e9b2547b3fe6cc470db"},"package":"b7e87b8dfbe3baffbe687eef2e164e32286eff31a5ee16463ce03d991643ec94"} \ No newline at end of file
diff --git a/vendor/winnow/Cargo.lock b/vendor/winnow/Cargo.lock
index 2e2dfe5de..25cdb72ee 100644
--- a/vendor/winnow/Cargo.lock
+++ b/vendor/winnow/Cargo.lock
@@ -863,6 +863,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
+[[package]]
name = "rustix"
version = "0.37.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1391,7 +1397,7 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
-version = "0.5.15"
+version = "0.5.25"
dependencies = [
"anstream",
"anstyle",
@@ -1403,6 +1409,7 @@ dependencies = [
"lexopt",
"memchr",
"proptest",
+ "rustc-hash",
"snapbox",
"term-transcript",
"terminal_size",
diff --git a/vendor/winnow/Cargo.toml b/vendor/winnow/Cargo.toml
index a44df6680..e0ef24f69 100644
--- a/vendor/winnow/Cargo.toml
+++ b/vendor/winnow/Cargo.toml
@@ -13,7 +13,7 @@
edition = "2021"
rust-version = "1.64.0"
name = "winnow"
-version = "0.5.15"
+version = "0.5.25"
include = [
"build.rs",
"src/**/*",
@@ -142,12 +142,17 @@ required-features = ["alloc"]
name = "arithmetic"
path = "examples/arithmetic/bench.rs"
harness = false
+required-features = ["alloc"]
[[bench]]
name = "contains_token"
harness = false
[[bench]]
+name = "find_slice"
+harness = false
+
+[[bench]]
name = "iter"
harness = false
@@ -212,6 +217,9 @@ version = "0.3.0"
[dev-dependencies.proptest]
version = "1.2.0"
+[dev-dependencies.rustc-hash]
+version = "1.1.0"
+
[dev-dependencies.snapbox]
version = "0.4.11"
features = ["examples"]
diff --git a/vendor/winnow/README.md b/vendor/winnow/README.md
index 507df4e42..5530657c9 100644
--- a/vendor/winnow/README.md
+++ b/vendor/winnow/README.md
@@ -19,7 +19,7 @@ For more details, see:
# Contributors
winnow is the fruit of the work of many contributors over the years, many
-thanks for your help! In particular, thanks to [Geal](https://github.com/Geal)
+thanks for your help! In particular, thanks to [Geal](https://github.com/Geal)
for the original [`nom` crate](https://crates.io/crates/nom).
<a href="https://github.com/winnow-rs/winnow/graphs/contributors">
diff --git a/vendor/winnow/benches/contains_token.rs b/vendor/winnow/benches/contains_token.rs
index 2980ce6c8..675b08e58 100644
--- a/vendor/winnow/benches/contains_token.rs
+++ b/vendor/winnow/benches/contains_token.rs
@@ -3,7 +3,7 @@ use criterion::black_box;
use winnow::combinator::alt;
use winnow::combinator::repeat;
use winnow::prelude::*;
-use winnow::token::take_till1;
+use winnow::token::take_till;
use winnow::token::take_while;
fn contains_token(c: &mut criterion::Criterion) {
@@ -52,17 +52,29 @@ fn contains_token(c: &mut criterion::Criterion) {
fn parser_slice(input: &mut &str) -> PResult<usize> {
let contains = &['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'][..];
- repeat(0.., alt((take_while(1.., contains), take_till1(contains)))).parse_next(input)
+ repeat(
+ 0..,
+ alt((take_while(1.., contains), take_till(1.., contains))),
+ )
+ .parse_next(input)
}
fn parser_array(input: &mut &str) -> PResult<usize> {
let contains = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
- repeat(0.., alt((take_while(1.., contains), take_till1(contains)))).parse_next(input)
+ repeat(
+ 0..,
+ alt((take_while(1.., contains), take_till(1.., contains))),
+ )
+ .parse_next(input)
}
fn parser_tuple(input: &mut &str) -> PResult<usize> {
let contains = ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9');
- repeat(0.., alt((take_while(1.., contains), take_till1(contains)))).parse_next(input)
+ repeat(
+ 0..,
+ alt((take_while(1.., contains), take_till(1.., contains))),
+ )
+ .parse_next(input)
}
fn parser_closure_or(input: &mut &str) -> PResult<usize> {
@@ -78,12 +90,20 @@ fn parser_closure_or(input: &mut &str) -> PResult<usize> {
|| c == '8'
|| c == '9'
};
- repeat(0.., alt((take_while(1.., contains), take_till1(contains)))).parse_next(input)
+ repeat(
+ 0..,
+ alt((take_while(1.., contains), take_till(1.., contains))),
+ )
+ .parse_next(input)
}
fn parser_closure_matches(input: &mut &str) -> PResult<usize> {
let contains = |c: char| matches!(c, '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9');
- repeat(0.., alt((take_while(1.., contains), take_till1(contains)))).parse_next(input)
+ repeat(
+ 0..,
+ alt((take_while(1.., contains), take_till(1.., contains))),
+ )
+ .parse_next(input)
}
const CONTIGUOUS: &str = "012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789";
diff --git a/vendor/winnow/benches/find_slice.rs b/vendor/winnow/benches/find_slice.rs
new file mode 100644
index 000000000..226fcadbf
--- /dev/null
+++ b/vendor/winnow/benches/find_slice.rs
@@ -0,0 +1,50 @@
+use criterion::black_box;
+
+use winnow::combinator::repeat;
+use winnow::prelude::*;
+use winnow::token::take_until0;
+
+fn find_slice(c: &mut criterion::Criterion) {
+ let empty = "";
+ let start_byte = "\r".repeat(100);
+ let start_slice = "\r\n".repeat(100);
+ let small = format!("{:>10}\r\n", "").repeat(100);
+ let large = format!("{:>10000}\r\n", "").repeat(100);
+
+ let data = [
+ ("empty", (empty, empty)),
+ ("start", (&start_byte, &start_slice)),
+ ("medium", (&small, &small)),
+ ("large", (&large, &large)),
+ ];
+ let mut group = c.benchmark_group("find_slice");
+ for (name, samples) in data {
+ group.bench_with_input(
+ criterion::BenchmarkId::new("byte", name),
+ samples.0,
+ |b, sample| {
+ b.iter(|| black_box(parser_byte.parse_peek(black_box(sample)).unwrap()));
+ },
+ );
+
+ group.bench_with_input(
+ criterion::BenchmarkId::new("slice", name),
+ samples.1,
+ |b, sample| {
+ b.iter(|| black_box(parser_slice.parse_peek(black_box(sample)).unwrap()));
+ },
+ );
+ }
+ group.finish();
+}
+
+fn parser_byte(input: &mut &str) -> PResult<usize> {
+ repeat(0.., (take_until0("\r"), "\r")).parse_next(input)
+}
+
+fn parser_slice(input: &mut &str) -> PResult<usize> {
+ repeat(0.., (take_until0("\r\n"), "\r\n")).parse_next(input)
+}
+
+criterion::criterion_group!(benches, find_slice);
+criterion::criterion_main!(benches);
diff --git a/vendor/winnow/examples/arithmetic/bench.rs b/vendor/winnow/examples/arithmetic/bench.rs
index 6504454c4..692ac22c9 100644
--- a/vendor/winnow/examples/arithmetic/bench.rs
+++ b/vendor/winnow/examples/arithmetic/bench.rs
@@ -1,19 +1,31 @@
mod parser;
+mod parser_ast;
+mod parser_lexer;
use winnow::prelude::*;
-use parser::expr;
-
#[allow(clippy::eq_op, clippy::erasing_op)]
fn arithmetic(c: &mut criterion::Criterion) {
- let data = " 2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2));";
+ let data = " 2*2 / ( 5 - 1) + 3 / 4 * (2 - 7 + 567 *12 /2) + 3*(1+2*( 45 /2))";
+ let expected = 2 * 2 / (5 - 1) + 3 * (1 + 2 * (45 / 2));
+ assert_eq!(parser::expr.parse(data), Ok(expected));
+ assert_eq!(
+ parser_ast::expr.parse(data).map(|ast| ast.eval()),
+ Ok(expected)
+ );
assert_eq!(
- expr.parse_peek(data),
- Ok((";", 2 * 2 / (5 - 1) + 3 * (1 + 2 * (45 / 2)),))
+ parser_lexer::expr2.parse(data).map(|ast| ast.eval()),
+ Ok(expected)
);
- c.bench_function("arithmetic", |b| {
- b.iter(|| expr.parse_peek(data).unwrap());
+ c.bench_function("direct", |b| {
+ b.iter(|| parser::expr.parse(data).unwrap());
+ });
+ c.bench_function("ast", |b| {
+ b.iter(|| parser_ast::expr.parse(data).unwrap().eval());
+ });
+ c.bench_function("lexer", |b| {
+ b.iter(|| parser_lexer::expr2.parse_peek(data).unwrap());
});
}
diff --git a/vendor/winnow/examples/arithmetic/main.rs b/vendor/winnow/examples/arithmetic/main.rs
index 94a17d85d..e46cf2f44 100644
--- a/vendor/winnow/examples/arithmetic/main.rs
+++ b/vendor/winnow/examples/arithmetic/main.rs
@@ -2,32 +2,41 @@ use winnow::prelude::*;
mod parser;
mod parser_ast;
+mod parser_lexer;
fn main() -> Result<(), lexopt::Error> {
let args = Args::parse()?;
let input = args.input.as_deref().unwrap_or("1 + 1");
+ if let Err(err) = calc(input, args.implementation) {
+ println!("FAILED");
+ println!("{}", err);
+ }
+
+ Ok(())
+}
+fn calc(
+ input: &str,
+ imp: Impl,
+) -> Result<(), winnow::error::ParseError<&str, winnow::error::ContextError>> {
println!("{} =", input);
- match args.implementation {
- Impl::Eval => match parser::expr.parse(input) {
- Ok(result) => {
- println!(" {}", result);
- }
- Err(err) => {
- println!(" {}", err);
- }
- },
- Impl::Ast => match parser_ast::expr.parse(input) {
- Ok(result) => {
- println!(" {:#?}", result);
- }
- Err(err) => {
- println!(" {}", err);
- }
- },
+ match imp {
+ Impl::Eval => {
+ let result = parser::expr.parse(input)?;
+ println!(" {}", result);
+ }
+ Impl::Ast => {
+ let result = parser_ast::expr.parse(input)?;
+ println!(" {:#?}={}", result, result.eval());
+ }
+ Impl::Lexer => {
+ let tokens = parser_lexer::lex.parse(input)?;
+ println!(" {:#?}", tokens);
+ let result = parser_lexer::expr.parse(tokens.as_slice()).unwrap();
+ println!(" {:#?}={}", result, result.eval());
+ }
}
-
Ok(())
}
@@ -40,6 +49,7 @@ struct Args {
enum Impl {
Eval,
Ast,
+ Lexer,
}
impl Default for Impl {
@@ -61,6 +71,7 @@ impl Args {
res.implementation = args.value()?.parse_with(|s| match s {
"eval" => Ok(Impl::Eval),
"ast" => Ok(Impl::Ast),
+ "lexer" => Ok(Impl::Lexer),
_ => Err("expected `eval`, `ast`"),
})?;
}
diff --git a/vendor/winnow/examples/arithmetic/parser.rs b/vendor/winnow/examples/arithmetic/parser.rs
index 50ffbdbbb..165727515 100644
--- a/vendor/winnow/examples/arithmetic/parser.rs
+++ b/vendor/winnow/examples/arithmetic/parser.rs
@@ -2,7 +2,7 @@ use std::str::FromStr;
use winnow::prelude::*;
use winnow::{
- ascii::{digit1 as digits, space0 as spaces},
+ ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
combinator::delimited,
combinator::fold_repeat,
@@ -50,53 +50,88 @@ fn term(i: &mut &str) -> PResult<i64> {
.parse_next(i)
}
-// We transform an integer string into a i64, ignoring surrounding whitespaces
+// We transform an integer string into a i64, ignoring surrounding whitespace
// 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: &mut &str) -> PResult<i64> {
delimited(
- spaces,
- alt((
- digits.try_map(FromStr::from_str),
- delimited('(', expr, ')'),
- parens,
- )),
- spaces,
+ multispaces,
+ alt((digits.try_map(FromStr::from_str), parens)),
+ multispaces,
)
.parse_next(i)
}
-// We parse any expr surrounded by parens, ignoring all whitespaces around those
+// We parse any expr surrounded by parens, ignoring all whitespace around those
fn parens(i: &mut &str) -> PResult<i64> {
delimited('(', expr, ')').parse_next(i)
}
#[test]
fn factor_test() {
- assert_eq!(factor.parse_peek("3"), Ok(("", 3)));
- assert_eq!(factor.parse_peek(" 12"), Ok(("", 12)));
- assert_eq!(factor.parse_peek("537 "), Ok(("", 537)));
- assert_eq!(factor.parse_peek(" 24 "), Ok(("", 24)));
+ let input = "3";
+ let expected = Ok(("", 3));
+ assert_eq!(factor.parse_peek(input), expected);
+
+ let input = " 12";
+ let expected = Ok(("", 12));
+ assert_eq!(factor.parse_peek(input), expected);
+
+ let input = "537 ";
+ let expected = Ok(("", 537));
+ assert_eq!(factor.parse_peek(input), expected);
+
+ let input = " 24 ";
+ let expected = Ok(("", 24));
+ assert_eq!(factor.parse_peek(input), expected);
}
#[test]
fn term_test() {
- assert_eq!(term.parse_peek(" 12 *2 / 3"), Ok(("", 8)));
- assert_eq!(term.parse_peek(" 2* 3 *2 *2 / 3"), Ok(("", 8)));
- assert_eq!(term.parse_peek(" 48 / 3/2"), Ok(("", 8)));
+ let input = " 12 *2 / 3";
+ let expected = Ok(("", 8));
+ assert_eq!(term.parse_peek(input), expected);
+
+ let input = " 12 *2 / 3";
+ let expected = Ok(("", 8));
+ assert_eq!(term.parse_peek(input), expected);
+
+ let input = " 2* 3 *2 *2 / 3";
+ let expected = Ok(("", 8));
+ assert_eq!(term.parse_peek(input), expected);
+
+ let input = " 48 / 3/2";
+ let expected = Ok(("", 8));
+ assert_eq!(term.parse_peek(input), expected);
}
#[test]
fn expr_test() {
- assert_eq!(expr.parse_peek(" 1 + 2 "), Ok(("", 3)));
- assert_eq!(expr.parse_peek(" 12 + 6 - 4+ 3"), Ok(("", 17)));
- assert_eq!(expr.parse_peek(" 1 + 2*3 + 4"), Ok(("", 11)));
+ let input = " 1 + 2 ";
+ let expected = Ok(("", 3));
+ assert_eq!(expr.parse_peek(input), expected);
+
+ let input = " 12 + 6 - 4+ 3";
+ let expected = Ok(("", 17));
+ assert_eq!(expr.parse_peek(input), expected);
+
+ let input = " 1 + 2*3 + 4";
+ let expected = Ok(("", 11));
+ assert_eq!(expr.parse_peek(input), expected);
}
#[test]
fn parens_test() {
- assert_eq!(expr.parse_peek(" ( 2 )"), Ok(("", 2)));
- assert_eq!(expr.parse_peek(" 2* ( 3 + 4 ) "), Ok(("", 14)));
- assert_eq!(expr.parse_peek(" 2*2 / ( 5 - 1) + 3"), Ok(("", 4)));
+ let input = " ( 2 )";
+ let expected = Ok(("", 2));
+ assert_eq!(expr.parse_peek(input), expected);
+
+ let input = " 2* ( 3 + 4 ) ";
+ let expected = Ok(("", 14));
+ assert_eq!(expr.parse_peek(input), expected);
+
+ let input = " 2*2 / ( 5 - 1) + 3";
+ let expected = Ok(("", 4));
+ assert_eq!(expr.parse_peek(input), expected);
}
diff --git a/vendor/winnow/examples/arithmetic/parser_ast.rs b/vendor/winnow/examples/arithmetic/parser_ast.rs
index 5fb9847c0..0ca153487 100644
--- a/vendor/winnow/examples/arithmetic/parser_ast.rs
+++ b/vendor/winnow/examples/arithmetic/parser_ast.rs
@@ -5,13 +5,14 @@ use std::str::FromStr;
use winnow::prelude::*;
use winnow::{
- ascii::{digit1 as digit, multispace0 as multispace},
+ ascii::{digit1 as digits, multispace0 as multispaces},
combinator::alt,
- combinator::repeat,
- combinator::{delimited, preceded},
+ combinator::delimited,
+ combinator::fold_repeat,
+ token::one_of,
};
-#[derive(Debug)]
+#[derive(Debug, Clone)]
pub enum Expr {
Value(i64),
Add(Box<Expr>, Box<Expr>),
@@ -21,12 +22,17 @@ pub enum Expr {
Paren(Box<Expr>),
}
-#[derive(Debug)]
-pub enum Oper {
- Add,
- Sub,
- Mul,
- Div,
+impl Expr {
+ pub fn eval(&self) -> i64 {
+ match self {
+ Self::Value(v) => *v,
+ Self::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
+ Self::Sub(lhs, rhs) => lhs.eval() - rhs.eval(),
+ Self::Mul(lhs, rhs) => lhs.eval() * rhs.eval(),
+ Self::Div(lhs, rhs) => lhs.eval() / rhs.eval(),
+ Self::Paren(expr) => expr.eval(),
+ }
+ }
}
impl Display for Expr {
@@ -44,125 +50,135 @@ impl Display for Expr {
}
pub fn expr(i: &mut &str) -> PResult<Expr> {
- let initial = term(i)?;
- let remainder = repeat(
+ let init = term.parse_next(i)?;
+
+ fold_repeat(
0..,
- alt((
- |i: &mut &str| {
- let add = preceded("+", term).parse_next(i)?;
- Ok((Oper::Add, add))
- },
- |i: &mut &str| {
- let sub = preceded("-", term).parse_next(i)?;
- Ok((Oper::Sub, sub))
- },
- )),
+ (one_of(['+', '-']), term),
+ move || init.clone(),
+ |acc, (op, val): (char, Expr)| {
+ if op == '+' {
+ Expr::Add(Box::new(acc), Box::new(val))
+ } else {
+ Expr::Sub(Box::new(acc), Box::new(val))
+ }
+ },
)
- .parse_next(i)?;
-
- Ok(fold_exprs(initial, remainder))
+ .parse_next(i)
}
fn term(i: &mut &str) -> PResult<Expr> {
- let initial = factor(i)?;
- let remainder = repeat(
+ let init = factor.parse_next(i)?;
+
+ fold_repeat(
0..,
- alt((
- |i: &mut &str| {
- let mul = preceded("*", factor).parse_next(i)?;
- Ok((Oper::Mul, mul))
- },
- |i: &mut &str| {
- let div = preceded("/", factor).parse_next(i)?;
- Ok((Oper::Div, div))
- },
- )),
+ (one_of(['*', '/']), factor),
+ move || init.clone(),
+ |acc, (op, val): (char, Expr)| {
+ if op == '*' {
+ Expr::Mul(Box::new(acc), Box::new(val))
+ } else {
+ Expr::Div(Box::new(acc), Box::new(val))
+ }
+ },
)
- .parse_next(i)?;
-
- Ok(fold_exprs(initial, remainder))
-}
-
-fn factor(i: &mut &str) -> PResult<Expr> {
- alt((
- delimited(multispace, digit, multispace)
- .try_map(FromStr::from_str)
- .map(Expr::Value),
- parens,
- ))
.parse_next(i)
}
-fn parens(i: &mut &str) -> PResult<Expr> {
+fn factor(i: &mut &str) -> PResult<Expr> {
delimited(
- multispace,
- delimited("(", expr.map(|e| Expr::Paren(Box::new(e))), ")"),
- multispace,
+ multispaces,
+ alt((digits.try_map(FromStr::from_str).map(Expr::Value), parens)),
+ multispaces,
)
.parse_next(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 parens(i: &mut &str) -> PResult<Expr> {
+ delimited("(", expr, ")")
+ .map(|e| Expr::Paren(Box::new(e)))
+ .parse_next(i)
}
#[test]
fn factor_test() {
- assert_eq!(
- factor
- .parse_peek(" 3 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok(("", String::from("Value(3)")))
- );
+ let input = "3";
+ let expected = Ok(("", String::from("Value(3)")));
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 12";
+ let expected = Ok(("", String::from("Value(12)")));
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = "537 ";
+ let expected = Ok(("", String::from("Value(537)")));
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 24 ";
+ let expected = Ok(("", String::from("Value(24)")));
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse_peek(input), expected);
}
#[test]
fn term_test() {
- assert_eq!(
- term.parse_peek(" 3 * 5 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok(("", String::from("Mul(Value(3), Value(5))")))
- );
+ let input = " 12 *2 / 3";
+ let expected = Ok(("", String::from("Div(Mul(Value(12), Value(2)), Value(3))")));
+ assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 12 *2 / 3";
+ let expected = Ok(("", String::from("Div(Mul(Value(12), Value(2)), Value(3))")));
+ assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 2* 3 *2 *2 / 3";
+ let expected = Ok((
+ "",
+ String::from("Div(Mul(Mul(Mul(Value(2), Value(3)), Value(2)), Value(2)), Value(3))"),
+ ));
+ assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 48 / 3/2";
+ let expected = Ok(("", String::from("Div(Div(Value(48), Value(3)), Value(2))")));
+ assert_eq!(term.map(|e| format!("{e:?}")).parse_peek(input), expected);
}
#[test]
fn expr_test() {
- assert_eq!(
- expr.parse_peek(" 1 + 2 * 3 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok(("", String::from("Add(Value(1), Mul(Value(2), Value(3)))")))
- );
- assert_eq!(
- expr.parse_peek(" 1 + 2 * 3 / 4 - 5 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok((
- "",
- String::from("Sub(Add(Value(1), Div(Mul(Value(2), Value(3)), Value(4))), Value(5))")
- ))
- );
- assert_eq!(
- expr.parse_peek(" 72 / 2 / 3 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok(("", String::from("Div(Div(Value(72), Value(2)), Value(3))")))
- );
+ let input = " 1 + 2 ";
+ let expected = Ok(("", String::from("Add(Value(1), Value(2))")));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 12 + 6 - 4+ 3";
+ let expected = Ok((
+ "",
+ String::from("Add(Sub(Add(Value(12), Value(6)), Value(4)), Value(3))"),
+ ));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 1 + 2*3 + 4";
+ let expected = Ok((
+ "",
+ String::from("Add(Add(Value(1), Mul(Value(2), Value(3))), Value(4))"),
+ ));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
}
#[test]
fn parens_test() {
- assert_eq!(
- expr.parse_peek(" ( 1 + 2 ) * 3 ")
- .map(|(i, x)| (i, format!("{:?}", x))),
- Ok((
- "",
- String::from("Mul(Paren(Add(Value(1), Value(2))), Value(3))")
- ))
- );
+ let input = " ( 2 )";
+ let expected = Ok(("", String::from("Paren(Value(2))")));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 2* ( 3 + 4 ) ";
+ let expected = Ok((
+ "",
+ String::from("Mul(Value(2), Paren(Add(Value(3), Value(4))))"),
+ ));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
+
+ let input = " 2*2 / ( 5 - 1) + 3";
+ let expected = Ok((
+ "",
+ String::from("Add(Div(Mul(Value(2), Value(2)), Paren(Sub(Value(5), Value(1)))), Value(3))"),
+ ));
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse_peek(input), expected);
}
diff --git a/vendor/winnow/examples/arithmetic/parser_lexer.rs b/vendor/winnow/examples/arithmetic/parser_lexer.rs
new file mode 100644
index 000000000..f49566d38
--- /dev/null
+++ b/vendor/winnow/examples/arithmetic/parser_lexer.rs
@@ -0,0 +1,297 @@
+use std::fmt;
+use std::fmt::{Debug, Display, Formatter};
+
+use std::str::FromStr;
+
+use winnow::prelude::*;
+use winnow::{
+ ascii::{digit1 as digits, multispace0 as multispaces},
+ combinator::alt,
+ combinator::dispatch,
+ combinator::fail,
+ combinator::fold_repeat,
+ combinator::peek,
+ combinator::repeat,
+ combinator::{delimited, preceded, terminated},
+ token::any,
+ token::one_of,
+};
+
+#[derive(Debug, Clone)]
+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>),
+}
+
+impl Expr {
+ pub fn eval(&self) -> i64 {
+ match self {
+ Self::Value(v) => *v,
+ Self::Add(lhs, rhs) => lhs.eval() + rhs.eval(),
+ Self::Sub(lhs, rhs) => lhs.eval() - rhs.eval(),
+ Self::Mul(lhs, rhs) => lhs.eval() * rhs.eval(),
+ Self::Div(lhs, rhs) => lhs.eval() / rhs.eval(),
+ Self::Paren(expr) => expr.eval(),
+ }
+ }
+}
+
+impl Display for Expr {
+ fn fmt(&self, format: &mut Formatter<'_>) -> fmt::Result {
+ use Expr::{Add, Div, Mul, Paren, Sub, Value};
+ 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),
+ }
+ }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Token {
+ Value(i64),
+ Oper(Oper),
+ OpenParen,
+ CloseParen,
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+pub enum Oper {
+ Add,
+ Sub,
+ Mul,
+ Div,
+}
+
+impl winnow::stream::ContainsToken<Token> for Token {
+ #[inline(always)]
+ fn contains_token(&self, token: Token) -> bool {
+ *self == token
+ }
+}
+
+impl winnow::stream::ContainsToken<Token> for &'_ [Token] {
+ #[inline]
+ fn contains_token(&self, token: Token) -> bool {
+ self.iter().any(|t| *t == token)
+ }
+}
+
+impl<const LEN: usize> winnow::stream::ContainsToken<Token> for &'_ [Token; LEN] {
+ #[inline]
+ fn contains_token(&self, token: Token) -> bool {
+ self.iter().any(|t| *t == token)
+ }
+}
+
+impl<const LEN: usize> winnow::stream::ContainsToken<Token> for [Token; LEN] {
+ #[inline]
+ fn contains_token(&self, token: Token) -> bool {
+ self.iter().any(|t| *t == token)
+ }
+}
+
+#[allow(dead_code)]
+pub fn expr2(i: &mut &str) -> PResult<Expr> {
+ let tokens = lex.parse_next(i)?;
+ expr.parse_next(&mut tokens.as_slice())
+}
+
+pub fn lex(i: &mut &str) -> PResult<Vec<Token>> {
+ preceded(multispaces, repeat(1.., terminated(token, multispaces))).parse_next(i)
+}
+
+fn token(i: &mut &str) -> PResult<Token> {
+ dispatch! {peek(any);
+ '0'..='9' => digits.try_map(FromStr::from_str).map(Token::Value),
+ '(' => '('.value(Token::OpenParen),
+ ')' => ')'.value(Token::CloseParen),
+ '+' => '+'.value(Token::Oper(Oper::Add)),
+ '-' => '-'.value(Token::Oper(Oper::Sub)),
+ '*' => '*'.value(Token::Oper(Oper::Mul)),
+ '/' => '/'.value(Token::Oper(Oper::Div)),
+ _ => fail,
+ }
+ .parse_next(i)
+}
+
+pub fn expr(i: &mut &[Token]) -> PResult<Expr> {
+ let init = term.parse_next(i)?;
+
+ fold_repeat(
+ 0..,
+ (
+ one_of([Token::Oper(Oper::Add), Token::Oper(Oper::Sub)]),
+ term,
+ ),
+ move || init.clone(),
+ |acc, (op, val): (Token, Expr)| {
+ if op == Token::Oper(Oper::Add) {
+ Expr::Add(Box::new(acc), Box::new(val))
+ } else {
+ Expr::Sub(Box::new(acc), Box::new(val))
+ }
+ },
+ )
+ .parse_next(i)
+}
+
+fn term(i: &mut &[Token]) -> PResult<Expr> {
+ let init = factor.parse_next(i)?;
+
+ fold_repeat(
+ 0..,
+ (
+ one_of([Token::Oper(Oper::Mul), Token::Oper(Oper::Div)]),
+ factor,
+ ),
+ move || init.clone(),
+ |acc, (op, val): (Token, Expr)| {
+ if op == Token::Oper(Oper::Mul) {
+ Expr::Mul(Box::new(acc), Box::new(val))
+ } else {
+ Expr::Div(Box::new(acc), Box::new(val))
+ }
+ },
+ )
+ .parse_next(i)
+}
+
+fn factor(i: &mut &[Token]) -> PResult<Expr> {
+ alt((
+ one_of(|t| matches!(t, Token::Value(_))).map(|t| match t {
+ Token::Value(v) => Expr::Value(v),
+ _ => unreachable!(),
+ }),
+ parens,
+ ))
+ .parse_next(i)
+}
+
+fn parens(i: &mut &[Token]) -> PResult<Expr> {
+ delimited(one_of(Token::OpenParen), expr, one_of(Token::CloseParen))
+ .map(|e| Expr::Paren(Box::new(e)))
+ .parse_next(i)
+}
+
+#[test]
+fn lex_test() {
+ let input = "3";
+ let expected = Ok(String::from(r#"("", [Value(3)])"#));
+ assert_eq!(lex.parse_peek(input).map(|e| format!("{e:?}")), expected);
+
+ let input = " 24 ";
+ let expected = Ok(String::from(r#"("", [Value(24)])"#));
+ assert_eq!(lex.parse_peek(input).map(|e| format!("{e:?}")), expected);
+
+ let input = " 12 *2 / 3";
+ let expected = Ok(String::from(
+ r#"("", [Value(12), Oper(Mul), Value(2), Oper(Div), Value(3)])"#,
+ ));
+ assert_eq!(lex.parse_peek(input).map(|e| format!("{e:?}")), expected);
+
+ let input = " 2*2 / ( 5 - 1) + 3";
+ let expected = Ok(String::from(
+ r#"("", [Value(2), Oper(Mul), Value(2), Oper(Div), OpenParen, Value(5), Oper(Sub), Value(1), CloseParen, Oper(Add), Value(3)])"#,
+ ));
+ assert_eq!(lex.parse_peek(input).map(|e| format!("{e:?}")), expected);
+}
+
+#[test]
+fn factor_test() {
+ let input = "3";
+ let expected = Ok(String::from("Value(3)"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 12";
+ let expected = Ok(String::from("Value(12)"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = "537 ";
+ let expected = Ok(String::from("Value(537)"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 24 ";
+ let expected = Ok(String::from("Value(24)"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(factor.map(|e| format!("{e:?}")).parse(&input), expected);
+}
+
+#[test]
+fn term_test() {
+ let input = " 12 *2 / 3";
+ let expected = Ok(String::from("Div(Mul(Value(12), Value(2)), Value(3))"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(term.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 12 *2 / 3";
+ let expected = Ok(String::from("Div(Mul(Value(12), Value(2)), Value(3))"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(term.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 2* 3 *2 *2 / 3";
+ let expected = Ok(String::from(
+ "Div(Mul(Mul(Mul(Value(2), Value(3)), Value(2)), Value(2)), Value(3))",
+ ));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(term.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 48 / 3/2";
+ let expected = Ok(String::from("Div(Div(Value(48), Value(3)), Value(2))"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(term.map(|e| format!("{e:?}")).parse(&input), expected);
+}
+
+#[test]
+fn expr_test() {
+ let input = " 1 + 2 ";
+ let expected = Ok(String::from("Add(Value(1), Value(2))"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 12 + 6 - 4+ 3";
+ let expected = Ok(String::from(
+ "Add(Sub(Add(Value(12), Value(6)), Value(4)), Value(3))",
+ ));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 1 + 2*3 + 4";
+ let expected = Ok(String::from(
+ "Add(Add(Value(1), Mul(Value(2), Value(3))), Value(4))",
+ ));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+}
+
+#[test]
+fn parens_test() {
+ let input = " ( 2 )";
+ let expected = Ok(String::from("Paren(Value(2))"));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 2* ( 3 + 4 ) ";
+ let expected = Ok(String::from(
+ "Mul(Value(2), Paren(Add(Value(3), Value(4))))",
+ ));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+
+ let input = " 2*2 / ( 5 - 1) + 3";
+ let expected = Ok(String::from(
+ "Add(Div(Mul(Value(2), Value(2)), Paren(Sub(Value(5), Value(1)))), Value(3))",
+ ));
+ let input = lex.parse(input).unwrap();
+ assert_eq!(expr.map(|e| format!("{e:?}")).parse(&input), expected);
+}
diff --git a/vendor/winnow/examples/http/parser.rs b/vendor/winnow/examples/http/parser.rs
index 7f62c4447..3a047545f 100644
--- a/vendor/winnow/examples/http/parser.rs
+++ b/vendor/winnow/examples/http/parser.rs
@@ -118,7 +118,7 @@ fn is_token(c: u8) -> bool {
}
fn is_version(c: u8) -> bool {
- (b'0'..=b'9').contains(&c) || c == b'.'
+ c.is_ascii_digit() || c == b'.'
}
fn not_line_ending(c: u8) -> bool {
diff --git a/vendor/winnow/examples/http/parser_streaming.rs b/vendor/winnow/examples/http/parser_streaming.rs
index d59e6f8a9..1f850e8b4 100644
--- a/vendor/winnow/examples/http/parser_streaming.rs
+++ b/vendor/winnow/examples/http/parser_streaming.rs
@@ -119,7 +119,7 @@ fn is_token(c: u8) -> bool {
}
fn is_version(c: u8) -> bool {
- (b'0'..=b'9').contains(&c) || c == b'.'
+ c.is_ascii_digit() || c == b'.'
}
fn not_line_ending(c: u8) -> bool {
diff --git a/vendor/winnow/examples/ini/parser_str.rs b/vendor/winnow/examples/ini/parser_str.rs
index 8f7b9cefc..c1858dbfc 100644
--- a/vendor/winnow/examples/ini/parser_str.rs
+++ b/vendor/winnow/examples/ini/parser_str.rs
@@ -6,7 +6,7 @@ use winnow::{
combinator::opt,
combinator::repeat,
combinator::{delimited, terminated},
- token::{take_till0, take_while},
+ token::{take_till, take_while},
};
pub type Stream<'i> = &'i str;
@@ -36,7 +36,7 @@ fn keys_and_values<'s>(input: &mut Stream<'s>) -> PResult<HashMap<&'s str, &'s s
fn key_value<'s>(i: &mut Stream<'s>) -> PResult<(&'s str, &'s str)> {
let key = alphanumeric.parse_next(i)?;
let _ = (opt(space), "=", opt(space)).parse_next(i)?;
- let val = take_till0(is_line_ending_or_comment).parse_next(i)?;
+ let val = take_till(0.., is_line_ending_or_comment).parse_next(i)?;
let _ = opt(space).parse_next(i)?;
let _ = opt((";", not_line_ending)).parse_next(i)?;
let _ = opt(space_or_line_ending).parse_next(i)?;
diff --git a/vendor/winnow/examples/json/parser.rs b/vendor/winnow/examples/json/parser.rs
index 8aa3bd387..250621e9c 100644
--- a/vendor/winnow/examples/json/parser.rs
+++ b/vendor/winnow/examples/json/parser.rs
@@ -7,7 +7,7 @@ use winnow::{
combinator::alt,
combinator::cut_err,
combinator::{delimited, preceded, separated_pair, terminated},
- combinator::{fold_repeat, separated0},
+ combinator::{fold_repeat, separated},
error::{AddContext, ParserError},
token::{any, none_of, take, take_while},
};
@@ -153,7 +153,7 @@ fn u16_hex<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<u1
.parse_next(input)
}
-/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly,
+/// Some combinators, like `separated` or `repeat`, will call a parser repeatedly,
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
@@ -162,7 +162,10 @@ fn array<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
) -> PResult<Vec<JsonValue>, E> {
preceded(
('[', ws),
- cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))),
+ cut_err(terminated(
+ separated(0.., json_value, (ws, ',', ws)),
+ (ws, ']'),
+ )),
)
.context("array")
.parse_next(input)
@@ -173,7 +176,10 @@ fn object<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>
) -> PResult<HashMap<String, JsonValue>, E> {
preceded(
('{', ws),
- cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))),
+ cut_err(terminated(
+ separated(0.., key_value, (ws, ',', ws)),
+ (ws, '}'),
+ )),
)
.context("object")
.parse_next(input)
diff --git a/vendor/winnow/examples/json/parser_dispatch.rs b/vendor/winnow/examples/json/parser_dispatch.rs
index 6fa722b45..8f7eaf999 100644
--- a/vendor/winnow/examples/json/parser_dispatch.rs
+++ b/vendor/winnow/examples/json/parser_dispatch.rs
@@ -10,7 +10,7 @@ use winnow::{
combinator::success,
combinator::{alt, dispatch},
combinator::{delimited, preceded, separated_pair, terminated},
- combinator::{fold_repeat, separated0},
+ combinator::{fold_repeat, separated},
error::{AddContext, ParserError},
token::{any, none_of, take, take_while},
};
@@ -160,7 +160,7 @@ fn u16_hex<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<u1
.parse_next(input)
}
-/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly,
+/// Some combinators, like `separated` or `repeat`, will call a parser repeatedly,
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
@@ -169,7 +169,10 @@ fn array<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
) -> PResult<Vec<JsonValue>, E> {
preceded(
('[', ws),
- cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))),
+ cut_err(terminated(
+ separated(0.., json_value, (ws, ',', ws)),
+ (ws, ']'),
+ )),
)
.context("array")
.parse_next(input)
@@ -180,7 +183,10 @@ fn object<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>
) -> PResult<HashMap<String, JsonValue>, E> {
preceded(
('{', ws),
- cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))),
+ cut_err(terminated(
+ separated(0.., key_value, (ws, ',', ws)),
+ (ws, '}'),
+ )),
)
.context("object")
.parse_next(input)
diff --git a/vendor/winnow/examples/json/parser_partial.rs b/vendor/winnow/examples/json/parser_partial.rs
index 3538d8e13..779e05f87 100644
--- a/vendor/winnow/examples/json/parser_partial.rs
+++ b/vendor/winnow/examples/json/parser_partial.rs
@@ -7,7 +7,7 @@ use winnow::{
combinator::alt,
combinator::{cut_err, rest},
combinator::{delimited, preceded, separated_pair, terminated},
- combinator::{fold_repeat, separated0},
+ combinator::{fold_repeat, separated},
error::{AddContext, ParserError},
stream::Partial,
token::{any, none_of, take, take_while},
@@ -154,7 +154,7 @@ fn u16_hex<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<u1
.parse_next(input)
}
-/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly,
+/// Some combinators, like `separated` or `repeat`, will call a parser repeatedly,
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
@@ -163,7 +163,10 @@ fn array<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
) -> PResult<Vec<JsonValue>, E> {
preceded(
('[', ws),
- cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))),
+ cut_err(terminated(
+ separated(0.., json_value, (ws, ',', ws)),
+ (ws, ']'),
+ )),
)
.context("array")
.parse_next(input)
@@ -174,7 +177,10 @@ fn object<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>
) -> PResult<HashMap<String, JsonValue>, E> {
preceded(
('{', ws),
- cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))),
+ cut_err(terminated(
+ separated(0.., key_value, (ws, ',', ws)),
+ (ws, '}'),
+ )),
)
.context("object")
.parse_next(input)
diff --git a/vendor/winnow/examples/json_iterator.rs b/vendor/winnow/examples/json_iterator.rs
index b8b46f39c..9c21ae38c 100644
--- a/vendor/winnow/examples/json_iterator.rs
+++ b/vendor/winnow/examples/json_iterator.rs
@@ -5,7 +5,7 @@ use winnow::{
ascii::{alphanumeric1 as alphanumeric, escaped, float},
combinator::alt,
combinator::cut_err,
- combinator::separated0,
+ combinator::separated,
combinator::{preceded, separated_pair, terminated},
error::ParserError,
error::StrContext,
@@ -233,7 +233,7 @@ fn array(i: &mut &str) -> PResult<()> {
preceded(
'[',
cut_err(terminated(
- separated0(value, preceded(sp, ',')),
+ separated(0.., value, preceded(sp, ',')),
preceded(sp, ']'),
)),
)
@@ -249,7 +249,7 @@ fn hash(i: &mut &str) -> PResult<()> {
preceded(
'{',
cut_err(terminated(
- separated0(key_value, preceded(sp, ',')),
+ separated(0.., key_value, preceded(sp, ',')),
preceded(sp, '}'),
)),
)
diff --git a/vendor/winnow/examples/ndjson/parser.rs b/vendor/winnow/examples/ndjson/parser.rs
index aaa5c9346..81b47459b 100644
--- a/vendor/winnow/examples/ndjson/parser.rs
+++ b/vendor/winnow/examples/ndjson/parser.rs
@@ -8,7 +8,7 @@ use winnow::{
combinator::alt,
combinator::cut_err,
combinator::{delimited, preceded, separated_pair, terminated},
- combinator::{fold_repeat, separated0},
+ combinator::{fold_repeat, separated},
error::{AddContext, ParserError},
stream::Partial,
token::{any, none_of, take, take_while},
@@ -158,7 +158,7 @@ fn u16_hex<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<u1
.parse_next(input)
}
-/// Some combinators, like `separated0` or `many0`, will call a parser repeatedly,
+/// Some combinators, like `separated` or `repeat`, will call a parser repeatedly,
/// accumulating results in a `Vec`, until it encounters an error.
/// If you want more control on the parser application, check out the `iterator`
/// combinator (cf `examples/iterator.rs`)
@@ -167,7 +167,10 @@ fn array<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>(
) -> PResult<Vec<JsonValue>, E> {
preceded(
('[', ws),
- cut_err(terminated(separated0(json_value, (ws, ',', ws)), (ws, ']'))),
+ cut_err(terminated(
+ separated(0.., json_value, (ws, ',', ws)),
+ (ws, ']'),
+ )),
)
.context("array")
.parse_next(input)
@@ -178,7 +181,10 @@ fn object<'i, E: ParserError<Stream<'i>> + AddContext<Stream<'i>, &'static str>>
) -> PResult<HashMap<String, JsonValue>, E> {
preceded(
('{', ws),
- cut_err(terminated(separated0(key_value, (ws, ',', ws)), (ws, '}'))),
+ cut_err(terminated(
+ separated(0.., key_value, (ws, ',', ws)),
+ (ws, '}'),
+ )),
)
.context("object")
.parse_next(input)
diff --git a/vendor/winnow/examples/s_expression/parser.rs b/vendor/winnow/examples/s_expression/parser.rs
index 919dcf430..c44505342 100644
--- a/vendor/winnow/examples/s_expression/parser.rs
+++ b/vendor/winnow/examples/s_expression/parser.rs
@@ -58,7 +58,7 @@ pub enum Atom {
BuiltIn(BuiltIn),
}
-/// Now, the most basic type. We define some built-in functions that our lisp has
+/// Now, the most basic type. We define some built-in functions that our lisp has
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub enum BuiltIn {
Plus,
diff --git a/vendor/winnow/examples/string/parser.rs b/vendor/winnow/examples/string/parser.rs
index 6b6345807..01de737b1 100644
--- a/vendor/winnow/examples/string/parser.rs
+++ b/vendor/winnow/examples/string/parser.rs
@@ -15,7 +15,7 @@ use winnow::combinator::fold_repeat;
use winnow::combinator::{delimited, preceded};
use winnow::error::{FromExternalError, ParserError};
use winnow::prelude::*;
-use winnow::token::{take_till1, take_while};
+use winnow::token::{take_till, take_while};
/// Parse a string. Use a loop of `parse_fragment` and push all of the fragments
/// into an output string.
@@ -78,13 +78,13 @@ where
/// Parse a non-empty block of text that doesn't include \ or "
fn parse_literal<'a, E: ParserError<&'a str>>(input: &mut &'a str) -> PResult<&'a str, E> {
- // `take_till1` parses a string of 0 or more characters that aren't one of the
+ // `take_till` parses a string of 0 or more characters that aren't one of the
// given characters.
- let not_quote_slash = take_till1(['"', '\\']);
+ let not_quote_slash = take_till(1.., ['"', '\\']);
// `verify` runs a parser, then runs a verification function on the output of
// the parser. The verification function accepts the output only if it
- // returns true. In this case, we want to ensure that the output of take_till1
+ // returns true. In this case, we want to ensure that the output of take_till
// is non-empty.
not_quote_slash
.verify(|s: &str| !s.is_empty())
diff --git a/vendor/winnow/src/_topic/arithmetic.rs b/vendor/winnow/src/_topic/arithmetic.rs
index 1a6eddcc4..d94b4fa4b 100644
--- a/vendor/winnow/src/_topic/arithmetic.rs
+++ b/vendor/winnow/src/_topic/arithmetic.rs
@@ -11,3 +11,9 @@
//! ```rust
#![doc = include_str!("../../examples/arithmetic/parser_ast.rs")]
//! ```
+//!
+//! ## Parse to Tokens then AST
+//!
+//! ```rust
+#![doc = include_str!("../../examples/arithmetic/parser_lexer.rs")]
+//! ```
diff --git a/vendor/winnow/src/_topic/mod.rs b/vendor/winnow/src/_topic/mod.rs
index 72c8145fe..79ba28a62 100644
--- a/vendor/winnow/src/_topic/mod.rs
+++ b/vendor/winnow/src/_topic/mod.rs
@@ -14,13 +14,14 @@
//! - [Implementing `FromStr`][fromstr]
//! - [Performance][performance]
//! - [Parsing Partial Input][partial]
-//! - [Custom stream][stream]
+//! - [Custom stream or token][stream]
//! - [Custom errors][error]
//!
//! See also parsers written with `winnow`:
//!
//! - [`toml_edit`](https://crates.io/crates/toml_edit)
//! - [`hcl-edit`](https://crates.io/crates/hcl-edit)
+#![allow(clippy::std_instead_of_core)]
pub mod arithmetic;
pub mod error;
diff --git a/vendor/winnow/src/_topic/partial.rs b/vendor/winnow/src/_topic/partial.rs
index 19895d35a..7a974217e 100644
--- a/vendor/winnow/src/_topic/partial.rs
+++ b/vendor/winnow/src/_topic/partial.rs
@@ -1,12 +1,12 @@
//! # Parsing Partial Input
//!
-//! Typically, the input being parsed is all in-memory, or is complete. Some data sources are too
+//! Typically, the input being parsed is all in-memory, or is complete. Some data sources are too
//! large to fit into memory, only allowing parsing an incomplete or [`Partial`] subset of the
//! data, requiring incrementally parsing.
//!
//! By wrapping a stream, like `&[u8]`, with [`Partial`], parsers will report when the data is
//! [`Incomplete`] and more input is [`Needed`], allowing the caller to stream-in additional data
-//! to be parsed. The data is then parsed a chunk at a time.
+//! to be parsed. The data is then parsed a chunk at a time.
//!
//! Chunks are typically defined by either:
//! - A header reporting the number of bytes, like with [`length_value`]
@@ -19,7 +19,7 @@
//! parser is for the next chunk.
//!
//! Caveats:
-//! - `winnow` takes the approach of re-parsing from scratch. Chunks should be relatively small to
+//! - `winnow` takes the approach of re-parsing from scratch. Chunks should be relatively small to
//! prevent the re-parsing overhead from dominating.
//! - Parsers like [`repeat`] do not know when an `eof` is from insufficient data or the end of the
//! stream, causing them to always report [`Incomplete`].
diff --git a/vendor/winnow/src/_topic/performance.rs b/vendor/winnow/src/_topic/performance.rs
index 8a6555a06..2b5303846 100644
--- a/vendor/winnow/src/_topic/performance.rs
+++ b/vendor/winnow/src/_topic/performance.rs
@@ -5,19 +5,19 @@
//! See also the general Rust [Performance Book](https://nnethercote.github.io/perf-book/)
//!
//! Tips
-//! - Try `cargo add winnow -F simd`. For some it offers significant performance improvements
+//! - Try `cargo add winnow -F simd`. For some it offers significant performance improvements
//! - When enough cases of an [`alt`] have unique prefixes, prefer [`dispatch`]
//! - When parsing text, try to parse as bytes (`u8`) rather than `char`s ([`BStr`] can make
//! debugging easier)
//! - Find simplified subsets of the grammar to parse, falling back to the full grammar when it
//! doesn't work. For example, when parsing json strings, parse them without support for escapes,
//! falling back to escape support if it fails.
-//! - Watch for large return types. A surprising place these can show up is when chaining parsers
+//! - Watch for large return types. A surprising place these can show up is when chaining parsers
//! with a tuple.
//!
//! ## Build-time Performance
//!
-//! Returning complex types as `impl Trait` can negatively impact build times. This can hit in
+//! Returning complex types as `impl Trait` can negatively impact build times. This can hit in
//! surprising cases like:
//! ```rust
//! # use winnow::prelude::*;
diff --git a/vendor/winnow/src/_topic/stream.rs b/vendor/winnow/src/_topic/stream.rs
index 4f94a94b9..2254f8710 100644
--- a/vendor/winnow/src/_topic/stream.rs
+++ b/vendor/winnow/src/_topic/stream.rs
@@ -1,20 +1,21 @@
-//! # Custom [`Stream`][crate::stream::Stream]
+//! # Custom [`Stream`]
//!
//! `winnow` is batteries included with support for
//! - Basic inputs like `&str`, newtypes with
-//! - Improved debug output like [`Bytes`][crate::Bytes]
-//! - [`Stateful`][crate::Stateful] for passing state through your parser, like tracking recursion
+//! - Improved debug output like [`Bytes`]
+//! - [`Stateful`] for passing state through your parser, like tracking recursion
//! depth
-//! - [`Located`][crate::Located] for looking up the absolute position of a token
+//! - [`Located`] for looking up the absolute position of a token
//!
-//! But that won't always cut it for your parser. For example, you might lex `&str` into
+//! But that won't always cut it for your parser. For example, you might lex `&str` into
//! a series of tokens and then want to parse a `TokenStream`.
//!
//! ## Implementing a custom stream
//!
-//! Let's assume we have an input type we'll call `MyStream`. `MyStream` is a sequence of `MyItem` type.
-//! The goal is to define parsers with this signature: `&mut MyStream -> PResult<Output>`.
+//! Let's assume we have an input type we'll call `MyStream`.
+//! `MyStream` is a sequence of `MyItem` type.
//!
+//! The goal is to define parsers with this signature: `&mut MyStream -> PResult<Output>`.
//! ```rust
//! # use winnow::prelude::*;
//! # use winnow::token::tag;
@@ -25,7 +26,7 @@
//! }
//! ```
//!
-//! Here are the traits we have to implement for `MyStream`:
+//! Here are the traits you may have to implement for `MyStream`:
//!
//! | trait | usage |
//! |---|---|
@@ -38,17 +39,28 @@
//! | [`Location`] |Calculate location within initial input|
//! | [`Offset`] |Calculate the offset between slices|
//!
-//! Here are the traits we have to implement for `MyItem`:
+//! And for `MyItem`:
//!
//! | trait | usage |
//! |---|---|
//! | [`AsChar`] |Transforms common types to a char for basic token parsing|
//! | [`ContainsToken`] |Look for the token in the given set|
//!
-//! And traits for slices of `MyItem`:
+//! And traits for `&[MyItem]`:
//!
+//! | trait | usage |
+//! |---|---|
//! | [`SliceLen`] |Calculate the input length|
//! | [`ParseSlice`] |Used to integrate `&str`'s `parse()` method|
+//!
+//! ## Implementing a custom token
+//!
+//! If you are parsing `&[Myitem]`, leaving just the `MyItem` traits.
+//!
+//! For example:
+//! ```rust
+#![doc = include_str!("../../examples/arithmetic/parser_lexer.rs")]
+//! ```
#[allow(unused_imports)] // Here for intra-dock links
use crate::stream::*;
diff --git a/vendor/winnow/src/_topic/why.rs b/vendor/winnow/src/_topic/why.rs
index e0328f117..d49af7e01 100644
--- a/vendor/winnow/src/_topic/why.rs
+++ b/vendor/winnow/src/_topic/why.rs
@@ -2,7 +2,7 @@
//!
//! To answer this question, it will be useful to contrast this with other approaches to parsing.
//!
-//! **Note:** This will focus on principles and priorities. For a deeper and wider wider
+//! **Note:** This will focus on principles and priorities. For a deeper and wider wider
//! comparison with other Rust parser libraries, see
//! [parse-rosetta-rs](https://github.com/rosetta-rs/parse-rosetta-rs).
//!
@@ -58,7 +58,7 @@
//!
//! ## `nom`
//!
-//! `winnow` is a fork of the venerable [`nom`](https://crates.io/crates/nom). The difference
+//! `winnow` is a fork of the venerable [`nom`](https://crates.io/crates/nom). The difference
//! between them is largely in priorities. `nom` prioritizes:
//! - Lower churn for existing users while `winnow` is trying to find ways to make things better
//! for the parsers yet to be written.
@@ -78,10 +78,10 @@
//! > "If you need to implement either `Parser` or `Strategy` by hand, that's a problem that needs fixing".
//!
//! This is under "batteries included" but it also ties into the feeling that `chumksy` acts more like
-//! a framework. Instead of composing together helpers, you are expected to do everything through
+//! a framework. Instead of composing together helpers, you are expected to do everything through
//! their system to the point that it is non-trivial to implement their `Parser` trait and are
//! encouraged to use the
-//! [`custom`](https://docs.rs/chumsky/0.9.0/chumsky/primitive/fn.custom.html) helper. This
+//! [`custom`](https://docs.rs/chumsky/0.9.0/chumsky/primitive/fn.custom.html) helper. This
//! requires re-framing everything to fit within their model and makes the code harder to understand
//! and debug as you are working with abstract operations that will eventually be applied
//! rather than directly with the parsers.
@@ -90,7 +90,7 @@
//! Probably the biggest thing that `winnow` loses out on is optimizations from ["parse modes" via
//! GATs](https://github.com/zesterer/chumsky/pull/82) which allows downstream parsers to tell
//! upstream parsers when information will be discarded, allowing bypassing expensive operations,
-//! like allocations. This requires a lot more complex interaction with parsers that isn't as
+//! like allocations. This requires a lot more complex interaction with parsers that isn't as
//! trivial to do with bare functions which would lose out on any of that side-band information.
//! Instead, we work around this with things like the [`Accumulate`] trait.
diff --git a/vendor/winnow/src/_tutorial/chapter_0.rs b/vendor/winnow/src/_tutorial/chapter_0.rs
index 47c196e86..35a2d1476 100644
--- a/vendor/winnow/src/_tutorial/chapter_0.rs
+++ b/vendor/winnow/src/_tutorial/chapter_0.rs
@@ -10,7 +10,7 @@
//! ## About
//!
//! `winnow` is a parser-combinator library. In other words, it gives you tools to define:
-//! - "parsers", or functions that takes an input and gives back an output
+//! - "parsers", or functions that take an input and give back an output
//! - "combinators", or functions that take parsers and _combine_ them together!
//!
//! While "combinator" might be an unfamiliar word, you are likely using them in your rust code
diff --git a/vendor/winnow/src/_tutorial/chapter_1.rs b/vendor/winnow/src/_tutorial/chapter_1.rs
index b16a16657..2d94418a9 100644
--- a/vendor/winnow/src/_tutorial/chapter_1.rs
+++ b/vendor/winnow/src/_tutorial/chapter_1.rs
@@ -10,17 +10,17 @@
//! - `Err` indicates the parser could not find what it was looking for.
//!
//! Parsers do more than just return a binary "success"/"failure" code.
-//! On success, the parser will return the processed data. The input will be left pointing to
+//! On success, the parser will return the processed data. The input will be left pointing to
//! data that still needs processing
//!
//! If the parser failed, then there are multiple errors that could be returned.
//! For simplicity, however, in the next chapters we will leave these unexplored.
//!
//! ```text
-//! ┌─► Ok(what matched the parser)
-//! ┌─────────┐ │
-//! my input───►│my parser├──►either──┤
-//! └─────────┘ └─► Err(...)
+//! ┌─► Ok(what matched the parser)
+//! ┌─────────┐ │
+//! my input───►│my parser├──►either──┤
+//! └─────────┘ └─► Err(...)
//! ```
//!
//!
@@ -53,7 +53,7 @@
//!
//! This parser function should take in a `&str`:
//!
-//! - Since it is supposed to succeed, we know it will return the Ok Variant.
+//! - Since it is supposed to succeed, we know it will return the `Ok` variant.
//! - Since it does nothing to our input, the remaining input is the same as the input.
//! - Since it doesn't parse anything, it also should just return an empty string.
//!
diff --git a/vendor/winnow/src/_tutorial/chapter_2.rs b/vendor/winnow/src/_tutorial/chapter_2.rs
index 0fb80ac37..c27b7196e 100644
--- a/vendor/winnow/src/_tutorial/chapter_2.rs
+++ b/vendor/winnow/src/_tutorial/chapter_2.rs
@@ -4,7 +4,7 @@
//!
//! ## Tokens
//!
-//! [`Stream`] provides some core operations to help with parsing. For example, to process a
+//! [`Stream`] provides some core operations to help with parsing. For example, to process a
//! single token, you can do:
//! ```rust
//! # use winnow::Parser;
@@ -135,13 +135,13 @@
//! # }
//! ```
//!
-//! In `winnow`, we call this type of parser a [`tag`]. See [`token`] for additional individual
+//! In `winnow`, we call this type of parser a [`tag`]. See [`token`] for additional individual
//! and token-slice parsers.
//!
//! ## Character Classes
//!
-//! Selecting a single `char` or a [`tag`] is fairly limited. Sometimes, you will want to select one of several
-//! `chars` of a specific class, like digits. For this, we use the [`one_of`] parer:
+//! Selecting a single `char` or a [`tag`] is fairly limited. Sometimes, you will want to select one of several
+//! `chars` of a specific class, like digits. For this, we use the [`one_of`] parser:
//!
//! ```rust
//! # use winnow::Parser;
@@ -207,7 +207,7 @@
//! }
//! ```
//!
-//! We could simplify this further with by using one of the built-in character classes, [`hex_digit1`]:
+//! We could simplify this further by using one of the built-in character classes, [`hex_digit1`]:
//! ```rust
//! # use winnow::Parser;
//! # use winnow::PResult;
diff --git a/vendor/winnow/src/_tutorial/chapter_3.rs b/vendor/winnow/src/_tutorial/chapter_3.rs
index 4dfdc31e4..e3f86b501 100644
--- a/vendor/winnow/src/_tutorial/chapter_3.rs
+++ b/vendor/winnow/src/_tutorial/chapter_3.rs
@@ -179,7 +179,7 @@
//! ```
//!
//! > **Warning:** the above example is for illustrative purposes and relying on `Result::Ok` or
-//! > `Result::Err` can lead to incorrect behavior. This will be clarified in later when covering
+//! > `Result::Err` can lead to incorrect behavior. This will be clarified in later when covering
//! > [error handling][`chapter_6`#errmode]
//!
//! [`opt`] is a basic building block for correctly handling retrying parsing:
@@ -296,8 +296,8 @@
//! > **Note:** [`success`] and [`fail`] are parsers that might be useful in the `else` case.
//!
//! Sometimes a giant if/else-if ladder can be slow and you'd rather have a `match` statement for
-//! branches of your parser that have unique prefixes. In this case, you can use the
-//! [`dispatch`][crate::combinator::dispatch] macro:
+//! branches of your parser that have unique prefixes. In this case, you can use the
+//! [`dispatch`] macro:
//!
//! ```rust
//! # use winnow::prelude::*;
diff --git a/vendor/winnow/src/_tutorial/chapter_4.rs b/vendor/winnow/src/_tutorial/chapter_4.rs
index 59aa7ee87..328a64843 100644
--- a/vendor/winnow/src/_tutorial/chapter_4.rs
+++ b/vendor/winnow/src/_tutorial/chapter_4.rs
@@ -10,9 +10,6 @@
//! All we need to do for our parser to return a different type is to change
//! the type parameter of [`PResult`] to the desired return type.
//! For example, to return a `usize`, return a `PResult<usize>`.
-//! Recall that the type parameter of the `PResult` is the input
-//! type, so even if you're returning something different, if your input
-//! is a `&str`, the type argument of `PResult` should be also.
//!
//! One winnow-native way of doing a type conversion is to use the
//! [`Parser::parse_to`] combinator
diff --git a/vendor/winnow/src/_tutorial/chapter_5.rs b/vendor/winnow/src/_tutorial/chapter_5.rs
index ffd8a29ce..8aa719b98 100644
--- a/vendor/winnow/src/_tutorial/chapter_5.rs
+++ b/vendor/winnow/src/_tutorial/chapter_5.rs
@@ -136,18 +136,18 @@
//! # }
//! ```
//!
-//! You'll notice that the above allows trailing `,` when we intended to not support that. We can
-//! easily fix this by using [`separated0`]:
+//! You'll notice that the above allows trailing `,` when we intended to not support that. We can
+//! easily fix this by using [`separated`]:
//! ```rust
//! # use winnow::prelude::*;
//! # use winnow::token::take_while;
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
-//! use winnow::combinator::separated0;
+//! use winnow::combinator::separated;
//!
//! fn parse_list(input: &mut &str) -> PResult<Vec<usize>> {
-//! separated0(parse_digits, ",").parse_next(input)
+//! separated(0.., parse_digits, ",").parse_next(input)
//! }
//!
//! // ...
@@ -200,7 +200,7 @@
//! ```
//!
//! If you look closely at [`repeat`], it isn't collecting directly into a [`Vec`] but
-//! [`Accumulate`] to gather the results. This let's us make more complex parsers than we did in
+//! [`Accumulate`] to gather the results. This lets us make more complex parsers than we did in
//! [`chapter_2`] by accumulating the results into a `()` and [`recognize`][Parser::recognize]-ing the captured input:
//! ```rust
//! # use winnow::prelude::*;
@@ -208,14 +208,14 @@
//! # use winnow::combinator::dispatch;
//! # use winnow::token::take;
//! # use winnow::combinator::fail;
-//! # use winnow::combinator::separated0;
+//! # use winnow::combinator::separated;
//! #
//! fn recognize_list<'s>(input: &mut &'s str) -> PResult<&'s str> {
//! parse_list.recognize().parse_next(input)
//! }
//!
//! fn parse_list(input: &mut &str) -> PResult<()> {
-//! separated0(parse_digits, ",").parse_next(input)
+//! separated(0.., parse_digits, ",").parse_next(input)
//! }
//!
//! # fn parse_digits(input: &mut &str) -> PResult<usize> {
@@ -272,7 +272,7 @@ use super::chapter_2;
use super::chapter_3;
use crate::combinator;
use crate::combinator::repeat;
-use crate::combinator::separated0;
+use crate::combinator::separated;
use crate::stream::Accumulate;
use crate::Parser;
use std::vec::Vec;
diff --git a/vendor/winnow/src/_tutorial/chapter_6.rs b/vendor/winnow/src/_tutorial/chapter_6.rs
index 9f4230942..0d54e1505 100644
--- a/vendor/winnow/src/_tutorial/chapter_6.rs
+++ b/vendor/winnow/src/_tutorial/chapter_6.rs
@@ -72,13 +72,13 @@
//! ```rust
//! # use winnow::error::ErrorKind;
//! # use winnow::error::ErrMode;
-//! pub type OResult<O, E = ErrorKind> = Result<O, ErrMode<E>>;
+//! pub type PResult<O, E = ErrorKind> = Result<O, ErrMode<E>>;
//! ```
//! [`PResult`] is just a fancy wrapper around `Result` that wraps our error in an [`ErrMode`]
//! type.
//!
//! [`ErrMode`] is an enum with [`Backtrack`] and [`Cut`] variants (ignore [`Incomplete`] as its only
-//! relevant for [streaming][_topic::stream]). By default, errors are [`Backtrack`], meaning that
+//! relevant for [streaming][_topic::stream]). By default, errors are [`Backtrack`], meaning that
//! other parsing branches will be attempted on failure, like the next case of an [`alt`]. [`Cut`]
//! shortcircuits all other branches, immediately reporting the error.
//!
diff --git a/vendor/winnow/src/_tutorial/mod.rs b/vendor/winnow/src/_tutorial/mod.rs
index 224fe6a80..2a4bd61f7 100644
--- a/vendor/winnow/src/_tutorial/mod.rs
+++ b/vendor/winnow/src/_tutorial/mod.rs
@@ -1,6 +1,7 @@
//! # Tutorial
//!
//! Table of Contents
+#![allow(clippy::std_instead_of_core)]
pub mod chapter_0;
pub mod chapter_1;
diff --git a/vendor/winnow/src/ascii/mod.rs b/vendor/winnow/src/ascii/mod.rs
index 8b3119fbf..6221efc2d 100644
--- a/vendor/winnow/src/ascii/mod.rs
+++ b/vendor/winnow/src/ascii/mod.rs
@@ -15,12 +15,41 @@ use crate::error::{ErrMode, ErrorKind, Needed};
use crate::stream::{AsBStr, AsChar, ParseSlice, Stream, StreamIsPartial};
use crate::stream::{Compare, CompareResult};
use crate::token::one_of;
-use crate::token::take_till0;
+use crate::token::take_till;
use crate::token::take_while;
use crate::trace::trace;
use crate::PResult;
use crate::Parser;
+/// Mark a value as case-insensitive for ASCII characters
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}};
+/// # use winnow::ascii::Caseless;
+///
+/// fn parser<'s>(s: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
+/// Caseless("hello").parse_next(s)
+/// }
+///
+/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser.parse_peek("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser.parse_peek("HeLlo, World!"), Ok((", World!", "HeLlo")));
+/// assert_eq!(parser.parse_peek("Some"), Err(ErrMode::Backtrack(InputError::new("Some", ErrorKind::Tag))));
+/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
+/// ```
+#[derive(Copy, Clone, Debug)]
+pub struct Caseless<T>(pub T);
+
+impl Caseless<&str> {
+ /// Get the byte-representation of this case-insensitive value
+ #[inline(always)]
+ pub fn as_bytes(&self) -> Caseless<&[u8]> {
+ Caseless(self.0.as_bytes())
+ }
+}
+
/// Recognizes the string `"\r\n"`.
///
/// *Complete version*: Will return an error if there's not enough input data.
@@ -123,7 +152,7 @@ where
I: Compare<&'static str>,
<I as Stream>::Token: AsChar + Clone,
{
- let res = take_till0(('\r', '\n')).parse_next(input)?;
+ let res = take_till(0.., ('\r', '\n')).parse_next(input)?;
if input.compare("\r") == CompareResult::Ok {
let comp = input.compare("\r\n");
match comp {
@@ -423,7 +452,7 @@ where
///
/// ## Parsing an integer
///
-/// You can use `digit1` in combination with [`Parser::try_map`][crate::Parser::try_map] to parse an integer:
+/// You can use `digit1` in combination with [`Parser::try_map`] to parse an integer:
///
/// ```
/// # use winnow::prelude::*;
@@ -965,6 +994,7 @@ impl Uint for u128 {
}
}
+/// Deprecated since v0.15.17
impl Uint for i8 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -974,6 +1004,7 @@ impl Uint for i8 {
}
}
+/// Deprecated since v0.15.17
impl Uint for i16 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -983,6 +1014,7 @@ impl Uint for i16 {
}
}
+/// Deprecated since v0.15.17
impl Uint for i32 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -992,6 +1024,7 @@ impl Uint for i32 {
}
}
+/// Deprecated since v0.15.17
impl Uint for i64 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -1001,6 +1034,7 @@ impl Uint for i64 {
}
}
+/// Deprecated since v0.15.17
impl Uint for i128 {
fn checked_mul(self, by: u8, _: sealed::SealedMarker) -> Option<Self> {
self.checked_mul(by as Self)
@@ -1318,6 +1352,7 @@ where
}
#[allow(clippy::trait_duplication_in_bounds)] // HACK: clippy 1.64.0 bug
+#[allow(deprecated)]
fn recognize_float_or_exceptions<I, E: ParserError<I>>(
input: &mut I,
) -> PResult<<I as Stream>::Slice, E>
diff --git a/vendor/winnow/src/binary/bits/mod.rs b/vendor/winnow/src/binary/bits/mod.rs
index b11ba43c7..16a0f6464 100644
--- a/vendor/winnow/src/binary/bits/mod.rs
+++ b/vendor/winnow/src/binary/bits/mod.rs
@@ -157,7 +157,7 @@ where
/// }
///
/// fn parser(input: (Stream<'_>, usize), count: usize)-> IResult<(Stream<'_>, usize), u8> {
-/// take(count).parse_peek(input)
+/// take(count).parse_peek(input)
/// }
///
/// // Consumes 0 bits, returns 0
diff --git a/vendor/winnow/src/combinator/core.rs b/vendor/winnow/src/combinator/core.rs
index d784b4e9e..2a92d64b7 100644
--- a/vendor/winnow/src/combinator/core.rs
+++ b/vendor/winnow/src/combinator/core.rs
@@ -331,7 +331,7 @@ where
/// Call the iterator's [`ParserIterator::finish`] method to get the remaining input if successful,
/// or the error value if we encountered an error.
///
-/// On [`ErrMode::Backtrack`], iteration will stop. To instead chain an error up, see [`cut_err`].
+/// On [`ErrMode::Backtrack`], iteration will stop. To instead chain an error up, see [`cut_err`].
///
/// # Example
///
diff --git a/vendor/winnow/src/combinator/mod.rs b/vendor/winnow/src/combinator/mod.rs
index ec68e48e2..542b156a2 100644
--- a/vendor/winnow/src/combinator/mod.rs
+++ b/vendor/winnow/src/combinator/mod.rs
@@ -6,72 +6,71 @@
//!
//! Those are used to recognize the lowest level elements of your grammar, like, "here is a dot", or "here is an big endian integer".
//!
-//! | combinator | usage | input | output | comment |
-//! |---|---|---|---|---|
-//! | [`one_of`][crate::token::one_of] | `one_of(['a', 'b', 'c'])` | `"abc"` | `Ok(("bc", 'a'))` |Matches one of the provided characters (works with non ASCII characters too)|
-//! | [`none_of`][crate::token::none_of] | `none_of(['a', 'b', 'c'])` | `"xyab"` | `Ok(("yab", 'x'))` |Matches anything but the provided characters|
-//! | [`tag`][crate::token::tag] | `"hello"` | `"hello world"` | `Ok((" world", "hello"))` |Recognizes a specific suite of characters or bytes|
-//! | [`tag_no_case`][crate::token::tag_no_case] | `tag_no_case("hello")` | `"HeLLo World"` | `Ok((" World", "HeLLo"))` |Case insensitive comparison. Note that case insensitive comparison is not well defined for unicode, and that you might have bad surprises|
-//! | [`take`][crate::token::take] | `take(4)` | `"hello"` | `Ok(("o", "hell"))` |Takes a specific number of bytes or characters|
-//! | [`take_while`][crate::token::take_while] | `take_while(0.., is_alphabetic)` | `"abc123"` | `Ok(("123", "abc"))` |Returns the longest list of bytes for which the provided pattern matches.|
-//! | [`take_till0`][crate::token::take_till0] | `take_till0(is_alphabetic)` | `"123abc"` | `Ok(("abc", "123"))` |Returns the longest list of bytes or characters until the provided pattern matches. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till(f)` is equivalent to `take_while(0.., \|c\| !f(c))`|
-//! | [`take_until0`][crate::token::take_until0] | `take_until0("world")` | `"Hello world"` | `Ok(("world", "Hello "))` |Returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character|
+//! | combinator | usage | input | new input | output | comment |
+//! |---|---|---|---|---|---|
+//! | [`one_of`][crate::token::one_of] | `one_of(['a', 'b', 'c'])` | `"abc"` | `"bc"` | `Ok('a')` |Matches one of the provided characters (works with non ASCII characters too)|
+//! | [`none_of`][crate::token::none_of] | `none_of(['a', 'b', 'c'])` | `"xyab"` | `"yab"` | `Ok('x')` |Matches anything but the provided characters|
+//! | [`tag`][crate::token::tag] | `"hello"` | `"hello world"` | `" world"` | `Ok("hello")` |Recognizes a specific suite of characters or bytes (see also [`Caseless`][crate::ascii::Caseless])|
+//! | [`take`][crate::token::take] | `take(4)` | `"hello"` | `"o"` | `Ok("hell")` |Takes a specific number of bytes or characters|
+//! | [`take_while`][crate::token::take_while] | `take_while(0.., is_alphabetic)` | `"abc123"` | `"123"` | `Ok("abc")` |Returns the longest list of bytes for which the provided pattern matches.|
+//! | [`take_till0`][crate::token::take_till0] | `take_till0(is_alphabetic)` | `"123abc"` | `"abc"` | `Ok("123")` |Returns the longest list of bytes or characters until the provided pattern matches. `take_till1` does the same, but must return at least one character. This is the reverse behaviour from `take_while`: `take_till(f)` is equivalent to `take_while(0.., \|c\| !f(c))`|
+//! | [`take_until0`][crate::token::take_until0] | `take_until0("world")` | `"Hello world"` | `"world"` | `Ok("Hello ")` |Returns the longest list of bytes or characters until the provided tag is found. `take_until1` does the same, but must return at least one character|
//!
//! ## Choice combinators
//!
-//! | combinator | usage | input | output | comment |
-//! |---|---|---|---|---|
-//! | [`alt`][crate::combinator::alt] | `alt(("ab", "cd"))` | `"cdef"` | `Ok(("ef", "cd"))` |Try a list of parsers and return the result of the first successful one|
-//! | [`dispatch`][crate::combinator::dispatch] | \- | \- | \- | `match` for parsers |
-//! | [`permutation`][crate::combinator::permutation] | `permutation(("ab", "cd", "12"))` | `"cd12abc"` | `Ok(("c", ("ab", "cd", "12"))` |Succeeds when all its child parser have succeeded, whatever the order|
+//! | combinator | usage | input | new input | output | comment |
+//! |---|---|---|---|---|---|
+//! | [`alt`] | `alt(("ab", "cd"))` | `"cdef"` | `"ef"` | `Ok("cd")` |Try a list of parsers and return the result of the first successful one|
+//! | [`dispatch`] | \- | \- | \- | \- | `match` for parsers |
+//! | [`permutation`] | `permutation(("ab", "cd", "12"))` | `"cd12abc"` | `"c"` | `Ok(("ab", "cd", "12"))` |Succeeds when all its child parser have succeeded, whatever the order|
//!
//! ## Sequence combinators
//!
-//! | combinator | usage | input | output | comment |
-//! |---|---|---|---|---|
-//! | [`(...)` (tuples)][crate::Parser] | `("ab", "XY", take(1))` | `"abXYZ!"` | `Ok(("!", ("ab", "XY", "Z")))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
-//! | [`delimited`] | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `Ok(("cd", "ab"))` ||
-//! | [`preceded`] | `preceded("ab", "XY")` | `"abXYZ"` | `Ok(("Z", "XY"))` ||
-//! | [`terminated`] | `terminated("ab", "XY")` | `"abXYZ"` | `Ok(("Z", "ab"))` ||
-//! | [`separated_pair`] | `separated_pair("hello", char(','), "world")` | `"hello,world!"` | `Ok(("!", ("hello", "world")))` ||
+//! | combinator | usage | input | new input | output | comment |
+//! |---|---|---|---|---|---|
+//! | [`(...)` (tuples)][crate::Parser] | `("ab", "XY", take(1))` | `"abXYZ!"` | `"!"` | `Ok(("ab", "XY", "Z"))` |Chains parsers and assemble the sub results in a tuple. You can use as many child parsers as you can put elements in a tuple|
+//! | [`delimited`] | `delimited(char('('), take(2), char(')'))` | `"(ab)cd"` | `"cd"` | `Ok("ab")` ||
+//! | [`preceded`] | `preceded("ab", "XY")` | `"abXYZ"` | `"Z"` | `Ok("XY")` ||
+//! | [`terminated`] | `terminated("ab", "XY")` | `"abXYZ"` | `"Z"` | `Ok("ab")` ||
+//! | [`separated_pair`] | `separated_pair("hello", char(','), "world")` | `"hello,world!"` | `"!"` | `Ok(("hello", "world"))` ||
//!
//! ## Applying a parser multiple times
//!
-//! | combinator | usage | input | output | comment |
-//! |---|---|---|---|---|
-//! | [`repeat`][crate::combinator::repeat] | `repeat(1..=3, "ab")` | `"ababc"` | `Ok(("c", vec!["ab", "ab"]))` |Applies the parser between m and n times (n included) and returns the list of results in a Vec|
-//! | [`repeat_till0`][crate::combinator::repeat_till0] | `repeat_till0(tag( "ab" ), tag( "ef" ))` | `"ababefg"` | `Ok(("g", (vec!["ab", "ab"], "ef")))` |Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second|
-//! | [`separated0`][crate::combinator::separated0] | `separated0("ab", ",")` | `"ab,ab,ab."` | `Ok((".", vec!["ab", "ab", "ab"]))` |`separated1` works like `separated0` but must returns at least one element|
-//! | [`fold_repeat`][crate::combinator::fold_repeat] | `fold_repeat(1..=2, be_u8, \|\| 0, \|acc, item\| acc + item)` | `[1, 2, 3]` | `Ok(([3], 3))` |Applies the parser between m and n times (n included) and folds the list of return value|
+//! | combinator | usage | input | new input | output | comment |
+//! |---|---|---|---|---|---|
+//! | [`repeat`] | `repeat(1..=3, "ab")` | `"ababc"` | `"c"` | `Ok(vec!["ab", "ab"])` |Applies the parser between m and n times (n included) and returns the list of results in a Vec|
+//! | [`repeat_till0`] | `repeat_till0(tag( "ab" ), tag( "ef" ))` | `"ababefg"` | `"g"` | `Ok((vec!["ab", "ab"], "ef"))` |Applies the first parser until the second applies. Returns a tuple containing the list of results from the first in a Vec and the result of the second|
+//! | [`separated`] | `separated(1..=3, "ab", ",")` | `"ab,ab,ab."` | `"."` | `Ok(vec!["ab", "ab", "ab"])` |Applies the parser and separator between m and n times (n included) and returns the list of results in a Vec|
+//! | [`fold_repeat`] | `fold_repeat(1..=2, be_u8, \|\| 0, \|acc, item\| acc + item)` | `[1, 2, 3]` | `[3]` | `Ok(3)` |Applies the parser between m and n times (n included) and folds the list of return value|
//!
//! ## Partial related
//!
-//! - [`eof`][eof]: Returns its input if it is at the end of input data
+//! - [`eof`]: Returns its input if it is at the end of input data
//! - [`Parser::complete_err`]: Replaces an `Incomplete` returned by the child parser with an `Backtrack`
//!
//! ## Modifiers
//!
-//! - [`cond`][cond]: Conditional combinator. Wraps another parser and calls it if the condition is met
-//! - [`Parser::flat_map`][crate::Parser::flat_map]: method to map a new parser from the output of the first parser, then apply that parser over the rest of the input
-//! - [`Parser::value`][crate::Parser::value]: method to replace the result of a parser
-//! - [`Parser::map`][crate::Parser::map]: method to map a function on the result of a parser
-//! - [`Parser::and_then`][crate::Parser::and_then]: Applies a second parser over the output of the first one
-//! - [`Parser::verify_map`][Parser::verify_map]: Maps a function returning an `Option` on the output of a parser
-//! - [`Parser::try_map`][Parser::try_map]: Maps a function returning a `Result` on the output of a parser
-//! - [`Parser::parse_to`][crate::Parser::parse_to]: Apply [`std::str::FromStr`] to the output of the parser
-//! - [`not`][not]: Returns a result only if the embedded parser returns `Backtrack` or `Incomplete`. Does not consume the input
-//! - [`opt`][opt]: Make the underlying parser optional
-//! - [`peek`][peek]: Returns a result without consuming the input
-//! - [`Parser::recognize`][Parser::recognize]: If the child parser was successful, return the consumed input as the produced value
-//! - [`Parser::with_recognized`][Parser::with_recognized]: If the child parser was successful, return a tuple of the consumed input and the produced output.
-//! - [`Parser::span`][Parser::span]: If the child parser was successful, return the location of the consumed input as the produced value
-//! - [`Parser::with_span`][Parser::with_span]: If the child parser was successful, return a tuple of the location of the consumed input and the produced output.
+//! - [`cond`]: Conditional combinator. Wraps another parser and calls it if the condition is met
+//! - [`Parser::flat_map`]: method to map a new parser from the output of the first parser, then apply that parser over the rest of the input
+//! - [`Parser::value`]: method to replace the result of a parser
+//! - [`Parser::map`]: method to map a function on the result of a parser
+//! - [`Parser::and_then`]: Applies a second parser over the output of the first one
+//! - [`Parser::verify_map`]: Maps a function returning an `Option` on the output of a parser
+//! - [`Parser::try_map`]: Maps a function returning a `Result` on the output of a parser
+//! - [`Parser::parse_to`]: Apply [`std::str::FromStr`] to the output of the parser
+//! - [`not`]: Returns a result only if the embedded parser returns `Backtrack` or `Incomplete`. Does not consume the input
+//! - [`opt`]: Make the underlying parser optional
+//! - [`peek`]: Returns a result without consuming the input
+//! - [`Parser::recognize`]: If the child parser was successful, return the consumed input as the produced value
+//! - [`Parser::with_recognized`]: If the child parser was successful, return a tuple of the consumed input and the produced output.
+//! - [`Parser::span`]: If the child parser was successful, return the location of the consumed input as the produced value
+//! - [`Parser::with_span`]: If the child parser was successful, return a tuple of the location of the consumed input and the produced output.
//! - [`Parser::verify`]: Returns the result of the child parser if it satisfies a verification function
//!
//! ## Error management and debugging
//!
//! - [`cut_err`]: Commit the parse result, disallowing alternative parsers from being attempted
-//! - [`backtrack_err`]: Attemmpts a parse, allowing alternative parsers to be attempted despite
+//! - [`backtrack_err`]: Attempts a parse, allowing alternative parsers to be attempted despite
//! use of `cut_err`
//! - [`Parser::context`]: Add context to the error if the parser fails
//! - [`trace`][crate::trace::trace]: Print the parse state with the `debug` feature flag
@@ -79,8 +78,8 @@
//!
//! ## Remaining combinators
//!
-//! - [`success`][success]: Returns a value without consuming any input, always succeeds
-//! - [`fail`][fail]: Inversion of `success`. Always fails.
+//! - [`success`]: Returns a value without consuming any input, always succeeds
+//! - [`fail`]: Inversion of `success`. Always fails.
//! - [`Parser::by_ref`]: Allow moving `&mut impl Parser` into other parsers
//!
//! ## Text parsing
@@ -91,7 +90,7 @@
//! - [`line_ending`][crate::ascii::line_ending]: Recognizes an end of line (both `\n` and `\r\n`)
//! - [`newline`][crate::ascii::newline]: Matches a newline character `\n`
//! - [`not_line_ending`][crate::ascii::not_line_ending]: Recognizes a string of any char except `\r` or `\n`
-//! - [`rest`][rest]: Return the remaining input
+//! - [`rest`]: Return the remaining input
//!
//! - [`alpha0`][crate::ascii::alpha0]: Recognizes zero or more lowercase and uppercase alphabetic characters: `[a-zA-Z]`. [`alpha1`][crate::ascii::alpha1] does the same but returns at least one character
//! - [`alphanumeric0`][crate::ascii::alphanumeric0]: Recognizes zero or more numerical and alphabetic characters: `[0-9a-zA-Z]`. [`alphanumeric1`][crate::ascii::alphanumeric1] does the same but returns at least one character
diff --git a/vendor/winnow/src/combinator/multi.rs b/vendor/winnow/src/combinator/multi.rs
index 1fdb7535b..d06362878 100644
--- a/vendor/winnow/src/combinator/multi.rs
+++ b/vendor/winnow/src/combinator/multi.rs
@@ -12,7 +12,7 @@ use crate::Parser;
/// [`Accumulate`] the output of a parser into a container, like `Vec`
///
-/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
@@ -28,7 +28,7 @@ use crate::Parser;
///
/// # Example
///
-/// Zero or more reptitions:
+/// Zero or more repetitions:
/// ```rust
/// # #[cfg(feature = "std")] {
/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
@@ -47,7 +47,7 @@ use crate::Parser;
/// # }
/// ```
///
-/// One or more reptitions:
+/// One or more repetitions:
/// ```rust
/// # #[cfg(feature = "std")] {
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
@@ -66,7 +66,7 @@ use crate::Parser;
/// # }
/// ```
///
-/// Fixed number of repeitions:
+/// Fixed number of repetitions:
/// ```rust
/// # #[cfg(feature = "std")] {
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
@@ -86,7 +86,7 @@ use crate::Parser;
/// # }
/// ```
///
-/// Arbitrary reptitions:
+/// Arbitrary repetitions:
/// ```rust
/// # #[cfg(feature = "std")] {
/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
@@ -201,6 +201,73 @@ where
}
}
+fn repeat_n_<I, O, C, E, F>(count: usize, f: &mut F, i: &mut I) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ F: Parser<I, O, E>,
+ E: ParserError<I>,
+{
+ let mut res = C::initial(Some(count));
+
+ for _ in 0..count {
+ match f.parse_next(i) {
+ Ok(o) => {
+ res.accumulate(o);
+ }
+ Err(e) => {
+ return Err(e.append(i, ErrorKind::Many));
+ }
+ }
+ }
+
+ Ok(res)
+}
+
+fn repeat_m_n_<I, O, C, E, F>(min: usize, max: usize, parse: &mut F, input: &mut I) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ F: Parser<I, O, E>,
+ E: ParserError<I>,
+{
+ if min > max {
+ return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
+ }
+
+ let mut res = C::initial(Some(min));
+ for count in 0..max {
+ let start = input.checkpoint();
+ let len = input.eof_offset();
+ match parse.parse_next(input) {
+ Ok(value) => {
+ // infinite loop check: the parser must always consume
+ if input.eof_offset() == len {
+ return Err(ErrMode::assert(
+ input,
+ "`repeat` parsers must always consume",
+ ));
+ }
+
+ res.accumulate(value);
+ }
+ Err(ErrMode::Backtrack(e)) => {
+ if count < min {
+ return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
+ } else {
+ input.reset(start);
+ return Ok(res);
+ }
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ }
+ }
+
+ Ok(res)
+}
+
/// [`Accumulate`] the output of parser `f` into a container, like `Vec`, until the parser `g`
/// produces a result.
///
@@ -269,9 +336,144 @@ where
})
}
-/// [`Accumulate`] the output of a parser, interleaed with `sep`
+/// [`Accumulate`] the output of a parser, interleaved with `sep`
///
-/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// [`cut_err`][crate::combinator::cut_err].
+///
+/// # Arguments
+/// * `range` The minimum and maximum number of iterations.
+/// * `parser` The parser that parses the elements of the list.
+/// * `sep` The parser that parses the separator between list elements.
+///
+/// **Warning:** If the separator parser accepts empty inputs
+/// (like `alpha0` or `digit0`), `separated` will return an error,
+/// to prevent going into an infinite loop.
+///
+/// # Example
+///
+/// Zero or more repetitions:
+/// ```rust
+/// # #[cfg(feature = "std")] {
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::combinator::separated;
+/// use winnow::token::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated(0.., "abc", "|").parse_peek(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
+/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![])));
+/// # }
+/// ```
+///
+/// One or more repetitions:
+/// ```rust
+/// # #[cfg(feature = "std")] {
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::combinator::separated;
+/// use winnow::token::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated(1.., "abc", "|").parse_peek(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("", vec!["abc", "abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
+/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(InputError::new("def|abc", ErrorKind::Tag))));
+/// # }
+/// ```
+///
+/// Fixed number of repetitions:
+/// ```rust
+/// # #[cfg(feature = "std")] {
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::combinator::separated;
+/// use winnow::token::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated(2, "abc", "|").parse_peek(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("|abc", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Err(ErrMode::Backtrack(InputError::new("123abc", ErrorKind::Tag))));
+/// assert_eq!(parser("abc|def"), Err(ErrMode::Backtrack(InputError::new("def", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
+/// assert_eq!(parser("def|abc"), Err(ErrMode::Backtrack(InputError::new("def|abc", ErrorKind::Tag))));
+/// # }
+/// ```
+///
+/// Arbitrary repetitions:
+/// ```rust
+/// # #[cfg(feature = "std")] {
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::combinator::separated;
+/// use winnow::token::tag;
+///
+/// fn parser(s: &str) -> IResult<&str, Vec<&str>> {
+/// separated(0..=2, "abc", "|").parse_peek(s)
+/// }
+///
+/// assert_eq!(parser("abc|abc|abc"), Ok(("|abc", vec!["abc", "abc"])));
+/// assert_eq!(parser("abc123abc"), Ok(("123abc", vec!["abc"])));
+/// assert_eq!(parser("abc|def"), Ok(("|def", vec!["abc"])));
+/// assert_eq!(parser(""), Ok(("", vec![])));
+/// assert_eq!(parser("def|abc"), Ok(("def|abc", vec![])));
+/// # }
+/// ```
+#[doc(alias = "sep_by")]
+#[doc(alias = "sep_by1")]
+#[doc(alias = "separated_list0")]
+#[doc(alias = "separated_list1")]
+#[doc(alias = "separated_m_n")]
+#[inline(always)]
+pub fn separated<I, O, C, O2, E, P, S>(
+ range: impl Into<Range>,
+ mut parser: P,
+ mut separator: S,
+) -> impl Parser<I, C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ P: Parser<I, O, E>,
+ S: Parser<I, O2, E>,
+ E: ParserError<I>,
+{
+ let Range {
+ start_inclusive,
+ end_inclusive,
+ } = range.into();
+ trace("separated", move |input: &mut I| {
+ match (start_inclusive, end_inclusive) {
+ (0, None) => separated0_(&mut parser, &mut separator, input),
+ (1, None) => separated1_(&mut parser, &mut separator, input),
+ (start, end) if Some(start) == end => {
+ separated_n_(start, &mut parser, &mut separator, input)
+ }
+ (start, end) => separated_m_n_(
+ start,
+ end.unwrap_or(usize::MAX),
+ &mut parser,
+ &mut separator,
+ input,
+ ),
+ }
+ })
+}
+
+/// [`Accumulate`] the output of a parser, interleaved with `sep`
+///
+/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
@@ -300,6 +502,7 @@ where
/// ```
#[doc(alias = "sep_by")]
#[doc(alias = "separated_list0")]
+#[deprecated(since = "0.5.19", note = "Replaced with `combinator::separated`")]
pub fn separated0<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E>
where
I: Stream,
@@ -309,56 +512,74 @@ where
E: ParserError<I>,
{
trace("separated0", move |i: &mut I| {
- let mut res = C::initial(None);
+ separated0_(&mut parser, &mut sep, i)
+ })
+}
- let start = i.checkpoint();
- match parser.parse_next(i) {
+fn separated0_<I, O, C, O2, E, P, S>(
+ parser: &mut P,
+ separator: &mut S,
+ input: &mut I,
+) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ P: Parser<I, O, E>,
+ S: Parser<I, O2, E>,
+ E: ParserError<I>,
+{
+ let mut acc = C::initial(None);
+
+ let start = input.checkpoint();
+ match parser.parse_next(input) {
+ Err(ErrMode::Backtrack(_)) => {
+ input.reset(start);
+ return Ok(acc);
+ }
+ Err(e) => return Err(e),
+ Ok(o) => {
+ acc.accumulate(o);
+ }
+ }
+
+ loop {
+ let start = input.checkpoint();
+ let len = input.eof_offset();
+ match separator.parse_next(input) {
Err(ErrMode::Backtrack(_)) => {
- i.reset(start);
- return Ok(res);
+ input.reset(start);
+ return Ok(acc);
}
Err(e) => return Err(e),
- Ok(o) => {
- res.accumulate(o);
- }
- }
-
- loop {
- let start = i.checkpoint();
- let len = i.eof_offset();
- match sep.parse_next(i) {
- Err(ErrMode::Backtrack(_)) => {
- i.reset(start);
- return Ok(res);
+ Ok(_) => {
+ // infinite loop check
+ if input.eof_offset() == len {
+ return Err(ErrMode::assert(
+ input,
+ "`separated` separator parser must always consume",
+ ));
}
- Err(e) => return Err(e),
- Ok(_) => {
- // infinite loop check: the parser must always consume
- if i.eof_offset() == len {
- return Err(ErrMode::assert(i, "sep parsers must always consume"));
- }
- match parser.parse_next(i) {
- Err(ErrMode::Backtrack(_)) => {
- i.reset(start);
- return Ok(res);
- }
- Err(e) => return Err(e),
- Ok(o) => {
- res.accumulate(o);
- }
+ match parser.parse_next(input) {
+ Err(ErrMode::Backtrack(_)) => {
+ input.reset(start);
+ return Ok(acc);
+ }
+ Err(e) => return Err(e),
+ Ok(o) => {
+ acc.accumulate(o);
}
}
}
}
- })
+ }
}
-/// [`Accumulate`] the output of a parser, interleaed with `sep`
+/// [`Accumulate`] the output of a parser, interleaved with `sep`
///
/// Fails if the element parser does not produce at least one element.$
///
-/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
@@ -387,6 +608,7 @@ where
/// ```
#[doc(alias = "sep_by1")]
#[doc(alias = "separated_list1")]
+#[deprecated(since = "0.5.19", note = "Replaced with `combinator::separated`")]
pub fn separated1<I, O, C, O2, E, P, S>(mut parser: P, mut sep: S) -> impl Parser<I, C, E>
where
I: Stream,
@@ -396,50 +618,209 @@ where
E: ParserError<I>,
{
trace("separated1", move |i: &mut I| {
- let mut res = C::initial(None);
+ separated1_(&mut parser, &mut sep, i)
+ })
+}
+
+fn separated1_<I, O, C, O2, E, P, S>(
+ parser: &mut P,
+ separator: &mut S,
+ input: &mut I,
+) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ P: Parser<I, O, E>,
+ S: Parser<I, O2, E>,
+ E: ParserError<I>,
+{
+ let mut acc = C::initial(None);
+
+ // Parse the first element
+ match parser.parse_next(input) {
+ Err(e) => return Err(e),
+ Ok(o) => {
+ acc.accumulate(o);
+ }
+ }
- // Parse the first element
- match parser.parse_next(i) {
+ loop {
+ let start = input.checkpoint();
+ let len = input.eof_offset();
+ match separator.parse_next(input) {
+ Err(ErrMode::Backtrack(_)) => {
+ input.reset(start);
+ return Ok(acc);
+ }
Err(e) => return Err(e),
- Ok(o) => {
- res.accumulate(o);
+ Ok(_) => {
+ // infinite loop check
+ if input.eof_offset() == len {
+ return Err(ErrMode::assert(
+ input,
+ "`separated` separator parser must always consume",
+ ));
+ }
+
+ match parser.parse_next(input) {
+ Err(ErrMode::Backtrack(_)) => {
+ input.reset(start);
+ return Ok(acc);
+ }
+ Err(e) => return Err(e),
+ Ok(o) => {
+ acc.accumulate(o);
+ }
+ }
}
}
+ }
+}
- loop {
- let start = i.checkpoint();
- let len = i.eof_offset();
- match sep.parse_next(i) {
- Err(ErrMode::Backtrack(_)) => {
- i.reset(start);
- return Ok(res);
+fn separated_n_<I, O, C, O2, E, P, S>(
+ count: usize,
+ parser: &mut P,
+ separator: &mut S,
+ input: &mut I,
+) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ P: Parser<I, O, E>,
+ S: Parser<I, O2, E>,
+ E: ParserError<I>,
+{
+ let mut acc = C::initial(Some(count));
+
+ if count == 0 {
+ return Ok(acc);
+ }
+
+ match parser.parse_next(input) {
+ Err(e) => {
+ return Err(e.append(input, ErrorKind::Many));
+ }
+ Ok(o) => {
+ acc.accumulate(o);
+ }
+ }
+
+ for _ in 1..count {
+ let len = input.eof_offset();
+ match separator.parse_next(input) {
+ Err(e) => {
+ return Err(e.append(input, ErrorKind::Many));
+ }
+ Ok(_) => {
+ // infinite loop check
+ if input.eof_offset() == len {
+ return Err(ErrMode::assert(
+ input,
+ "`separated` separator parser must always consume",
+ ));
}
- Err(e) => return Err(e),
- Ok(_) => {
- // infinite loop check: the parser must always consume
- if i.eof_offset() == len {
- return Err(ErrMode::assert(i, "sep parsers must always consume"));
+
+ match parser.parse_next(input) {
+ Err(e) => {
+ return Err(e.append(input, ErrorKind::Many));
+ }
+ Ok(o) => {
+ acc.accumulate(o);
}
+ }
+ }
+ }
+ }
- match parser.parse_next(i) {
- Err(ErrMode::Backtrack(_)) => {
- i.reset(start);
- return Ok(res);
- }
- Err(e) => return Err(e),
- Ok(o) => {
- res.accumulate(o);
+ Ok(acc)
+}
+
+fn separated_m_n_<I, O, C, O2, E, P, S>(
+ min: usize,
+ max: usize,
+ parser: &mut P,
+ separator: &mut S,
+ input: &mut I,
+) -> PResult<C, E>
+where
+ I: Stream,
+ C: Accumulate<O>,
+ P: Parser<I, O, E>,
+ S: Parser<I, O2, E>,
+ E: ParserError<I>,
+{
+ if min > max {
+ return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
+ }
+
+ let mut acc = C::initial(Some(min));
+
+ let start = input.checkpoint();
+ match parser.parse_next(input) {
+ Err(ErrMode::Backtrack(e)) => {
+ if min == 0 {
+ input.reset(start);
+ return Ok(acc);
+ } else {
+ return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
+ }
+ }
+ Err(e) => return Err(e),
+ Ok(o) => {
+ acc.accumulate(o);
+ }
+ }
+
+ for index in 1..max {
+ let start = input.checkpoint();
+ let len = input.eof_offset();
+ match separator.parse_next(input) {
+ Err(ErrMode::Backtrack(e)) => {
+ if index < min {
+ return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
+ } else {
+ input.reset(start);
+ return Ok(acc);
+ }
+ }
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(_) => {
+ // infinite loop check
+ if input.eof_offset() == len {
+ return Err(ErrMode::assert(
+ input,
+ "`separated` separator parser must always consume",
+ ));
+ }
+
+ match parser.parse_next(input) {
+ Err(ErrMode::Backtrack(e)) => {
+ if index < min {
+ return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
+ } else {
+ input.reset(start);
+ return Ok(acc);
}
}
+ Err(e) => {
+ return Err(e);
+ }
+ Ok(o) => {
+ acc.accumulate(o);
+ }
}
}
}
- })
+ }
+
+ Ok(acc)
}
/// Alternates between two parsers, merging the results (left associative)
///
-/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Example
@@ -506,7 +887,7 @@ where
/// Alternates between two parsers, merging the results (right associative)
///
-/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops when either parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Example
@@ -556,73 +937,6 @@ where
})
}
-fn repeat_m_n_<I, O, C, E, F>(min: usize, max: usize, parse: &mut F, input: &mut I) -> PResult<C, E>
-where
- I: Stream,
- C: Accumulate<O>,
- F: Parser<I, O, E>,
- E: ParserError<I>,
-{
- if min > max {
- return Err(ErrMode::Cut(E::from_error_kind(input, ErrorKind::Many)));
- }
-
- let mut res = C::initial(Some(min));
- for count in 0..max {
- let start = input.checkpoint();
- let len = input.eof_offset();
- match parse.parse_next(input) {
- Ok(value) => {
- // infinite loop check: the parser must always consume
- if input.eof_offset() == len {
- return Err(ErrMode::assert(
- input,
- "`repeat` parsers must always consume",
- ));
- }
-
- res.accumulate(value);
- }
- Err(ErrMode::Backtrack(e)) => {
- if count < min {
- return Err(ErrMode::Backtrack(e.append(input, ErrorKind::Many)));
- } else {
- input.reset(start);
- return Ok(res);
- }
- }
- Err(e) => {
- return Err(e);
- }
- }
- }
-
- Ok(res)
-}
-
-fn repeat_n_<I, O, C, E, F>(count: usize, f: &mut F, i: &mut I) -> PResult<C, E>
-where
- I: Stream,
- C: Accumulate<O>,
- F: Parser<I, O, E>,
- E: ParserError<I>,
-{
- let mut res = C::initial(Some(count));
-
- for _ in 0..count {
- match f.parse_next(i) {
- Ok(o) => {
- res.accumulate(o);
- }
- Err(e) => {
- return Err(e.append(i, ErrorKind::Many));
- }
- }
- }
-
- Ok(res)
-}
-
/// Repeats the embedded parser, filling the given slice with results.
///
/// This parser fails if the input runs out before the given slice is full.
@@ -675,7 +989,7 @@ where
/// Repeats the embedded parser `m..=n` times, calling `g` to gather the results
///
-/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
+/// This stops before `n` when the parser returns [`ErrMode::Backtrack`]. To instead chain an error up, see
/// [`cut_err`][crate::combinator::cut_err].
///
/// # Arguments
diff --git a/vendor/winnow/src/combinator/parser.rs b/vendor/winnow/src/combinator/parser.rs
index fb11adc15..c95f1f6f3 100644
--- a/vendor/winnow/src/combinator/parser.rs
+++ b/vendor/winnow/src/combinator/parser.rs
@@ -7,7 +7,7 @@ use crate::trace::trace;
use crate::trace::trace_result;
use crate::*;
-/// Implementation of [`Parser::by_ref`][Parser::by_ref]
+/// Implementation of [`Parser::by_ref`]
#[cfg_attr(nightly, warn(rustdoc::missing_doc_code_examples))]
pub struct ByRef<'p, P> {
p: &'p mut P,
diff --git a/vendor/winnow/src/combinator/tests.rs b/vendor/winnow/src/combinator/tests.rs
index 9d2b49d80..27fa53456 100644
--- a/vendor/winnow/src/combinator/tests.rs
+++ b/vendor/winnow/src/combinator/tests.rs
@@ -717,13 +717,13 @@ fn permutation_test() {
#[cfg(feature = "alloc")]
fn separated0_test() {
fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated0("abcd", ",").parse_peek(i)
+ separated(0.., "abcd", ",").parse_peek(i)
}
fn multi_empty(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated0("", ",").parse_peek(i)
+ separated(0.., "", ",").parse_peek(i)
}
fn multi_longsep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated0("abcd", "..").parse_peek(i)
+ separated(0.., "abcd", "..").parse_peek(i)
}
let a = &b"abcdef"[..];
@@ -773,7 +773,7 @@ fn separated0_test() {
#[cfg_attr(debug_assertions, should_panic)]
fn separated0_empty_sep_test() {
fn empty_sep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated0("abc", "").parse_peek(i)
+ separated(0.., "abc", "").parse_peek(i)
}
let i = &b"abcabc"[..];
@@ -792,10 +792,10 @@ fn separated0_empty_sep_test() {
#[cfg(feature = "alloc")]
fn separated1_test() {
fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated1("abcd", ",").parse_peek(i)
+ separated(1.., "abcd", ",").parse_peek(i)
}
fn multi_longsep(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
- separated1("abcd", "..").parse_peek(i)
+ separated(1.., "abcd", "..").parse_peek(i)
}
let a = &b"abcdef"[..];
@@ -840,6 +840,47 @@ fn separated1_test() {
#[test]
#[cfg(feature = "alloc")]
+fn separated_test() {
+ fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
+ separated(2..=4, "abcd", ",").parse_peek(i)
+ }
+
+ let a = &b"abcd,ef"[..];
+ let b = &b"abcd,abcd,efgh"[..];
+ let c = &b"abcd,abcd,abcd,abcd,efgh"[..];
+ let d = &b"abcd,abcd,abcd,abcd,abcd,efgh"[..];
+ let e = &b"abcd,ab"[..];
+
+ assert_eq!(
+ multi(Partial::new(a)),
+ Err(ErrMode::Backtrack(error_position!(
+ &Partial::new(&b"ef"[..]),
+ ErrorKind::Tag
+ )))
+ );
+ let res1 = vec![&b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(
+ multi(Partial::new(b)),
+ Ok((Partial::new(&b",efgh"[..]), res1))
+ );
+ let res2 = vec![&b"abcd"[..], &b"abcd"[..], &b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(
+ multi(Partial::new(c)),
+ Ok((Partial::new(&b",efgh"[..]), res2))
+ );
+ let res3 = vec![&b"abcd"[..], &b"abcd"[..], &b"abcd"[..], &b"abcd"[..]];
+ assert_eq!(
+ multi(Partial::new(d)),
+ Ok((Partial::new(&b",abcd,efgh"[..]), res3))
+ );
+ assert_eq!(
+ multi(Partial::new(e)),
+ Err(ErrMode::Incomplete(Needed::new(2)))
+ );
+}
+
+#[test]
+#[cfg(feature = "alloc")]
fn repeat0_test() {
fn multi(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, Vec<&[u8]>> {
repeat(0.., "abcd").parse_peek(i)
diff --git a/vendor/winnow/src/error.rs b/vendor/winnow/src/error.rs
index 449bebc55..fd7d94695 100644
--- a/vendor/winnow/src/error.rs
+++ b/vendor/winnow/src/error.rs
@@ -4,12 +4,12 @@
//! - Accumulate more [context][Parser::context] as the error goes up the parser chain
//! - Distinguish between [recoverable errors,
//! unrecoverable errors, and more data is needed][ErrMode]
-//! - Have a very low overhead, as errors are often discarded by the calling parser (examples: `many0`, `alt`)
+//! - Have a very low overhead, as errors are often discarded by the calling parser (examples: `repeat`, `alt`)
//! - Can be modified according to the user's needs, because some languages need a lot more information
//! - Help thread-through the [stream][crate::stream]
//!
//! To abstract these needs away from the user, generally `winnow` parsers use the [`PResult`]
-//! alias, rather than [`Result`][std::result::Result]. [`Parser::parse`] is a top-level operation
+//! alias, rather than [`Result`]. [`Parser::parse`] is a top-level operation
//! that can help convert to a `Result` for integrating with your application's error reporting.
//!
//! Error types include:
@@ -30,26 +30,29 @@ use crate::stream::Stream;
#[allow(unused_imports)] // Here for intra-doc links
use crate::Parser;
-/// Holds the result of [`Parser`]
+/// For use with [`Parser::parse_peek`] which allows the input stream to be threaded through a
+/// parser.
///
/// - `Ok((I, O))` is the remaining [input][crate::stream] and the parsed value
/// - [`Err(ErrMode<E>)`][ErrMode] is the error along with how to respond to it
///
/// By default, the error type (`E`) is [`InputError`]
///
-/// [`Parser::parse`] is a top-level operation that can help convert to a `Result` for integrating
-/// with your application's error reporting.
+/// When integrating into the result of the application, see
+/// - [`Parser::parse`]
+/// - [`ErrMode::into_inner`]
pub type IResult<I, O, E = InputError<I>> = PResult<(I, O), E>;
-/// Holds the result of [`Parser`]
+/// For use with [`Parser::parse_next`]
///
/// - `Ok(O)` is the parsed value
/// - [`Err(ErrMode<E>)`][ErrMode] is the error along with how to respond to it
///
-/// By default, the error type (`E`) is [`ErrorKind`].
+/// By default, the error type (`E`) is [`ContextError`].
///
-/// [`Parser::parse`] is a top-level operation that can help convert to a `Result` for integrating
-/// with your application's error reporting.
+/// When integrating into the result of the application, see
+/// - [`Parser::parse`]
+/// - [`ErrMode::into_inner`]
pub type PResult<O, E = ContextError> = Result<O, ErrMode<E>>;
/// Contains information on needed data if a parser returned `Incomplete`
@@ -97,7 +100,7 @@ pub enum ErrMode<E> {
///
/// More data needs to be buffered before retrying the parse.
///
- /// This must only be set when the [`Stream`][crate::stream::Stream] is [partial][`crate::stream::StreamIsPartial`], like with
+ /// This must only be set when the [`Stream`] is [partial][`crate::stream::StreamIsPartial`], like with
/// [`Partial`][crate::Partial]
///
/// Convert this into an `Backtrack` with [`Parser::complete_err`]
@@ -106,7 +109,7 @@ pub enum ErrMode<E> {
///
/// For example, a parser for json values might include a
/// [`dec_uint`][crate::ascii::dec_uint] as one case in an [`alt`][crate::combinator::alt]
- /// combiantor. If it fails, the next case should be tried.
+ /// combinator. If it fails, the next case should be tried.
Backtrack(E),
/// The parser had an unrecoverable error.
///
@@ -877,7 +880,7 @@ where
#[cfg(feature = "std")]
impl<I, C> TreeError<I, C>
where
- I: Clone + std::fmt::Display,
+ I: Clone + crate::lib::std::fmt::Display,
C: fmt::Display,
{
fn write(&self, f: &mut fmt::Formatter<'_>, indent: usize) -> fmt::Result {
@@ -1179,6 +1182,9 @@ impl<I, E> ParseError<I, E> {
}
/// The location in [`ParseError::input`] where parsing failed
+ ///
+ /// **Note:** This is an offset, not an index, and may point to the end of input
+ /// (`input.len()`) on eof errors.
#[inline]
pub fn offset(&self) -> usize {
self.offset
@@ -1219,21 +1225,21 @@ where
writeln!(f, "parse error at line {}, column {}", line_num, col_num)?;
// |
- for _ in 0..=gutter {
+ for _ in 0..gutter {
write!(f, " ")?;
}
- writeln!(f, "|")?;
+ writeln!(f, " |")?;
// 1 | 00:32:00.a999999
write!(f, "{} | ", line_num)?;
writeln!(f, "{}", String::from_utf8_lossy(content))?;
// | ^
- for _ in 0..=gutter {
+ for _ in 0..gutter {
write!(f, " ")?;
}
- write!(f, "|")?;
- for _ in 0..=col_idx {
+ write!(f, " | ")?;
+ for _ in 0..col_idx {
write!(f, " ")?;
}
// The span will be empty at eof, so we need to make sure we always print at least
@@ -1246,7 +1252,7 @@ where
} else {
let content = input;
writeln!(f, "{}", String::from_utf8_lossy(content))?;
- for _ in 0..=span_start {
+ for _ in 0..span_start {
write!(f, " ")?;
}
// The span will be empty at eof, so we need to make sure we always print at least
@@ -1284,10 +1290,9 @@ fn translate_position(input: &[u8], index: usize) -> (usize, usize) {
None => 0,
};
let line = input[0..line_start].iter().filter(|b| **b == b'\n').count();
- let line = line;
// HACK: This treats byte offset and column offsets the same
- let column = std::str::from_utf8(&input[line_start..=index])
+ let column = crate::lib::std::str::from_utf8(&input[line_start..=index])
.map(|s| s.chars().count() - 1)
.unwrap_or_else(|_| index - line_start);
let column = column + column_offset;
@@ -1297,6 +1302,27 @@ fn translate_position(input: &[u8], index: usize) -> (usize, usize) {
#[cfg(test)]
#[cfg(feature = "std")]
+mod test_parse_error {
+ use super::*;
+
+ #[test]
+ fn single_line() {
+ let mut input = "0xZ123";
+ let start = input.checkpoint();
+ let _ = input.next_token().unwrap();
+ let _ = input.next_token().unwrap();
+ let inner = InputError::new(input, ErrorKind::Slice);
+ let error = ParseError::new(input, start, inner);
+ let expected = "\
+0xZ123
+ ^
+slice error starting at: Z123";
+ assert_eq!(error.to_string(), expected);
+ }
+}
+
+#[cfg(test)]
+#[cfg(feature = "std")]
mod test_translate_position {
use super::*;
diff --git a/vendor/winnow/src/lib.rs b/vendor/winnow/src/lib.rs
index 5614b7f11..4a21b9e11 100644
--- a/vendor/winnow/src/lib.rs
+++ b/vendor/winnow/src/lib.rs
@@ -49,6 +49,7 @@
#![cfg_attr(docsrs, feature(extended_key_value_attributes))]
#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
+#![warn(clippy::std_instead_of_core)]
// BEGIN - Embark standard lints v6 for Rust 1.55+
// do not change or add/remove here, but one can add exceptions after this section
// for more info see: <https://github.com/EmbarkStudios/rust-ecosystem/issues/59>
@@ -175,6 +176,7 @@ pub(crate) mod lib {
#[cfg(feature = "std")]
/// internal std exports for `no_std` compatibility
pub mod std {
+ #![allow(clippy::std_instead_of_core)]
#[doc(hidden)]
pub use std::{
alloc, borrow, boxed, cmp, collections, convert, fmt, hash, iter, mem, ops, option,
diff --git a/vendor/winnow/src/parser.rs b/vendor/winnow/src/parser.rs
index b59e4cd83..8a1040dc9 100644
--- a/vendor/winnow/src/parser.rs
+++ b/vendor/winnow/src/parser.rs
@@ -1,5 +1,6 @@
//! Basic types to build the parsers
+use crate::ascii::Caseless as AsciiCaseless;
use crate::combinator::*;
use crate::error::{AddContext, FromExternalError, IResult, PResult, ParseError, ParserError};
use crate::stream::{AsChar, Compare, Location, ParseSlice, Stream, StreamIsPartial};
@@ -91,7 +92,7 @@ pub trait Parser<I, O, E> {
///
/// # Example
///
- /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f`
+ /// Because parsers are `FnMut`, they can be called multiple times. This prevents moving `f`
/// into [`length_data`][crate::binary::length_data] and `g` into
/// [`Parser::complete_err`]:
/// ```rust,compile_fail
@@ -194,11 +195,11 @@ pub trait Parser<I, O, E> {
/// use winnow::ascii::alpha1;
/// # fn main() {
///
- /// fn parser1<'s>(i: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
- /// alpha1(i)
- /// }
+ /// fn parser1<'s>(i: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
+ /// alpha1(i)
+ /// }
///
- /// let mut parser2 = parser1.output_into();
+ /// let mut parser2 = parser1.output_into();
///
/// // the parser converts the &str output of the child parser into a Vec<u8>
/// let bytes: IResult<&str, Vec<u8>> = parser2.parse_peek("abcd");
@@ -742,6 +743,38 @@ where
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
+/// use winnow::ascii::Caseless;
+///
+/// fn parser<'s>(s: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> {
+/// alt((Caseless(&"hello"[..]), take(5usize))).parse_next(s)
+/// }
+///
+/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
+/// assert_eq!(parser.parse_peek(&b"hello, World!"[..]), Ok((&b", World!"[..], &b"hello"[..])));
+/// assert_eq!(parser.parse_peek(&b"HeLlo, World!"[..]), Ok((&b", World!"[..], &b"HeLlo"[..])));
+/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
+/// assert_eq!(parser.parse_peek(&b"Some"[..]), Err(ErrMode::Backtrack(InputError::new(&b"Some"[..], ErrorKind::Slice))));
+/// assert_eq!(parser.parse_peek(&b""[..]), Err(ErrMode::Backtrack(InputError::new(&b""[..], ErrorKind::Slice))));
+/// ```
+impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for AsciiCaseless<&'s [u8]>
+where
+ I: Compare<AsciiCaseless<&'s [u8]>> + StreamIsPartial,
+ I: Stream,
+{
+ #[inline(always)]
+ fn parse_next(&mut self, i: &mut I) -> PResult<<I as Stream>::Slice, E> {
+ crate::token::tag(*self).parse_next(i)
+ }
+}
+
+/// This is a shortcut for [`tag`][crate::token::tag].
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::combinator::alt;
+/// # use winnow::token::take;
///
/// fn parser<'s>(s: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> {
/// alt((b"Hello", take(5usize))).parse_next(s)
@@ -768,6 +801,39 @@ where
/// # Example
/// ```rust
/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::combinator::alt;
+/// # use winnow::token::take;
+/// use winnow::ascii::Caseless;
+///
+/// fn parser<'s>(s: &mut &'s [u8]) -> PResult<&'s [u8], InputError<&'s [u8]>> {
+/// alt((Caseless(b"hello"), take(5usize))).parse_next(s)
+/// }
+///
+/// assert_eq!(parser.parse_peek(&b"Hello, World!"[..]), Ok((&b", World!"[..], &b"Hello"[..])));
+/// assert_eq!(parser.parse_peek(&b"hello, World!"[..]), Ok((&b", World!"[..], &b"hello"[..])));
+/// assert_eq!(parser.parse_peek(&b"HeLlo, World!"[..]), Ok((&b", World!"[..], &b"HeLlo"[..])));
+/// assert_eq!(parser.parse_peek(&b"Something"[..]), Ok((&b"hing"[..], &b"Somet"[..])));
+/// assert_eq!(parser.parse_peek(&b"Some"[..]), Err(ErrMode::Backtrack(InputError::new(&b"Some"[..], ErrorKind::Slice))));
+/// assert_eq!(parser.parse_peek(&b""[..]), Err(ErrMode::Backtrack(InputError::new(&b""[..], ErrorKind::Slice))));
+/// ```
+impl<'s, I, E: ParserError<I>, const N: usize> Parser<I, <I as Stream>::Slice, E>
+ for AsciiCaseless<&'s [u8; N]>
+where
+ I: Compare<AsciiCaseless<&'s [u8; N]>> + StreamIsPartial,
+ I: Stream,
+{
+ #[inline(always)]
+ fn parse_next(&mut self, i: &mut I) -> PResult<<I as Stream>::Slice, E> {
+ crate::token::tag(*self).parse_next(i)
+ }
+}
+
+/// This is a shortcut for [`tag`][crate::token::tag].
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}};
/// # use winnow::combinator::alt;
/// # use winnow::token::take;
@@ -792,6 +858,38 @@ where
}
}
+/// This is a shortcut for [`tag`][crate::token::tag].
+///
+/// # Example
+/// ```rust
+/// # use winnow::prelude::*;
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}};
+/// # use winnow::combinator::alt;
+/// # use winnow::token::take;
+/// # use winnow::ascii::Caseless;
+///
+/// fn parser<'s>(s: &mut &'s str) -> PResult<&'s str, InputError<&'s str>> {
+/// alt((Caseless("hello"), take(5usize))).parse_next(s)
+/// }
+///
+/// assert_eq!(parser.parse_peek("Hello, World!"), Ok((", World!", "Hello")));
+/// assert_eq!(parser.parse_peek("hello, World!"), Ok((", World!", "hello")));
+/// assert_eq!(parser.parse_peek("HeLlo, World!"), Ok((", World!", "HeLlo")));
+/// assert_eq!(parser.parse_peek("Something"), Ok(("hing", "Somet")));
+/// assert_eq!(parser.parse_peek("Some"), Err(ErrMode::Backtrack(InputError::new("Some", ErrorKind::Slice))));
+/// assert_eq!(parser.parse_peek(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Slice))));
+/// ```
+impl<'s, I, E: ParserError<I>> Parser<I, <I as Stream>::Slice, E> for AsciiCaseless<&'s str>
+where
+ I: Compare<AsciiCaseless<&'s str>> + StreamIsPartial,
+ I: Stream,
+{
+ #[inline(always)]
+ fn parse_next(&mut self, i: &mut I) -> PResult<<I as Stream>::Slice, E> {
+ crate::token::tag(*self).parse_next(i)
+ }
+}
+
impl<I, E: ParserError<I>> Parser<I, (), E> for () {
#[inline(always)]
fn parse_next(&mut self, _i: &mut I) -> PResult<(), E> {
diff --git a/vendor/winnow/src/stream/impls.rs b/vendor/winnow/src/stream/impls.rs
index b277dd9a9..d76e1bf35 100644
--- a/vendor/winnow/src/stream/impls.rs
+++ b/vendor/winnow/src/stream/impls.rs
@@ -238,14 +238,14 @@ mod bytes {
impl PartialOrd for Bytes {
#[inline]
fn partial_cmp(&self, other: &Bytes) -> Option<Ordering> {
- PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
+ Some(self.cmp(other))
}
}
impl Ord for Bytes {
#[inline]
fn cmp(&self, other: &Bytes) -> Ordering {
- self.partial_cmp(other).unwrap()
+ Ord::cmp(self.as_bytes(), other.as_bytes())
}
}
@@ -485,14 +485,14 @@ mod bstr {
impl PartialOrd for BStr {
#[inline]
fn partial_cmp(&self, other: &BStr) -> Option<Ordering> {
- PartialOrd::partial_cmp(self.as_bytes(), other.as_bytes())
+ Some(self.cmp(other))
}
}
impl Ord for BStr {
#[inline]
fn cmp(&self, other: &BStr) -> Ordering {
- self.partial_cmp(other).unwrap()
+ Ord::cmp(self.as_bytes(), other.as_bytes())
}
}
diff --git a/vendor/winnow/src/stream/mod.rs b/vendor/winnow/src/stream/mod.rs
index 5f2152e27..d0af80f3e 100644
--- a/vendor/winnow/src/stream/mod.rs
+++ b/vendor/winnow/src/stream/mod.rs
@@ -9,8 +9,10 @@
//! - [`Partial`] can mark an input as partial buffer that is being streamed into
//! - [Custom stream types][crate::_topic::stream]
+use core::hash::BuildHasher;
use core::num::NonZeroUsize;
+use crate::ascii::Caseless as AsciiCaseless;
use crate::error::Needed;
use crate::lib::std::iter::{Cloned, Enumerate};
use crate::lib::std::slice::Iter;
@@ -24,8 +26,12 @@ use crate::error::ErrMode;
#[cfg(feature = "alloc")]
use crate::lib::std::collections::BTreeMap;
+#[cfg(feature = "alloc")]
+use crate::lib::std::collections::BTreeSet;
#[cfg(feature = "std")]
use crate::lib::std::collections::HashMap;
+#[cfg(feature = "std")]
+use crate::lib::std::collections::HashSet;
#[cfg(feature = "alloc")]
use crate::lib::std::string::String;
#[cfg(feature = "alloc")]
@@ -88,6 +94,15 @@ impl BStr {
/// Allow collecting the span of a parsed token
///
+/// Spans are tracked as a [`Range<usize>`] of byte offsets.
+///
+/// Converting byte offsets to line or column numbers is left up to the user, as computing column
+/// numbers requires domain knowledge (are columns byte-based, codepoint-based, or grapheme-based?)
+/// and O(n) iteration over the input to determine codepoint and line boundaries.
+///
+/// [The `line-span` crate](https://docs.rs/line-span/latest/line_span/) can help with converting
+/// byte offsets to line numbers.
+///
/// See [`Parser::span`][crate::Parser::span] and [`Parser::with_span`][crate::Parser::with_span] for more details
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub struct Located<I> {
@@ -202,7 +217,7 @@ impl<I: crate::lib::std::fmt::Display, S> crate::lib::std::fmt::Display for Stat
/// Mark the input as a partial buffer for streaming input.
///
-/// Complete input means that we already have all of the data. This will be the common case with
+/// Complete input means that we already have all of the data. This will be the common case with
/// small files that can be read entirely to memory.
///
/// In contrast, streaming input assumes that we might not have all of the data.
@@ -322,6 +337,13 @@ pub trait SliceLen {
fn slice_len(&self) -> usize;
}
+impl<S: SliceLen> SliceLen for AsciiCaseless<S> {
+ #[inline(always)]
+ fn slice_len(&self) -> usize {
+ self.0.slice_len()
+ }
+}
+
impl<'a, T> SliceLen for &'a [T] {
#[inline]
fn slice_len(&self) -> usize {
@@ -423,7 +445,8 @@ pub trait Stream: Offset<<Self as Stream>::Checkpoint> + crate::lib::std::fmt::D
/// Iterate with the offset from the current location
fn iter_offsets(&self) -> Self::IterOffsets;
- /// Returns the offaet to the end of the input
+
+ /// Returns the offset to the end of the input
fn eof_offset(&self) -> usize;
/// Split off the next token from the input
@@ -450,7 +473,7 @@ pub trait Stream: Offset<<Self as Stream>::Checkpoint> + crate::lib::std::fmt::D
/// Split off a slice of tokens from the input
///
/// **NOTE:** For inputs with variable width tokens, like `&str`'s `char`, `offset` might not correspond
- /// with the number of tokens. To get a valid offset, use:
+ /// with the number of tokens. To get a valid offset, use:
/// - [`Stream::eof_offset`]
/// - [`Stream::iter_offsets`]
/// - [`Stream::offset_for`]
@@ -1276,7 +1299,10 @@ where
/// Useful functions to calculate the offset between slices and show a hexdump of a slice
pub trait Offset<Start = Self> {
- /// Offset between the first byte of `start` and the first byte of `self`
+ /// Offset between the first byte of `start` and the first byte of `self`a
+ ///
+ /// **Note:** This is an offset, not an index, and may point to the end of input
+ /// (`start.len()`) when `self` is exhausted.
fn offset_from(&self, start: &Start) -> usize;
}
@@ -1288,9 +1314,9 @@ impl<'a, T> Offset for &'a [T] {
debug_assert!(
fst <= snd,
- "`Offset::offset_to` only accepts slices of `self`"
+ "`Offset::offset_from({snd:?}, {fst:?})` only accepts slices of `self`"
);
- snd as usize - fst as usize
+ (snd as usize - fst as usize) / crate::lib::std::mem::size_of::<T>()
}
}
@@ -1567,47 +1593,50 @@ pub trait Compare<T> {
/// by lowercasing both strings and comparing
/// the result. This is a temporary solution until
/// a better one appears
+ #[deprecated(since = "0.5.20", note = "Replaced with `compare(ascii::Caseless(_))`")]
fn compare_no_case(&self, t: T) -> CompareResult;
}
-fn lowercase_byte(c: u8) -> u8 {
- match c {
- b'A'..=b'Z' => c - b'A' + b'a',
- _ => c,
- }
-}
-
impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] {
#[inline]
fn compare(&self, t: &'b [u8]) -> CompareResult {
- let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b);
-
- match pos {
- Some(_) => CompareResult::Error,
- None => {
- if self.len() >= t.len() {
- CompareResult::Ok
- } else {
- CompareResult::Incomplete
- }
- }
+ if t.iter().zip(*self).any(|(a, b)| a != b) {
+ CompareResult::Error
+ } else if self.len() < t.slice_len() {
+ CompareResult::Incomplete
+ } else {
+ CompareResult::Ok
}
}
- #[inline]
+ #[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
- if self
+ self.compare(AsciiCaseless(t))
+ }
+}
+
+impl<'a, 'b> Compare<AsciiCaseless<&'b [u8]>> for &'a [u8] {
+ #[inline]
+ fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult {
+ if t.0
.iter()
- .zip(t)
- .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b))
+ .zip(*self)
+ .any(|(a, b)| !a.eq_ignore_ascii_case(b))
{
CompareResult::Error
- } else if self.len() < t.len() {
+ } else if self.len() < t.slice_len() {
CompareResult::Incomplete
} else {
CompareResult::Ok
}
}
+
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult {
+ self.compare(t)
+ }
}
impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] {
@@ -1617,11 +1646,25 @@ impl<'a, const LEN: usize> Compare<[u8; LEN]> for &'a [u8] {
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: [u8; LEN]) -> CompareResult {
self.compare_no_case(&t[..])
}
}
+impl<'a, const LEN: usize> Compare<AsciiCaseless<[u8; LEN]>> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: AsciiCaseless<[u8; LEN]>) -> CompareResult {
+ self.compare(AsciiCaseless(&t.0[..]))
+ }
+
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<[u8; LEN]>) -> CompareResult {
+ self.compare_no_case(AsciiCaseless(&t.0[..]))
+ }
+}
+
impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] {
#[inline(always)]
fn compare(&self, t: &'b [u8; LEN]) -> CompareResult {
@@ -1629,46 +1672,72 @@ impl<'a, 'b, const LEN: usize> Compare<&'b [u8; LEN]> for &'a [u8] {
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: &'b [u8; LEN]) -> CompareResult {
self.compare_no_case(&t[..])
}
}
+impl<'a, 'b, const LEN: usize> Compare<AsciiCaseless<&'b [u8; LEN]>> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: AsciiCaseless<&'b [u8; LEN]>) -> CompareResult {
+ self.compare(AsciiCaseless(&t.0[..]))
+ }
+
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<&'b [u8; LEN]>) -> CompareResult {
+ self.compare_no_case(AsciiCaseless(&t.0[..]))
+ }
+}
+
impl<'a, 'b> Compare<&'b str> for &'a [u8] {
#[inline(always)]
fn compare(&self, t: &'b str) -> CompareResult {
self.compare(t.as_bytes())
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: &'b str) -> CompareResult {
self.compare_no_case(t.as_bytes())
}
}
+impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a [u8] {
+ #[inline(always)]
+ fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult {
+ self.compare(AsciiCaseless(t.0.as_bytes()))
+ }
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<&'b str>) -> CompareResult {
+ self.compare_no_case(AsciiCaseless(t.0.as_bytes()))
+ }
+}
+
impl<'a, 'b> Compare<&'b str> for &'a str {
#[inline(always)]
fn compare(&self, t: &'b str) -> CompareResult {
self.as_bytes().compare(t.as_bytes())
}
- //FIXME: this version is too simple and does not use the current locale
#[inline]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: &'b str) -> CompareResult {
- let pos = self
- .chars()
- .zip(t.chars())
- .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase()));
+ self.compare(AsciiCaseless(t))
+ }
+}
- match pos {
- Some(_) => CompareResult::Error,
- None => {
- if self.len() >= t.len() {
- CompareResult::Ok
- } else {
- CompareResult::Incomplete
- }
- }
- }
+impl<'a, 'b> Compare<AsciiCaseless<&'b str>> for &'a str {
+ #[inline(always)]
+ fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult {
+ self.as_bytes().compare(t.as_bytes())
+ }
+
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<&'b str>) -> CompareResult {
+ self.compare(t)
}
}
@@ -1678,11 +1747,24 @@ impl<'a, 'b> Compare<&'b [u8]> for &'a str {
AsBStr::as_bstr(self).compare(t)
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: &'b [u8]) -> CompareResult {
AsBStr::as_bstr(self).compare_no_case(t)
}
}
+impl<'a, 'b> Compare<AsciiCaseless<&'b [u8]>> for &'a str {
+ #[inline(always)]
+ fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult {
+ AsBStr::as_bstr(self).compare(t)
+ }
+ #[inline(always)]
+ #[allow(deprecated)]
+ fn compare_no_case(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult {
+ AsBStr::as_bstr(self).compare_no_case(t)
+ }
+}
+
impl<'a, T> Compare<T> for &'a Bytes
where
&'a [u8]: Compare<T>,
@@ -1694,6 +1776,7 @@ where
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: T) -> CompareResult {
let bytes = (*self).as_bytes();
bytes.compare_no_case(t)
@@ -1711,6 +1794,7 @@ where
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: T) -> CompareResult {
let bytes = (*self).as_bytes();
bytes.compare_no_case(t)
@@ -1727,6 +1811,7 @@ where
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, other: U) -> CompareResult {
self.input.compare_no_case(other)
}
@@ -1742,6 +1827,7 @@ where
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, other: U) -> CompareResult {
self.input.compare_no_case(other)
}
@@ -1757,6 +1843,7 @@ where
}
#[inline(always)]
+ #[allow(deprecated)]
fn compare_no_case(&self, t: T) -> CompareResult {
self.input.compare_no_case(t)
}
@@ -1775,6 +1862,27 @@ impl<'i, 's> FindSlice<&'s [u8]> for &'i [u8] {
}
}
+impl<'i, 's> FindSlice<(&'s [u8],)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s [u8],)) -> Option<usize> {
+ memmem(self, substr.0)
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s [u8], &'s [u8])> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s [u8], &'s [u8])) -> Option<usize> {
+ memmem2(self, substr)
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s [u8], &'s [u8], &'s [u8])> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s [u8], &'s [u8], &'s [u8])) -> Option<usize> {
+ memmem3(self, substr)
+ }
+}
+
impl<'i> FindSlice<u8> for &'i [u8] {
#[inline(always)]
fn find_slice(&self, substr: u8) -> Option<usize> {
@@ -1782,6 +1890,27 @@ impl<'i> FindSlice<u8> for &'i [u8] {
}
}
+impl<'i> FindSlice<(u8,)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8,)) -> Option<usize> {
+ memchr(substr.0, self)
+ }
+}
+
+impl<'i> FindSlice<(u8, u8)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8, u8)) -> Option<usize> {
+ memchr2(substr, self)
+ }
+}
+
+impl<'i> FindSlice<(u8, u8, u8)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8, u8, u8)) -> Option<usize> {
+ memchr3(substr, self)
+ }
+}
+
impl<'i, 's> FindSlice<&'s str> for &'i [u8] {
#[inline(always)]
fn find_slice(&self, substr: &'s str) -> Option<usize> {
@@ -1789,17 +1918,129 @@ impl<'i, 's> FindSlice<&'s str> for &'i [u8] {
}
}
+impl<'i, 's> FindSlice<(&'s str,)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str,)) -> Option<usize> {
+ memmem(self, substr.0.as_bytes())
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<usize> {
+ memmem2(self, (substr.0.as_bytes(), substr.1.as_bytes()))
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i [u8] {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<usize> {
+ memmem3(
+ self,
+ (
+ substr.0.as_bytes(),
+ substr.1.as_bytes(),
+ substr.2.as_bytes(),
+ ),
+ )
+ }
+}
+
impl<'i, 's> FindSlice<&'s str> for &'i str {
#[inline(always)]
fn find_slice(&self, substr: &'s str) -> Option<usize> {
- self.find(substr)
+ self.as_bytes().find_slice(substr.as_bytes())
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s str,)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str,)) -> Option<usize> {
+ self.as_bytes().find_slice(substr)
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s str, &'s str)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str, &'s str)) -> Option<usize> {
+ self.as_bytes().find_slice(substr)
+ }
+}
+
+impl<'i, 's> FindSlice<(&'s str, &'s str, &'s str)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (&'s str, &'s str, &'s str)) -> Option<usize> {
+ self.as_bytes().find_slice(substr)
}
}
impl<'i> FindSlice<char> for &'i str {
#[inline(always)]
fn find_slice(&self, substr: char) -> Option<usize> {
- self.find(substr)
+ let mut b = [0; 4];
+ let substr = substr.encode_utf8(&mut b);
+ self.find_slice(&*substr)
+ }
+}
+
+impl<'i> FindSlice<(char,)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (char,)) -> Option<usize> {
+ let mut b = [0; 4];
+ let substr0 = substr.0.encode_utf8(&mut b);
+ self.find_slice((&*substr0,))
+ }
+}
+
+impl<'i> FindSlice<(char, char)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (char, char)) -> Option<usize> {
+ let mut b = [0; 4];
+ let substr0 = substr.0.encode_utf8(&mut b);
+ let mut b = [0; 4];
+ let substr1 = substr.1.encode_utf8(&mut b);
+ self.find_slice((&*substr0, &*substr1))
+ }
+}
+
+impl<'i> FindSlice<(char, char, char)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (char, char, char)) -> Option<usize> {
+ let mut b = [0; 4];
+ let substr0 = substr.0.encode_utf8(&mut b);
+ let mut b = [0; 4];
+ let substr1 = substr.1.encode_utf8(&mut b);
+ let mut b = [0; 4];
+ let substr2 = substr.2.encode_utf8(&mut b);
+ self.find_slice((&*substr0, &*substr1, &*substr2))
+ }
+}
+
+impl<'i> FindSlice<u8> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: u8) -> Option<usize> {
+ self.find_slice(substr.as_char())
+ }
+}
+
+impl<'i> FindSlice<(u8,)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8,)) -> Option<usize> {
+ self.find_slice((substr.0.as_char(),))
+ }
+}
+
+impl<'i> FindSlice<(u8, u8)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8, u8)) -> Option<usize> {
+ self.find_slice((substr.0.as_char(), substr.1.as_char()))
+ }
+}
+
+impl<'i> FindSlice<(u8, u8, u8)> for &'i str {
+ #[inline(always)]
+ fn find_slice(&self, substr: (u8, u8, u8)) -> Option<usize> {
+ self.find_slice((substr.0.as_char(), substr.1.as_char(), substr.2.as_char()))
}
}
@@ -1953,7 +2194,7 @@ where
}
}
-/// Ensure checkpoint details are kept privazte
+/// Ensure checkpoint details are kept private
#[derive(Copy, Clone, Debug)]
pub struct Checkpoint<T>(T);
@@ -2177,15 +2418,19 @@ where
}
#[cfg(feature = "std")]
-impl<K, V> Accumulate<(K, V)> for HashMap<K, V>
+impl<K, V, S> Accumulate<(K, V)> for HashMap<K, V, S>
where
K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash,
+ S: BuildHasher + Default,
{
#[inline(always)]
fn initial(capacity: Option<usize>) -> Self {
+ let h = S::default();
match capacity {
- Some(capacity) => HashMap::with_capacity(clamp_capacity::<(K, V)>(capacity)),
- None => HashMap::new(),
+ Some(capacity) => {
+ HashMap::with_capacity_and_hasher(clamp_capacity::<(K, V)>(capacity), h)
+ }
+ None => HashMap::with_hasher(h),
}
}
#[inline(always)]
@@ -2195,6 +2440,41 @@ where
}
#[cfg(feature = "alloc")]
+impl<K> Accumulate<K> for BTreeSet<K>
+where
+ K: crate::lib::std::cmp::Ord,
+{
+ #[inline(always)]
+ fn initial(_capacity: Option<usize>) -> Self {
+ BTreeSet::new()
+ }
+ #[inline(always)]
+ fn accumulate(&mut self, key: K) {
+ self.insert(key);
+ }
+}
+
+#[cfg(feature = "std")]
+impl<K, S> Accumulate<K> for HashSet<K, S>
+where
+ K: crate::lib::std::cmp::Eq + crate::lib::std::hash::Hash,
+ S: BuildHasher + Default,
+{
+ #[inline(always)]
+ fn initial(capacity: Option<usize>) -> Self {
+ let h = S::default();
+ match capacity {
+ Some(capacity) => HashSet::with_capacity_and_hasher(clamp_capacity::<K>(capacity), h),
+ None => HashSet::with_hasher(h),
+ }
+ }
+ #[inline(always)]
+ fn accumulate(&mut self, key: K) {
+ self.insert(key);
+ }
+}
+
+#[cfg(feature = "alloc")]
#[inline]
pub(crate) fn clamp_capacity<T>(capacity: usize) -> usize {
/// Don't pre-allocate more than 64KiB when calling `Vec::with_capacity`.
@@ -2520,7 +2800,7 @@ impl<C: AsChar> ContainsToken<C> for char {
}
}
-impl<C: AsChar, F: Fn(C) -> bool> ContainsToken<C> for F {
+impl<C, F: Fn(C) -> bool> ContainsToken<C> for F {
#[inline(always)]
fn contains_token(&self, token: C) -> bool {
self(token)
@@ -2675,51 +2955,158 @@ fn memchr(token: u8, slice: &[u8]) -> Option<usize> {
memchr::memchr(token, slice)
}
+#[cfg(feature = "simd")]
+#[inline(always)]
+fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> {
+ memchr::memchr2(token.0, token.1, slice)
+}
+
+#[cfg(feature = "simd")]
+#[inline(always)]
+fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> {
+ memchr::memchr3(token.0, token.1, token.2, slice)
+}
+
#[cfg(not(feature = "simd"))]
#[inline(always)]
fn memchr(token: u8, slice: &[u8]) -> Option<usize> {
slice.iter().position(|t| *t == token)
}
-#[cfg(feature = "simd")]
+#[cfg(not(feature = "simd"))]
+#[inline(always)]
+fn memchr2(token: (u8, u8), slice: &[u8]) -> Option<usize> {
+ slice.iter().position(|t| *t == token.0 || *t == token.1)
+}
+
+#[cfg(not(feature = "simd"))]
+#[inline(always)]
+fn memchr3(token: (u8, u8, u8), slice: &[u8]) -> Option<usize> {
+ slice
+ .iter()
+ .position(|t| *t == token.0 || *t == token.1 || *t == token.2)
+}
+
#[inline(always)]
fn memmem(slice: &[u8], tag: &[u8]) -> Option<usize> {
- if tag.len() > slice.len() {
- return None;
+ if tag.len() == 1 {
+ memchr(tag[0], slice)
+ } else {
+ memmem_(slice, tag)
+ }
+}
+
+#[inline(always)]
+fn memmem2(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> {
+ if tag.0.len() == 1 && tag.1.len() == 1 {
+ memchr2((tag.0[0], tag.1[0]), slice)
+ } else {
+ memmem2_(slice, tag)
+ }
+}
+
+#[inline(always)]
+fn memmem3(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> {
+ if tag.0.len() == 1 && tag.1.len() == 1 && tag.2.len() == 1 {
+ memchr3((tag.0[0], tag.1[0], tag.2[0]), slice)
+ } else {
+ memmem3_(slice, tag)
}
+}
- let (&substr_first, substr_rest) = match tag.split_first() {
- Some(split) => split,
- // an empty substring is found at position 0
- // This matches the behavior of str.find("").
+#[cfg(feature = "simd")]
+#[inline(always)]
+fn memmem_(slice: &[u8], tag: &[u8]) -> Option<usize> {
+ let &prefix = match tag.first() {
+ Some(x) => x,
None => return Some(0),
};
-
- if substr_rest.is_empty() {
- return memchr::memchr(substr_first, slice);
+ #[allow(clippy::manual_find)] // faster this way
+ for i in memchr::memchr_iter(prefix, slice) {
+ if slice[i..].starts_with(tag) {
+ return Some(i);
+ }
}
+ None
+}
- let mut offset = 0;
- let haystack = &slice[..slice.len() - substr_rest.len()];
+#[cfg(feature = "simd")]
+fn memmem2_(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> {
+ let prefix = match (tag.0.first(), tag.1.first()) {
+ (Some(&a), Some(&b)) => (a, b),
+ _ => return Some(0),
+ };
+ #[allow(clippy::manual_find)] // faster this way
+ for i in memchr::memchr2_iter(prefix.0, prefix.1, slice) {
+ let subslice = &slice[i..];
+ if subslice.starts_with(tag.0) {
+ return Some(i);
+ }
+ if subslice.starts_with(tag.1) {
+ return Some(i);
+ }
+ }
+ None
+}
- while let Some(position) = memchr::memchr(substr_first, &haystack[offset..]) {
- offset += position;
- let next_offset = offset + 1;
- if &slice[next_offset..][..substr_rest.len()] == substr_rest {
- return Some(offset);
+#[cfg(feature = "simd")]
+fn memmem3_(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> {
+ let prefix = match (tag.0.first(), tag.1.first(), tag.2.first()) {
+ (Some(&a), Some(&b), Some(&c)) => (a, b, c),
+ _ => return Some(0),
+ };
+ #[allow(clippy::manual_find)] // faster this way
+ for i in memchr::memchr3_iter(prefix.0, prefix.1, prefix.2, slice) {
+ let subslice = &slice[i..];
+ if subslice.starts_with(tag.0) {
+ return Some(i);
+ }
+ if subslice.starts_with(tag.1) {
+ return Some(i);
}
+ if subslice.starts_with(tag.2) {
+ return Some(i);
+ }
+ }
+ None
+}
- offset = next_offset;
+#[cfg(not(feature = "simd"))]
+fn memmem_(slice: &[u8], tag: &[u8]) -> Option<usize> {
+ for i in 0..slice.len() {
+ let subslice = &slice[i..];
+ if subslice.starts_with(tag) {
+ return Some(i);
+ }
}
+ None
+}
+#[cfg(not(feature = "simd"))]
+fn memmem2_(slice: &[u8], tag: (&[u8], &[u8])) -> Option<usize> {
+ for i in 0..slice.len() {
+ let subslice = &slice[i..];
+ if subslice.starts_with(tag.0) {
+ return Some(i);
+ }
+ if subslice.starts_with(tag.1) {
+ return Some(i);
+ }
+ }
None
}
#[cfg(not(feature = "simd"))]
-fn memmem(slice: &[u8], tag: &[u8]) -> Option<usize> {
+fn memmem3_(slice: &[u8], tag: (&[u8], &[u8], &[u8])) -> Option<usize> {
for i in 0..slice.len() {
let subslice = &slice[i..];
- if subslice.starts_with(tag) {
+ if subslice.starts_with(tag.0) {
+ return Some(i);
+ }
+ if subslice.starts_with(tag.1) {
+ return Some(i);
+ }
+ if subslice.starts_with(tag.2) {
return Some(i);
}
}
diff --git a/vendor/winnow/src/stream/tests.rs b/vendor/winnow/src/stream/tests.rs
index e653ad9e0..0129f6e3f 100644
--- a/vendor/winnow/src/stream/tests.rs
+++ b/vendor/winnow/src/stream/tests.rs
@@ -1,8 +1,25 @@
#[cfg(feature = "std")]
use proptest::prelude::*;
+use crate::{
+ combinator::{separated, separated_pair},
+ PResult, Parser,
+};
+
use super::*;
+#[cfg(feature = "std")]
+#[test]
+fn test_fxhashmap_compiles() {
+ let input = "a=b";
+ fn pair(i: &mut &str) -> PResult<(char, char)> {
+ let out = separated_pair('a', '=', 'b').parse_next(i)?;
+ Ok(out)
+ }
+
+ let _: rustc_hash::FxHashMap<char, char> = separated(0.., pair, ',').parse(input).unwrap();
+}
+
#[test]
fn test_offset_u8() {
let s = b"abcd123";
@@ -114,3 +131,18 @@ fn test_partial_complete() {
i.restore_partial(incomplete_state);
assert!(i.is_partial(), "incomplete stream state should be restored");
}
+
+#[test]
+fn test_custom_slice() {
+ type Token = usize;
+ type TokenSlice<'i> = &'i [Token];
+
+ let mut tokens: TokenSlice<'_> = &[1, 2, 3, 4];
+
+ let input = &mut tokens;
+ let start = input.checkpoint();
+ let _ = input.next_token();
+ let _ = input.next_token();
+ let offset = input.offset_from(&start);
+ assert_eq!(offset, 2);
+}
diff --git a/vendor/winnow/src/token/mod.rs b/vendor/winnow/src/token/mod.rs
index fba019c97..839821f79 100644
--- a/vendor/winnow/src/token/mod.rs
+++ b/vendor/winnow/src/token/mod.rs
@@ -81,7 +81,7 @@ where
///
/// It will return `Err(ErrMode::Backtrack(InputError::new(_, ErrorKind::Tag)))` if the input doesn't match the pattern
///
-/// **Note:** [`Parser`][crate::Parser] is implemented for strings and byte strings as a convenience (complete
+/// **Note:** [`Parser`] is implemented for strings and byte strings as a convenience (complete
/// only)
///
/// # Example
@@ -114,6 +114,23 @@ where
/// assert_eq!(parser(Partial::new("S")), Err(ErrMode::Backtrack(InputError::new(Partial::new("S"), ErrorKind::Tag))));
/// assert_eq!(parser(Partial::new("H")), Err(ErrMode::Incomplete(Needed::new(4))));
/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::{InputError, ErrorKind}, error::Needed};
+/// # use winnow::prelude::*;
+/// use winnow::token::tag;
+/// use winnow::ascii::Caseless;
+///
+/// fn parser(s: &str) -> IResult<&str, &str> {
+/// tag(Caseless("hello")).parse_peek(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(ErrMode::Backtrack(InputError::new("Something", ErrorKind::Tag))));
+/// assert_eq!(parser(""), Err(ErrMode::Backtrack(InputError::new("", ErrorKind::Tag))));
+/// ```
#[inline(always)]
#[doc(alias = "literal")]
#[doc(alias = "bytes")]
@@ -201,6 +218,7 @@ where
#[doc(alias = "literal")]
#[doc(alias = "bytes")]
#[doc(alias = "just")]
+#[deprecated(since = "0.5.20", note = "Replaced with `tag(ascii::Caseless(_))`")]
pub fn tag_no_case<T, I, Error: ParserError<I>>(
tag: T,
) -> impl Parser<I, <I as Stream>::Slice, Error>
@@ -219,6 +237,7 @@ where
})
}
+#[allow(deprecated)]
fn tag_no_case_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
i: &mut I,
t: T,
@@ -244,7 +263,7 @@ where
/// Recognize a token that matches the [pattern][ContainsToken]
///
-/// **Note:** [`Parser`][crate::Parser] is implemented as a convenience (complete
+/// **Note:** [`Parser`] is implemented as a convenience (complete
/// only) for
/// - `u8`
/// - `char`
@@ -349,9 +368,9 @@ where
/// It will return an `ErrMode::Backtrack(InputError::new(_, ErrorKind::Slice))` if the pattern wasn't met or is out
/// of range (m <= len <= n).
///
-/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
+/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the pattern reaches the end of the input or is too short.
///
-/// To recognize a series of tokens, use [`repeat`][crate::combinator::repeat] to [`Accumulate`][crate::stream::Accumulate] into a `()` and then [`Parser::recognize`][crate::Parser::recognize].
+/// To recognize a series of tokens, use [`repeat`][crate::combinator::repeat] to [`Accumulate`][crate::stream::Accumulate] into a `()` and then [`Parser::recognize`].
///
/// # Example
///
@@ -546,14 +565,27 @@ where
I: Stream,
T: ContainsToken<<I as Stream>::Token>,
{
- let e: ErrorKind = ErrorKind::Slice;
if PARTIAL && input.is_partial() {
- take_till1_partial(input, |c| !list.contains_token(c), e)
+ take_till1_partial(input, |c| !list.contains_token(c))
} else {
- take_till1_complete(input, |c| !list.contains_token(c), e)
+ take_till1_complete(input, |c| !list.contains_token(c))
}
}
+fn take_while_m_n_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
+ input: &mut I,
+ m: usize,
+ n: usize,
+ list: &T,
+) -> PResult<<I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ take_till_m_n::<_, _, _, PARTIAL>(input, m, n, |c| !list.contains_token(c))
+}
+
/// Looks for the first element of the input type for which the condition returns true,
/// and returns the input up to this position.
///
@@ -580,11 +612,11 @@ where
fn take_till1_partial<P, I: Stream, E: ParserError<I>>(
input: &mut I,
predicate: P,
- e: ErrorKind,
) -> PResult<<I as Stream>::Slice, E>
where
P: Fn(I::Token) -> bool,
{
+ let e: ErrorKind = ErrorKind::Slice;
let offset = input
.offset_for(predicate)
.ok_or_else(|| ErrMode::Incomplete(Needed::new(1)))?;
@@ -621,11 +653,11 @@ where
fn take_till1_complete<P, I: Stream, E: ParserError<I>>(
input: &mut I,
predicate: P,
- e: ErrorKind,
) -> PResult<<I as Stream>::Slice, E>
where
P: Fn(I::Token) -> bool,
{
+ let e: ErrorKind = ErrorKind::Slice;
let offset = input
.offset_for(predicate)
.unwrap_or_else(|| input.eof_offset());
@@ -636,16 +668,16 @@ where
}
}
-fn take_while_m_n_<T, I, Error: ParserError<I>, const PARTIAL: bool>(
+fn take_till_m_n<P, I, Error: ParserError<I>, const PARTIAL: bool>(
input: &mut I,
m: usize,
n: usize,
- list: &T,
+ predicate: P,
) -> PResult<<I as Stream>::Slice, Error>
where
I: StreamIsPartial,
I: Stream,
- T: ContainsToken<<I as Stream>::Token>,
+ P: Fn(I::Token) -> bool,
{
if n < m {
return Err(ErrMode::assert(input, "`m` should be <= `n`"));
@@ -653,7 +685,7 @@ where
let mut final_count = 0;
for (processed, (offset, token)) in input.iter_offsets().enumerate() {
- if !list.contains_token(token) {
+ if predicate(token) {
if processed < m {
return Err(ErrMode::from_error_kind(input, ErrorKind::Slice));
} else {
@@ -696,6 +728,86 @@ where
/// ```rust
/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
/// # use winnow::prelude::*;
+/// use winnow::token::take_till;
+///
+/// fn till_colon(s: &str) -> IResult<&str, &str> {
+/// take_till(0.., |c| c == ':').parse_peek(s)
+/// }
+///
+/// assert_eq!(till_colon("latin:123"), Ok((":123", "latin")));
+/// assert_eq!(till_colon(":empty matched"), Ok((":empty matched", ""))); //allowed
+/// assert_eq!(till_colon("12345"), Ok(("", "12345")));
+/// assert_eq!(till_colon(""), Ok(("", "")));
+/// ```
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
+/// # use winnow::prelude::*;
+/// # use winnow::Partial;
+/// use winnow::token::take_till;
+///
+/// fn till_colon(s: Partial<&str>) -> IResult<Partial<&str>, &str> {
+/// take_till(0.., |c| c == ':').parse_peek(s)
+/// }
+///
+/// assert_eq!(till_colon(Partial::new("latin:123")), Ok((Partial::new(":123"), "latin")));
+/// assert_eq!(till_colon(Partial::new(":empty matched")), Ok((Partial::new(":empty matched"), ""))); //allowed
+/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
+/// ```
+#[inline(always)]
+#[doc(alias = "is_not")]
+pub fn take_till<T, I, Error: ParserError<I>>(
+ range: impl Into<Range>,
+ list: T,
+) -> impl Parser<I, <I as Stream>::Slice, Error>
+where
+ I: StreamIsPartial,
+ I: Stream,
+ T: ContainsToken<<I as Stream>::Token>,
+{
+ let Range {
+ start_inclusive,
+ end_inclusive,
+ } = range.into();
+ trace("take_till", move |i: &mut I| {
+ match (start_inclusive, end_inclusive) {
+ (0, None) => {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_till0_partial(i, |c| list.contains_token(c))
+ } else {
+ take_till0_complete(i, |c| list.contains_token(c))
+ }
+ }
+ (1, None) => {
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_till1_partial(i, |c| list.contains_token(c))
+ } else {
+ take_till1_complete(i, |c| list.contains_token(c))
+ }
+ }
+ (start, end) => {
+ let end = end.unwrap_or(usize::MAX);
+ if <I as StreamIsPartial>::is_partial_supported() {
+ take_till_m_n::<_, _, _, true>(i, start, end, |c| list.contains_token(c))
+ } else {
+ take_till_m_n::<_, _, _, false>(i, start, end, |c| list.contains_token(c))
+ }
+ }
+ }
+ })
+}
+
+/// Recognize the longest input slice (if any) till a [pattern][ContainsToken] is met.
+///
+/// *Partial version* will return a `ErrMode::Incomplete(Needed::new(1))` if the match reaches the
+/// end of input or if there was not match.
+///
+/// # Example
+///
+/// ```rust
+/// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError, error::Needed};
+/// # use winnow::prelude::*;
/// use winnow::token::take_till0;
///
/// fn till_colon(s: &str) -> IResult<&str, &str> {
@@ -723,6 +835,7 @@ where
/// assert_eq!(till_colon(Partial::new("12345")), Err(ErrMode::Incomplete(Needed::new(1))));
/// assert_eq!(till_colon(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
/// ```
+#[deprecated(since = "0.5.21", note = "Replaced with `take_till(0.., ...)`")]
#[inline(always)]
pub fn take_till0<T, I, Error: ParserError<I>>(
list: T,
@@ -800,7 +913,7 @@ where
/// assert_eq!(not_space(Partial::new("")), Err(ErrMode::Incomplete(Needed::new(1))));
/// ```
#[inline(always)]
-#[doc(alias = "is_not")]
+#[deprecated(since = "0.5.21", note = "Replaced with `take_till(1.., ...)`")]
pub fn take_till1<T, I, Error: ParserError<I>>(
list: T,
) -> impl Parser<I, <I as Stream>::Slice, Error>
@@ -810,11 +923,10 @@ where
T: ContainsToken<<I as Stream>::Token>,
{
trace("take_till1", move |i: &mut I| {
- let e: ErrorKind = ErrorKind::Slice;
if <I as StreamIsPartial>::is_partial_supported() && i.is_partial() {
- take_till1_partial(i, |c| list.contains_token(c), e)
+ take_till1_partial(i, |c| list.contains_token(c))
} else {
- take_till1_complete(i, |c| list.contains_token(c), e)
+ take_till1_complete(i, |c| list.contains_token(c))
}
})
}
@@ -1025,7 +1137,7 @@ where
/// assert_eq!(until_eof(Partial::new("hello, world")), Err(ErrMode::Incomplete(Needed::Unknown)));
/// assert_eq!(until_eof(Partial::new("hello, worldeo")), Err(ErrMode::Incomplete(Needed::Unknown)));
/// assert_eq!(until_eof(Partial::new("1eof2eof")), Ok((Partial::new("eof2eof"), "1")));
-/// assert_eq!(until_eof(Partial::new("eof")), Err(ErrMode::Backtrack(InputError::new(Partial::new("eof"), ErrorKind::Slice))));
+/// assert_eq!(until_eof(Partial::new("eof")), Err(ErrMode::Backtrack(InputError::new(Partial::new("eof"), ErrorKind::Slice))));
/// ```
#[inline(always)]
pub fn take_until1<T, I, Error: ParserError<I>>(
diff --git a/vendor/winnow/src/token/tests.rs b/vendor/winnow/src/token/tests.rs
index d9f364607..696187d64 100644
--- a/vendor/winnow/src/token/tests.rs
+++ b/vendor/winnow/src/token/tests.rs
@@ -3,6 +3,7 @@ use super::*;
#[cfg(feature = "std")]
use proptest::prelude::*;
+use crate::ascii::Caseless;
use crate::binary::length_data;
use crate::combinator::delimited;
use crate::error::ErrMode;
@@ -183,7 +184,7 @@ fn partial_is_a() {
#[test]
fn partial_is_not() {
fn a_or_b(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
- take_till1(['a', 'b']).parse_peek(i)
+ take_till(1.., ['a', 'b']).parse_peek(i)
}
let a = Partial::new(&b"cdab"[..]);
@@ -365,7 +366,7 @@ fn partial_take_while_m_n() {
#[test]
fn partial_take_till0() {
fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
- take_till0(AsChar::is_alpha).parse_peek(i)
+ take_till(0.., AsChar::is_alpha).parse_peek(i)
}
let a = &b""[..];
let b = &b"abcd"[..];
@@ -387,7 +388,7 @@ fn partial_take_till0() {
#[test]
fn partial_take_till1() {
fn f(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
- take_till1(AsChar::is_alpha).parse_peek(i)
+ take_till(1.., AsChar::is_alpha).parse_peek(i)
}
let a = &b""[..];
let b = &b"abcd"[..];
@@ -447,7 +448,7 @@ fn partial_take_while_utf8() {
#[test]
fn partial_take_till0_utf8() {
fn f(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
- take_till0(|c| c == '點').parse_peek(i)
+ take_till(0.., |c| c == '點').parse_peek(i)
}
assert_eq!(
@@ -465,7 +466,7 @@ fn partial_take_till0_utf8() {
);
fn g(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
- take_till0(|c| c != '點').parse_peek(i)
+ take_till(0.., |c| c != '點').parse_peek(i)
}
assert_eq!(
@@ -619,7 +620,7 @@ fn partial_length_bytes() {
#[test]
fn partial_case_insensitive() {
fn test(i: Partial<&[u8]>) -> IResult<Partial<&[u8]>, &[u8]> {
- tag_no_case("ABcd").parse_peek(i)
+ tag(Caseless("ABcd")).parse_peek(i)
}
assert_eq!(
test(Partial::new(&b"aBCdefgh"[..])),
@@ -653,7 +654,7 @@ fn partial_case_insensitive() {
);
fn test2(i: Partial<&str>) -> IResult<Partial<&str>, &str> {
- tag_no_case("ABcd").parse_peek(i)
+ tag(Caseless("ABcd")).parse_peek(i)
}
assert_eq!(
test2(Partial::new("aBCdefgh")),
diff --git a/vendor/winnow/src/trace/mod.rs b/vendor/winnow/src/trace/mod.rs
index cd96e0258..6fe89aca2 100644
--- a/vendor/winnow/src/trace/mod.rs
+++ b/vendor/winnow/src/trace/mod.rs
@@ -1,11 +1,12 @@
//! Parser execution tracing
//!
-//! By default, nothing happens and tracing gets compiled away as a no-op. To enable tracing, use
+//! By default, nothing happens and tracing gets compiled away as a no-op. To enable tracing, use
//! `--features debug`.
//!
//! # Example
//!
//!![Trace output from string example](https://raw.githubusercontent.com/winnow-rs/winnow/main/assets/trace.svg "Example output")
+#![cfg_attr(feature = "debug", allow(clippy::std_instead_of_core))]
#[cfg(feature = "debug")]
mod internals;
@@ -19,7 +20,7 @@ compile_error!("`debug` requires `std`");
/// Trace the execution of the parser
///
-/// Note that [`Parser::context` also provides high level trace information.
+/// Note that [`Parser::context`] also provides high level trace information.
///
/// See [`trace` module][self] for more details.
///