diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/matchit | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/matchit')
| -rw-r--r-- | vendor/matchit/.cargo-checksum.json | 1 | ||||
| -rw-r--r-- | vendor/matchit/Cargo.lock | 1229 | ||||
| -rw-r--r-- | vendor/matchit/Cargo.toml | 82 | ||||
| -rw-r--r-- | vendor/matchit/LICENSE | 21 | ||||
| -rw-r--r-- | vendor/matchit/LICENSE.httprouter | 29 | ||||
| -rw-r--r-- | vendor/matchit/README.md | 127 | ||||
| -rw-r--r-- | vendor/matchit/benches/bench.rs | 247 | ||||
| -rw-r--r-- | vendor/matchit/examples/hyper.rs | 87 | ||||
| -rw-r--r-- | vendor/matchit/src/error.rs | 127 | ||||
| -rw-r--r-- | vendor/matchit/src/escape.rs | 184 | ||||
| -rw-r--r-- | vendor/matchit/src/lib.rs | 131 | ||||
| -rw-r--r-- | vendor/matchit/src/params.rs | 262 | ||||
| -rw-r--r-- | vendor/matchit/src/router.rs | 147 | ||||
| -rw-r--r-- | vendor/matchit/src/tree.rs | 878 | ||||
| -rw-r--r-- | vendor/matchit/tests/insert.rs | 243 | ||||
| -rw-r--r-- | vendor/matchit/tests/match.rs | 1047 | ||||
| -rw-r--r-- | vendor/matchit/tests/remove.rs | 265 |
17 files changed, 0 insertions, 5107 deletions
diff --git a/vendor/matchit/.cargo-checksum.json b/vendor/matchit/.cargo-checksum.json deleted file mode 100644 index 0b740b3d..00000000 --- a/vendor/matchit/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"Cargo.lock":"176d03166aad1265d1c8a1430b0d95fc0d9aeb24a4ba22a6eb99058fe8cbcccf","Cargo.toml":"6be08693223305210754898a92d1fa142a884bad57798e193331a2d87560461f","LICENSE":"de701d0618d694feb1af90f02181a1763d9b0bdeb70a3a592781e529077dba65","LICENSE.httprouter":"162ce11ad71338d0a0c6ebaf5c48af72c6ae237b468859d3656fe2d9ed3f3a85","README.md":"181706c7b32682e534462b54ae1bfd0bad2050552cf1bbf6f31f21a8a3bbc5a8","benches/bench.rs":"6e075954539bb0c49cece34fa5d4259cde4d6fb247bbb5e4e9735b161e1bf857","examples/hyper.rs":"bd51bb5a293a6fed5162d70f509061219c61c63b83da8248bde4d75a2f7ac025","src/error.rs":"325f4f1e302a191bfb0e0d3240b2a124b612b86aa4fbfe8d799427bc58e02eb8","src/escape.rs":"f4ad9f1f935941fd0487bd0ee86569a0a21a47f8a1e1dc98f9bce7bfcc3f8e03","src/lib.rs":"d9aacf8176a0c8b74861a7364447a55779611cbaad2c08ca0b498a28d6359a4d","src/params.rs":"18327c24f0031efb4485351cc3984a489c037ad5b767ebb75aaec14e25b8573c","src/router.rs":"79bebbf3bc4c1597c7822a50955f935545231dc82918c954388c116b937ff736","src/tree.rs":"5c25f9d1f3e1e2af538822903c2375e117cc1f8c270f8a1c91ce106f0f2bb939","tests/insert.rs":"7c10cc38e1fdbb2ba5ddc2961a24dfb11dca263abde2833e28cb77acdc988f15","tests/match.rs":"33bf4781f538e3499cb1e463ae212787e21df2b8f3cbf04c18982c4b0f1a1213","tests/remove.rs":"bc2de63e42ab925b6faa0343a173fa9d57c8d91b305bf476d4e14bd0d6965800"},"package":"47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"}
\ No newline at end of file diff --git a/vendor/matchit/Cargo.lock b/vendor/matchit/Cargo.lock deleted file mode 100644 index c017aedf..00000000 --- a/vendor/matchit/Cargo.lock +++ /dev/null @@ -1,1229 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "actix-router" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad299af73649e1fc893e333ccf86f377751eb95ff875d095131574c6f43452c" -dependencies = [ - "bytestring", - "http", - "log", - "regex", - "serde", -] - -[[package]] -name = "addr2line" -version = "0.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "aho-corasick" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" -dependencies = [ - "memchr", -] - -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "backtrace" -version = "0.3.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" -dependencies = [ - "addr2line", - "cc", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bstr" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" -dependencies = [ - "lazy_static", - "memchr", - "regex-automata", - "serde", -] - -[[package]] -name = "bumpalo" -version = "3.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" - -[[package]] -name = "bytes" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" - -[[package]] -name = "bytestring" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" -dependencies = [ - "bytes", -] - -[[package]] -name = "cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" - -[[package]] -name = "cc" -version = "1.0.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "clap" -version = "2.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" -dependencies = [ - "bitflags", - "textwrap", - "unicode-width", -] - -[[package]] -name = "criterion" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" -dependencies = [ - "atty", - "cast", - "clap", - "criterion-plot", - "csv", - "itertools", - "lazy_static", - "num-traits", - "oorandom", - "plotters", - "rayon", - "regex", - "serde", - "serde_cbor", - "serde_derive", - "serde_json", - "tinytemplate", - "walkdir", -] - -[[package]] -name = "criterion-plot" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" -dependencies = [ - "cast", - "itertools", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "csv" -version = "1.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" -dependencies = [ - "bstr", - "csv-core", - "itoa 0.4.8", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -dependencies = [ - "memchr", -] - -[[package]] -name = "either" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "futures-channel" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" -dependencies = [ - "futures-core", -] - -[[package]] -name = "futures-core" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" - -[[package]] -name = "futures-sink" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" - -[[package]] -name = "futures-task" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" - -[[package]] -name = "futures-util" -version = "0.3.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" -dependencies = [ - "futures-core", - "futures-task", - "pin-project-lite", - "pin-utils", -] - -[[package]] -name = "gimli" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" - -[[package]] -name = "gonzales" -version = "0.0.3-beta" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a63ae0a0e43eefd14cdf85f9d98396115f4473239585f111e5626c79be8007" -dependencies = [ - "smallvec", -] - -[[package]] -name = "h2" -version = "0.3.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" - -[[package]] -name = "hermit-abi" -version = "0.1.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] - -[[package]] -name = "http" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.4", -] - -[[package]] -name = "http-body" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" -dependencies = [ - "bytes", - "http", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "hyper" -version = "0.14.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.4", - "pin-project-lite", - "socket2 0.4.9", - "tokio", - "tower-service", - "tracing", - "want", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown", -] - -[[package]] -name = "itertools" -version = "0.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" - -[[package]] -name = "js-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.148" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" - -[[package]] -name = "lock_api" -version = "0.4.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" -dependencies = [ - "autocfg", - "scopeguard", -] - -[[package]] -name = "log" -version = "0.4.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "matchit" -version = "0.8.4" -dependencies = [ - "actix-router", - "criterion", - "gonzales", - "hyper", - "path-tree", - "regex", - "route-recognizer", - "routefinder", - "tokio", - "tower", -] - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - -[[package]] -name = "miniz_oxide" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" -dependencies = [ - "adler", -] - -[[package]] -name = "mio" -version = "0.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" -dependencies = [ - "libc", - "wasi", - "windows-sys", -] - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "num_cpus" -version = "1.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "object" -version = "0.32.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" -dependencies = [ - "memchr", -] - -[[package]] -name = "once_cell" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" - -[[package]] -name = "oorandom" -version = "11.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" - -[[package]] -name = "parking_lot" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" -dependencies = [ - "lock_api", - "parking_lot_core", -] - -[[package]] -name = "parking_lot_core" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" -dependencies = [ - "cfg-if", - "libc", - "redox_syscall", - "smallvec", - "windows-targets", -] - -[[package]] -name = "path-tree" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d036097265640507a68750c543f2bd2f16565c5a9bb9675b1e213b9a422d3aa" - -[[package]] -name = "pin-project" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.37", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "plotters" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" -dependencies = [ - "num-traits", - "plotters-backend", - "plotters-svg", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "plotters-backend" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" - -[[package]] -name = "plotters-svg" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" -dependencies = [ - "plotters-backend", -] - -[[package]] -name = "proc-macro2" -version = "1.0.67" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "rayon" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" -dependencies = [ - "autocfg", - "crossbeam-deque", - "either", - "rayon-core", -] - -[[package]] -name = "rayon-core" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" -dependencies = [ - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-utils", - "num_cpus", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "regex" -version = "1.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" - -[[package]] -name = "regex-syntax" -version = "0.6.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" - -[[package]] -name = "route-recognizer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afab94fb28594581f62d981211a9a4d53cc8130bbcbbb89a0440d9b8e81a7746" - -[[package]] -name = "routefinder" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54e6ab7fb7d4627afa0d64a31cdf9545a23906a6f107bd7c9a6e4ec8fb952ea5" -dependencies = [ - "smartcow", - "smartstring", -] - -[[package]] -name = "rustc-demangle" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" - -[[package]] -name = "ryu" -version = "1.0.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" - -[[package]] -name = "same-file" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "scopeguard" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" - -[[package]] -name = "serde" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" - -[[package]] -name = "serde_cbor" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" -dependencies = [ - "half", - "serde", -] - -[[package]] -name = "serde_derive" -version = "1.0.147" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.103", -] - -[[package]] -name = "serde_json" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" -dependencies = [ - "itoa 1.0.4", - "ryu", - "serde", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" -dependencies = [ - "libc", -] - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "smallvec" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" - -[[package]] -name = "smartcow" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cd4be1039bf9f153b3a1a055043dc144360ec289854ece5dde68385f85d0faa" -dependencies = [ - "smartstring", -] - -[[package]] -name = "smartstring" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" -dependencies = [ - "autocfg", - "static_assertions", - "version_check", -] - -[[package]] -name = "socket2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "syn" -version = "1.0.103" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "2.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "tinytemplate" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" -dependencies = [ - "serde", - "serde_json", -] - -[[package]] -name = "tokio" -version = "1.32.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" -dependencies = [ - "backtrace", - "bytes", - "libc", - "mio", - "num_cpus", - "parking_lot", - "pin-project-lite", - "signal-hook-registry", - "socket2 0.5.4", - "tokio-macros", - "windows-sys", -] - -[[package]] -name = "tokio-macros" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.37", -] - -[[package]] -name = "tokio-util" -version = "0.7.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" -dependencies = [ - "bytes", - "futures-core", - "futures-sink", - "pin-project-lite", - "tokio", - "tracing", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "pin-project", - "pin-project-lite", - "tokio", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" - -[[package]] -name = "tower-service" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" - -[[package]] -name = "tracing" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" -dependencies = [ - "cfg-if", - "log", - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "try-lock" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" - -[[package]] -name = "unicode-ident" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" - -[[package]] -name = "walkdir" -version = "2.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" -dependencies = [ - "same-file", - "winapi", - "winapi-util", -] - -[[package]] -name = "want" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" -dependencies = [ - "try-lock", -] - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasm-bindgen" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" -dependencies = [ - "cfg-if", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" -dependencies = [ - "bumpalo", - "log", - "once_cell", - "proc-macro2", - "quote", - "syn 1.0.103", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.103", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.83" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" - -[[package]] -name = "web-sys" -version = "0.3.60" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" - -[[package]] -name = "windows_i686_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" diff --git a/vendor/matchit/Cargo.toml b/vendor/matchit/Cargo.toml deleted file mode 100644 index a2bf2392..00000000 --- a/vendor/matchit/Cargo.toml +++ /dev/null @@ -1,82 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -name = "matchit" -version = "0.8.4" -authors = ["Ibraheem Ahmed <ibraheem@ibraheem.ca>"] -description = "A high performance, zero-copy URL router." -readme = "README.md" -keywords = [ - "router", - "path", - "tree", - "match", - "url", -] -categories = [ - "network-programming", - "algorithms", -] -license = "MIT AND BSD-3-Clause" -repository = "https://github.com/ibraheemdev/matchit" - -[profile.release] -opt-level = 3 -lto = true -codegen-units = 1 - -[[bench]] -name = "bench" -harness = false - -[dependencies] - -[dev-dependencies.actix-router] -version = "0.2.7" - -[dev-dependencies.criterion] -version = "0.3.4" - -[dev-dependencies.gonzales] -version = "0.0.3-beta" - -[dev-dependencies.hyper] -version = "0.14" -features = ["full"] - -[dev-dependencies.path-tree] -version = "0.2.2" - -[dev-dependencies.regex] -version = "1.5.4" - -[dev-dependencies.route-recognizer] -version = "0.3.0" - -[dev-dependencies.routefinder] -version = "0.5.2" - -[dev-dependencies.tokio] -version = "1" -features = ["full"] - -[dev-dependencies.tower] -version = "0.4" -features = [ - "make", - "util", -] - -[features] -__test_helpers = [] -default = [] diff --git a/vendor/matchit/LICENSE b/vendor/matchit/LICENSE deleted file mode 100644 index 24411c7b..00000000 --- a/vendor/matchit/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2022 Ibraheem Ahmed - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/matchit/LICENSE.httprouter b/vendor/matchit/LICENSE.httprouter deleted file mode 100644 index 875308f5..00000000 --- a/vendor/matchit/LICENSE.httprouter +++ /dev/null @@ -1,29 +0,0 @@ -BSD 3-Clause License - -Copyright (c) 2013, Julien Schmidt -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -3. Neither the name of the copyright holder nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/matchit/README.md b/vendor/matchit/README.md deleted file mode 100644 index d54e7b64..00000000 --- a/vendor/matchit/README.md +++ /dev/null @@ -1,127 +0,0 @@ -# `matchit` - -[<img alt="crates.io" src="https://img.shields.io/crates/v/matchit?style=for-the-badge" height="25">](https://crates.io/crates/matchit) -[<img alt="github" src="https://img.shields.io/badge/github-matchit-blue?style=for-the-badge" height="25">](https://github.com/ibraheemdev/matchit) -[<img alt="docs.rs" src="https://img.shields.io/docsrs/matchit?style=for-the-badge" height="25">](https://docs.rs/matchit) - -A high performance, zero-copy URL router. - -```rust -use matchit::Router; - -fn main() -> Result<(), Box<dyn std::error::Error>> { - let mut router = Router::new(); - router.insert("/home", "Welcome!")?; - router.insert("/users/{id}", "A User")?; - - let matched = router.at("/users/978")?; - assert_eq!(matched.params.get("id"), Some("978")); - assert_eq!(*matched.value, "A User"); - - Ok(()) -} -``` - -## Parameters - -The router supports dynamic route segments. These can either be named or catch-all parameters. - -Named parameters like `/{id}` match anything until the next `/` or the end of the path. Note that named parameters must be followed -by a `/` or the end of the route. Dynamic suffixes are not currently supported. - -```rust,ignore -let mut m = Router::new(); -m.insert("/users/{id}", true)?; - -assert_eq!(m.at("/users/1")?.params.get("id"), Some("1")); -assert_eq!(m.at("/users/23")?.params.get("id"), Some("23")); -assert!(m.at("/users").is_err()); -``` - -Catch-all parameters start with `*` and match anything until the end of the path. They must always be at the **end** of the route. - -```rust,ignore -let mut m = Router::new(); -m.insert("/{*p}", true)?; - -assert_eq!(m.at("/foo.js")?.params.get("p"), Some("foo.js")); -assert_eq!(m.at("/c/bar.css")?.params.get("p"), Some("c/bar.css")); - -// note that this will not match -assert!(m.at("/").is_err()); -``` - -The literal characters `{` and `}` may be included in a static route by escaping them with the same character. For example, the `{` character is escaped with `{{` and the `}` character is escaped with `}}`. - -```rust,ignore -let mut m = Router::new(); -m.insert("/{{hello}}", true)?; -m.insert("/{hello}", true)?; - -// match the static route -assert!(m.at("/{hello}")?.value); - -// match the dynamic route -assert_eq!(m.at("/hello")?.params.get("hello"), Some("hello")); -``` - -## Routing Priority - -Static and dynamic route segments are allowed to overlap. If they do, static segments will be given higher priority: - -```rust,ignore -let mut m = Router::new(); -m.insert("/", "Welcome!").unwrap(); // priority: 1 -m.insert("/about", "About Me").unwrap(); // priority: 1 -m.insert("/{*filepath}", "...").unwrap(); // priority: 2 -``` - -## How does it work? - -The router takes advantage of the fact that URL routes generally follow a hierarchical structure. Routes are stored them in a radix trie that makes heavy use of common prefixes. - -```text -Priority Path Value -9 \ 1 -3 ├s None -2 |├earch\ 2 -1 |└upport\ 3 -2 ├blog\ 4 -1 | └{post} None -1 | └\ 5 -2 ├about-us\ 6 -1 | └team\ 7 -1 └contact\ 8 -``` - -This allows us to reduce the route search to a small number of branches. Child nodes on the same level of the tree are also prioritized -by the number of children with registered values, increasing the chance of choosing the correct branch of the first try. - -## Benchmarks - -As it turns out, this method of routing is extremely fast. In a benchmark matching 4 paths against 130 registered routes, `matchit` find the correct routes -in under 200 nanoseconds, an order of magnitude faster than most other routers. You can view the benchmark code [here](https://github.com/ibraheemdev/matchit/blob/master/benches/bench.rs). - -```text -Compare Routers/matchit -time: [175.96 ns 176.39 ns 176.84 ns] - -Compare Routers/actix -time: [26.805 us 26.811 us 26.816 us] - -Compare Routers/path-tree -time: [468.95 ns 470.34 ns 471.65 ns] - -Compare Routers/regex -time: [22.539 us 22.584 us 22.639 us] - -Compare Routers/route-recognizer -time: [3.7552 us 3.7732 us 3.8027 us] - -Compare Routers/routefinder -time: [5.7313 us 5.7405 us 5.7514 us] -``` - -## Credits - -A lot of the code in this package was based on Julien Schmidt's [`httprouter`](https://github.com/julienschmidt/httprouter). diff --git a/vendor/matchit/benches/bench.rs b/vendor/matchit/benches/bench.rs deleted file mode 100644 index b345b023..00000000 --- a/vendor/matchit/benches/bench.rs +++ /dev/null @@ -1,247 +0,0 @@ -use criterion::{black_box, criterion_group, criterion_main, Criterion}; - -fn call() -> impl IntoIterator<Item = &'static str> { - [ - "/user/repos", - "/repos/rust-lang/rust/stargazers", - "/orgs/rust-lang/public_members/nikomatsakis", - "/repos/rust-lang/rust/releases/1.51.0", - ] -} - -fn compare_routers(c: &mut Criterion) { - let mut group = c.benchmark_group("Compare Routers"); - - let mut matchit = matchit::Router::new(); - for route in register!(brackets) { - matchit.insert(route, true).unwrap(); - } - group.bench_function("matchit", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(matchit.at(route).unwrap()); - } - }); - }); - - let mut path_tree = path_tree::PathTree::new(); - for route in register!(colon) { - path_tree.insert(route, true); - } - group.bench_function("path-tree", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(path_tree.find(route).unwrap()); - } - }); - }); - - let gonzales = gonzales::RouterBuilder::new().build(register!(brackets)); - group.bench_function("gonzales", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(gonzales.route(route).unwrap()); - } - }); - }); - - let mut actix = actix_router::Router::<bool>::build(); - for route in register!(brackets) { - actix.path(route, true); - } - let actix = actix.finish(); - group.bench_function("actix", |b| { - b.iter(|| { - for route in black_box(call()) { - let mut path = actix_router::Path::new(route); - black_box(actix.recognize(&mut path).unwrap()); - } - }); - }); - - let regex_set = regex::RegexSet::new(register!(regex)).unwrap(); - group.bench_function("regex", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(regex_set.matches(route)); - } - }); - }); - - let mut route_recognizer = route_recognizer::Router::new(); - for route in register!(colon) { - route_recognizer.add(route, true); - } - group.bench_function("route-recognizer", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(route_recognizer.recognize(route).unwrap()); - } - }); - }); - - let mut routefinder = routefinder::Router::new(); - for route in register!(colon) { - routefinder.add(route, true).unwrap(); - } - group.bench_function("routefinder", |b| { - b.iter(|| { - for route in black_box(call()) { - black_box(routefinder.best_match(route).unwrap()); - } - }); - }); - - group.finish(); -} - -criterion_group!(benches, compare_routers); -criterion_main!(benches); - -macro_rules! register { - (colon) => {{ - register!(finish => ":p1", ":p2", ":p3", ":p4") - }}; - (brackets) => {{ - register!(finish => "{p1}", "{p2}", "{p3}", "{p4}") - }}; - (regex) => {{ - register!(finish => "(.*)", "(.*)", "(.*)", "(.*)") - }}; - (finish => $p1:literal, $p2:literal, $p3:literal, $p4:literal) => {{ - [ - concat!("/authorizations"), - concat!("/authorizations/", $p1), - concat!("/applications/", $p1, "/tokens/", $p2), - concat!("/events"), - concat!("/repos/", $p1, "/", $p2, "/events"), - concat!("/networks/", $p1, "/", $p2, "/events"), - concat!("/orgs/", $p1, "/events"), - concat!("/users/", $p1, "/received_events"), - concat!("/users/", $p1, "/received_events/public"), - concat!("/users/", $p1, "/events"), - concat!("/users/", $p1, "/events/public"), - concat!("/users/", $p1, "/events/orgs/", $p2), - concat!("/feeds"), - concat!("/notifications"), - concat!("/repos/", $p1, "/", $p2, "/notifications"), - concat!("/notifications/threads/", $p1), - concat!("/notifications/threads/", $p1, "/subscription"), - concat!("/repos/", $p1, "/", $p2, "/stargazers"), - concat!("/users/", $p1, "/starred"), - concat!("/user/starred"), - concat!("/user/starred/", $p1, "/", $p2), - concat!("/repos/", $p1, "/", $p2, "/subscribers"), - concat!("/users/", $p1, "/subscriptions"), - concat!("/user/subscriptions"), - concat!("/repos/", $p1, "/", $p2, "/subscription"), - concat!("/user/subscriptions/", $p1, "/", $p2), - concat!("/users/", $p1, "/gists"), - concat!("/gists"), - concat!("/gists/", $p1), - concat!("/gists/", $p1, "/star"), - concat!("/repos/", $p1, "/", $p2, "/git/blobs/", $p3), - concat!("/repos/", $p1, "/", $p2, "/git/commits/", $p3), - concat!("/repos/", $p1, "/", $p2, "/git/refs"), - concat!("/repos/", $p1, "/", $p2, "/git/tags/", $p3), - concat!("/repos/", $p1, "/", $p2, "/git/trees/", $p3), - concat!("/issues"), - concat!("/user/issues"), - concat!("/orgs/", $p1, "/issues"), - concat!("/repos/", $p1, "/", $p2, "/issues"), - concat!("/repos/", $p1, "/", $p2, "/issues/", $p3), - concat!("/repos/", $p1, "/", $p2, "/assignees"), - concat!("/repos/", $p1, "/", $p2, "/assignees/", $p3), - concat!("/repos/", $p1, "/", $p2, "/issues/", $p3, "/comments"), - concat!("/repos/", $p1, "/", $p2, "/issues/", $p3, "/events"), - concat!("/repos/", $p1, "/", $p2, "/labels"), - concat!("/repos/", $p1, "/", $p2, "/labels/", $p3), - concat!("/repos/", $p1, "/", $p2, "/issues/", $p3, "/labels"), - concat!("/repos/", $p1, "/", $p2, "/milestones/", $p3, "/labels"), - concat!("/repos/", $p1, "/", $p2, "/milestones/"), - concat!("/repos/", $p1, "/", $p2, "/milestones/", $p3), - concat!("/emojis"), - concat!("/gitignore/templates"), - concat!("/gitignore/templates/", $p1), - concat!("/meta"), - concat!("/rate_limit"), - concat!("/users/", $p1, "/orgs"), - concat!("/user/orgs"), - concat!("/orgs/", $p1), - concat!("/orgs/", $p1, "/members"), - concat!("/orgs/", $p1, "/members", $p2), - concat!("/orgs/", $p1, "/public_members"), - concat!("/orgs/", $p1, "/public_members/", $p2), - concat!("/orgs/", $p1, "/teams"), - concat!("/teams/", $p1), - concat!("/teams/", $p1, "/members"), - concat!("/teams/", $p1, "/members", $p2), - concat!("/teams/", $p1, "/repos"), - concat!("/teams/", $p1, "/repos/", $p2, "/", $p3), - concat!("/user/teams"), - concat!("/repos/", $p1, "/", $p2, "/pulls"), - concat!("/repos/", $p1, "/", $p2, "/pulls/", $p3), - concat!("/repos/", $p1, "/", $p2, "/pulls/", $p3, "/commits"), - concat!("/repos/", $p1, "/", $p2, "/pulls/", $p3, "/files"), - concat!("/repos/", $p1, "/", $p2, "/pulls/", $p3, "/merge"), - concat!("/repos/", $p1, "/", $p2, "/pulls/", $p3, "/comments"), - concat!("/user/repos"), - concat!("/users/", $p1, "/repos"), - concat!("/orgs/", $p1, "/repos"), - concat!("/repositories"), - concat!("/repos/", $p1, "/", $p2), - concat!("/repos/", $p1, "/", $p2, "/contributors"), - concat!("/repos/", $p1, "/", $p2, "/languages"), - concat!("/repos/", $p1, "/", $p2, "/teams"), - concat!("/repos/", $p1, "/", $p2, "/tags"), - concat!("/repos/", $p1, "/", $p2, "/branches"), - concat!("/repos/", $p1, "/", $p2, "/branches/", $p3), - concat!("/repos/", $p1, "/", $p2, "/collaborators"), - concat!("/repos/", $p1, "/", $p2, "/collaborators/", $p3), - concat!("/repos/", $p1, "/", $p2, "/comments"), - concat!("/repos/", $p1, "/", $p2, "/commits/", $p3, "/comments"), - concat!("/repos/", $p1, "/", $p2, "/commits"), - concat!("/repos/", $p1, "/", $p2, "/commits/", $p3), - concat!("/repos/", $p1, "/", $p2, "/readme"), - concat!("/repos/", $p1, "/", $p2, "/keys"), - concat!("/repos/", $p1, "/", $p2, "/keys", $p3), - concat!("/repos/", $p1, "/", $p2, "/downloads"), - concat!("/repos/", $p1, "/", $p2, "/downloads", $p3), - concat!("/repos/", $p1, "/", $p2, "/forks"), - concat!("/repos/", $p1, "/", $p2, "/hooks"), - concat!("/repos/", $p1, "/", $p2, "/hooks", $p3), - concat!("/repos/", $p1, "/", $p2, "/releases"), - concat!("/repos/", $p1, "/", $p2, "/releases/", $p3), - concat!("/repos/", $p1, "/", $p2, "/releases/", $p3, "/assets"), - concat!("/repos/", $p1, "/", $p2, "/stats/contributors"), - concat!("/repos/", $p1, "/", $p2, "/stats/commit_activity"), - concat!("/repos/", $p1, "/", $p2, "/stats/code_frequency"), - concat!("/repos/", $p1, "/", $p2, "/stats/participation"), - concat!("/repos/", $p1, "/", $p2, "/stats/punch_card"), - concat!("/repos/", $p1, "/", $p2, "/statuses/", $p3), - concat!("/search/repositories"), - concat!("/search/code"), - concat!("/search/issues"), - concat!("/search/users"), - concat!("/legacy/issues/search/", $p1, "/", $p2, "/", $p3, "/", $p4), - concat!("/legacy/repos/search/", $p1), - concat!("/legacy/user/search/", $p1), - concat!("/legacy/user/email/", $p1), - concat!("/users/", $p1), - concat!("/user"), - concat!("/users"), - concat!("/user/emails"), - concat!("/users/", $p1, "/followers"), - concat!("/user/followers"), - concat!("/users/", $p1, "/following"), - concat!("/user/following"), - concat!("/user/following/", $p1), - concat!("/users/", $p1, "/following", $p2), - concat!("/users/", $p1, "/keys"), - concat!("/user/keys"), - concat!("/user/keys/", $p1), - ] - }}; -} - -use register; diff --git a/vendor/matchit/examples/hyper.rs b/vendor/matchit/examples/hyper.rs deleted file mode 100644 index 803af5f4..00000000 --- a/vendor/matchit/examples/hyper.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::collections::HashMap; -use std::convert::Infallible; -use std::sync::{Arc, Mutex}; - -use hyper::server::Server; -use hyper::service::{make_service_fn, service_fn}; -use hyper::{Body, Method, Request, Response}; -use tower::util::BoxCloneService; -use tower::Service as _; - -// GET / -async fn index(_req: Request<Body>) -> hyper::Result<Response<Body>> { - Ok(Response::new(Body::from("Hello, world!"))) -} - -// GET /blog -async fn blog(_req: Request<Body>) -> hyper::Result<Response<Body>> { - Ok(Response::new(Body::from("..."))) -} - -// 404 handler -async fn not_found(_req: Request<Body>) -> hyper::Result<Response<Body>> { - Ok(Response::builder().status(404).body(Body::empty()).unwrap()) -} - -// We can use `BoxCloneService` to erase the type of each handler service. -// -// We still need a `Mutex` around each service because `BoxCloneService` doesn't -// require the service to implement `Sync`. -type Service = Mutex<BoxCloneService<Request<Body>, Response<Body>, hyper::Error>>; - -// We use a `HashMap` to hold a `Router` for each HTTP method. This allows us -// to register the same route for multiple methods. -type Router = HashMap<Method, matchit::Router<Service>>; - -async fn route(router: Arc<Router>, req: Request<Body>) -> hyper::Result<Response<Body>> { - // find the subrouter for this request method - let router = match router.get(req.method()) { - Some(router) => router, - // if there are no routes for this method, respond with 405 Method Not Allowed - None => return Ok(Response::builder().status(405).body(Body::empty()).unwrap()), - }; - - // find the service for this request path - match router.at(req.uri().path()) { - Ok(found) => { - // lock the service for a very short time, just to clone the service - let mut service = found.value.lock().unwrap().clone(); - service.call(req).await - } - // if we there is no matching service, call the 404 handler - Err(_) => not_found(req).await, - } -} - -#[tokio::main] -async fn main() { - // Create a router and register our routes. - let mut router = Router::new(); - - // GET / => `index` - router - .entry(Method::GET) - .or_default() - .insert("/", BoxCloneService::new(service_fn(index)).into()) - .unwrap(); - - // GET /blog => `blog` - router - .entry(Method::GET) - .or_default() - .insert("/blog", BoxCloneService::new(service_fn(blog)).into()) - .unwrap(); - - // boilerplate for the hyper service - let router = Arc::new(router); - let make_service = make_service_fn(|_| { - let router = router.clone(); - async { Ok::<_, Infallible>(service_fn(move |request| route(router.clone(), request))) } - }); - - // run the server - Server::bind(&([127, 0, 0, 1], 3000).into()) - .serve(make_service) - .await - .unwrap() -} diff --git a/vendor/matchit/src/error.rs b/vendor/matchit/src/error.rs deleted file mode 100644 index ab879f30..00000000 --- a/vendor/matchit/src/error.rs +++ /dev/null @@ -1,127 +0,0 @@ -use crate::escape::{UnescapedRef, UnescapedRoute}; -use crate::tree::{denormalize_params, Node}; - -use std::fmt; - -/// Represents errors that can occur when inserting a new route. -#[non_exhaustive] -#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] -pub enum InsertError { - /// Attempted to insert a path that conflicts with an existing route. - Conflict { - /// The existing route that the insertion is conflicting with. - with: String, - }, - /// Only one parameter per route segment is allowed. - /// - /// Static segments are also allowed before a parameter, but not after it. For example, - /// `/foo-{bar}` is a valid route, but `/{bar}-foo` is not. - InvalidParamSegment, - /// Parameters must be registered with a valid name and matching braces. - /// - /// Note you can use `{{` or `}}` to escape literal brackets. - InvalidParam, - /// Catch-all parameters are only allowed at the end of a path. - InvalidCatchAll, -} - -impl fmt::Display for InsertError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Conflict { with } => { - write!( - f, - "Insertion failed due to conflict with previously registered route: {}", - with - ) - } - Self::InvalidParamSegment => { - write!(f, "Only one parameter is allowed per path segment") - } - Self::InvalidParam => write!(f, "Parameters must be registered with a valid name"), - Self::InvalidCatchAll => write!( - f, - "Catch-all parameters are only allowed at the end of a route" - ), - } - } -} - -impl std::error::Error for InsertError {} - -impl InsertError { - /// Returns an error for a route conflict with the given node. - /// - /// This method attempts to find the full conflicting route. - pub(crate) fn conflict<T>( - route: &UnescapedRoute, - prefix: UnescapedRef<'_>, - current: &Node<T>, - ) -> Self { - let mut route = route.clone(); - - // The route is conflicting with the current node. - if prefix.unescaped() == current.prefix.unescaped() { - denormalize_params(&mut route, ¤t.remapping); - return InsertError::Conflict { - with: String::from_utf8(route.into_unescaped()).unwrap(), - }; - } - - // Remove the non-matching suffix from the route. - route.truncate(route.len() - prefix.len()); - - // Add the conflicting prefix. - if !route.ends_with(¤t.prefix) { - route.append(¤t.prefix); - } - - // Add the prefixes of any conflicting children. - let mut child = current.children.first(); - while let Some(node) = child { - route.append(&node.prefix); - child = node.children.first(); - } - - // Denormalize any route parameters. - let mut last = current; - while let Some(node) = last.children.first() { - last = node; - } - denormalize_params(&mut route, &last.remapping); - - // Return the conflicting route. - InsertError::Conflict { - with: String::from_utf8(route.into_unescaped()).unwrap(), - } - } -} - -/// A failed match attempt. -/// -/// ``` -/// use matchit::{MatchError, Router}; -/// # fn main() -> Result<(), Box<dyn std::error::Error>> { -/// let mut router = Router::new(); -/// router.insert("/home", "Welcome!")?; -/// router.insert("/blog", "Our blog.")?; -/// -/// // no routes match -/// if let Err(err) = router.at("/blo") { -/// assert_eq!(err, MatchError::NotFound); -/// } -/// # Ok(()) -/// # } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum MatchError { - /// No matching route was found. - NotFound, -} - -impl fmt::Display for MatchError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "Matching route not found") - } -} - -impl std::error::Error for MatchError {} diff --git a/vendor/matchit/src/escape.rs b/vendor/matchit/src/escape.rs deleted file mode 100644 index ef8ddbfb..00000000 --- a/vendor/matchit/src/escape.rs +++ /dev/null @@ -1,184 +0,0 @@ -use std::{fmt, ops::Range}; - -/// An unescaped route that keeps track of the position of escaped characters ('{{' or '}}'). -/// -/// Note that this type dereferences to `&[u8]`. -#[derive(Clone, Default)] -pub struct UnescapedRoute { - // The raw unescaped route. - inner: Vec<u8>, - escaped: Vec<usize>, -} - -impl UnescapedRoute { - /// Unescapes escaped brackets ('{{' or '}}') in a route. - pub fn new(mut inner: Vec<u8>) -> UnescapedRoute { - let mut escaped = Vec::new(); - let mut i = 0; - - while let Some(&c) = inner.get(i) { - if (c == b'{' && inner.get(i + 1) == Some(&b'{')) - || (c == b'}' && inner.get(i + 1) == Some(&b'}')) - { - inner.remove(i); - escaped.push(i); - } - - i += 1; - } - - UnescapedRoute { inner, escaped } - } - - /// Returns true if the character at the given index was escaped. - pub fn is_escaped(&self, i: usize) -> bool { - self.escaped.contains(&i) - } - - /// Replaces the characters in the given range. - pub fn splice( - &mut self, - range: Range<usize>, - replace: Vec<u8>, - ) -> impl Iterator<Item = u8> + '_ { - // Ignore any escaped characters in the range being replaced. - self.escaped.retain(|x| !range.contains(x)); - - // Update the escaped indices. - let offset = (replace.len() as isize) - (range.len() as isize); - for i in &mut self.escaped { - if *i > range.end { - *i = i.checked_add_signed(offset).unwrap(); - } - } - - self.inner.splice(range, replace) - } - - /// Appends another route to the end of this one. - pub fn append(&mut self, other: &UnescapedRoute) { - for i in &other.escaped { - self.escaped.push(self.inner.len() + i); - } - - self.inner.extend_from_slice(&other.inner); - } - - /// Truncates the route to the given length. - pub fn truncate(&mut self, to: usize) { - self.escaped.retain(|&x| x < to); - self.inner.truncate(to); - } - - /// Returns a reference to this route. - pub fn as_ref(&self) -> UnescapedRef<'_> { - UnescapedRef { - inner: &self.inner, - escaped: &self.escaped, - offset: 0, - } - } - - /// Returns a reference to the unescaped slice. - pub fn unescaped(&self) -> &[u8] { - &self.inner - } - - /// Returns the unescaped route. - pub fn into_unescaped(self) -> Vec<u8> { - self.inner - } -} - -impl std::ops::Deref for UnescapedRoute { - type Target = [u8]; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl fmt::Debug for UnescapedRoute { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - fmt::Debug::fmt(std::str::from_utf8(&self.inner).unwrap(), f) - } -} - -/// A reference to an `UnescapedRoute`. -#[derive(Copy, Clone)] -pub struct UnescapedRef<'a> { - pub inner: &'a [u8], - escaped: &'a [usize], - // An offset applied to each escaped index. - offset: isize, -} - -impl<'a> UnescapedRef<'a> { - /// Converts this reference into an owned route. - pub fn to_owned(self) -> UnescapedRoute { - let mut escaped = Vec::new(); - for &i in self.escaped { - let i = i.checked_add_signed(self.offset); - - match i { - Some(i) if i < self.inner.len() => escaped.push(i), - _ => {} - } - } - - UnescapedRoute { - escaped, - inner: self.inner.to_owned(), - } - } - - /// Returns `true` if the character at the given index was escaped. - pub fn is_escaped(&self, i: usize) -> bool { - if let Some(i) = i.checked_add_signed(-self.offset) { - return self.escaped.contains(&i); - } - - false - } - - /// Slices the route with `start..`. - pub fn slice_off(&self, start: usize) -> UnescapedRef<'a> { - UnescapedRef { - inner: &self.inner[start..], - escaped: self.escaped, - offset: self.offset - (start as isize), - } - } - - /// Slices the route with `..end`. - pub fn slice_until(&self, end: usize) -> UnescapedRef<'a> { - UnescapedRef { - inner: &self.inner[..end], - escaped: self.escaped, - offset: self.offset, - } - } - - /// Returns a reference to the unescaped slice. - pub fn unescaped(&self) -> &[u8] { - self.inner - } -} - -impl<'a> std::ops::Deref for UnescapedRef<'a> { - type Target = &'a [u8]; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl<'a> fmt::Debug for UnescapedRef<'a> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("UnescapedRef") - .field("inner", &std::str::from_utf8(self.inner)) - .field("escaped", &self.escaped) - .field("offset", &self.offset) - .finish() - } -} diff --git a/vendor/matchit/src/lib.rs b/vendor/matchit/src/lib.rs deleted file mode 100644 index cf128525..00000000 --- a/vendor/matchit/src/lib.rs +++ /dev/null @@ -1,131 +0,0 @@ -/*! -A high performance, zero-copy URL router. - -```rust -use matchit::Router; - -fn main() -> Result<(), Box<dyn std::error::Error>> { - let mut router = Router::new(); - router.insert("/home", "Welcome!")?; - router.insert("/users/{id}", "A User")?; - - let matched = router.at("/users/978")?; - assert_eq!(matched.params.get("id"), Some("978")); - assert_eq!(*matched.value, "A User"); - - Ok(()) -} -``` - -# Parameters - -The router supports dynamic route segments. These can either be named or catch-all parameters. - -Named parameters like `/{id}` match anything until the next `/` or the end of the path. Note that named parameters must be followed -by a `/` or the end of the route. Dynamic suffixes are not currently supported. - -```rust -# use matchit::Router; -# fn main() -> Result<(), Box<dyn std::error::Error>> { -let mut m = Router::new(); -m.insert("/users/{id}", true)?; - -assert_eq!(m.at("/users/1")?.params.get("id"), Some("1")); -assert_eq!(m.at("/users/23")?.params.get("id"), Some("23")); -assert!(m.at("/users").is_err()); -# Ok(()) -# } -``` - -Catch-all parameters start with `*` and match anything until the end of the path. They must always be at the **end** of the route. - -```rust -# use matchit::Router; -# fn main() -> Result<(), Box<dyn std::error::Error>> { -let mut m = Router::new(); -m.insert("/{*p}", true)?; - -assert_eq!(m.at("/foo.js")?.params.get("p"), Some("foo.js")); -assert_eq!(m.at("/c/bar.css")?.params.get("p"), Some("c/bar.css")); - -// note that this will not match -assert!(m.at("/").is_err()); -# Ok(()) -# } -``` - -The literal characters `{` and `}` may be included in a static route by escaping them with the same character. For example, the `{` character is escaped with `{{` and the `}` character is escaped with `}}`. - -```rust -# use matchit::Router; -# fn main() -> Result<(), Box<dyn std::error::Error>> { -let mut m = Router::new(); -m.insert("/{{hello}}", true)?; -m.insert("/{hello}", true)?; - -// match the static route -assert!(m.at("/{hello}")?.value); - -// match the dynamic route -assert_eq!(m.at("/hello")?.params.get("hello"), Some("hello")); -# Ok(()) -# } -``` - -# Routing Priority - -Static and dynamic route segments are allowed to overlap. If they do, static segments will be given higher priority: - -```rust -# use matchit::Router; -# fn main() -> Result<(), Box<dyn std::error::Error>> { -let mut m = Router::new(); -m.insert("/", "Welcome!").unwrap(); // priority: 1 -m.insert("/about", "About Me").unwrap(); // priority: 1 -m.insert("/{*filepath}", "...").unwrap(); // priority: 2 -# Ok(()) -# } -``` - -# How does it work? - -The router takes advantage of the fact that URL routes generally follow a hierarchical structure. Routes are stored them in a radix trie that makes heavy use of common prefixes. - -```text -Priority Path Value -9 \ 1 -3 ├s None -2 |├earch\ 2 -1 |└upport\ 3 -2 ├blog\ 4 -1 | └{post} None -1 | └\ 5 -2 ├about-us\ 6 -1 | └team\ 7 -1 └contact\ 8 -``` - -This allows us to reduce the route search to a small number of branches. Child nodes on the same level of the tree are also prioritized -by the number of children with registered values, increasing the chance of choosing the correct branch of the first try. - -As it turns out, this method of routing is extremely fast. See the [benchmark results](https://github.com/ibraheemdev/matchit?tab=readme-ov-file#benchmarks) for details. -*/ - -#![deny(rust_2018_idioms, clippy::all)] - -mod error; -mod escape; -mod params; -mod router; -mod tree; - -pub use error::{InsertError, MatchError}; -pub use params::{Params, ParamsIter}; -pub use router::{Match, Router}; - -#[cfg(doctest)] -mod readme { - #[allow(dead_code)] - #[doc = include_str!("../README.md")] - struct Readme; -} diff --git a/vendor/matchit/src/params.rs b/vendor/matchit/src/params.rs deleted file mode 100644 index 625b544b..00000000 --- a/vendor/matchit/src/params.rs +++ /dev/null @@ -1,262 +0,0 @@ -use std::{fmt, iter, mem, slice}; - -/// A single URL parameter, consisting of a key and a value. -#[derive(PartialEq, Eq, Ord, PartialOrd, Default, Copy, Clone)] -struct Param<'k, 'v> { - // Keys and values are stored as byte slices internally by the router - // to avoid UTF8 checks when slicing, but UTF8 is still respected, - // so these slices are valid strings. - key: &'k [u8], - value: &'v [u8], -} - -impl<'k, 'v> Param<'k, 'v> { - const EMPTY: Param<'static, 'static> = Param { - key: b"", - value: b"", - }; - - // Returns the parameter key as a string. - fn key_str(&self) -> &'k str { - std::str::from_utf8(self.key).unwrap() - } - - // Returns the parameter value as a string. - fn value_str(&self) -> &'v str { - std::str::from_utf8(self.value).unwrap() - } -} - -/// A list of parameters returned by a route match. -/// -/// ```rust -/// # fn main() -> Result<(), Box<dyn std::error::Error>> { -/// # let mut router = matchit::Router::new(); -/// # router.insert("/users/{id}", true).unwrap(); -/// let matched = router.at("/users/1")?; -/// -/// // Iterate through the keys and values. -/// for (key, value) in matched.params.iter() { -/// println!("key: {}, value: {}", key, value); -/// } -/// -/// // Get a specific value by name. -/// let id = matched.params.get("id"); -/// assert_eq!(id, Some("1")); -/// # Ok(()) -/// # } -/// ``` -#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)] -pub struct Params<'k, 'v> { - kind: ParamsKind<'k, 'v>, -} - -// Most routes have a small number of dynamic parameters, so we can avoid -// heap allocations in the common case. -const SMALL: usize = 3; - -// A list of parameters, optimized to avoid allocations when possible. -#[derive(PartialEq, Eq, Ord, PartialOrd, Clone)] -enum ParamsKind<'k, 'v> { - Small([Param<'k, 'v>; SMALL], usize), - Large(Vec<Param<'k, 'v>>), -} - -impl<'k, 'v> Params<'k, 'v> { - pub(crate) fn new() -> Self { - Self { - kind: ParamsKind::Small([Param::EMPTY; 3], 0), - } - } - - /// Returns the number of parameters. - pub fn len(&self) -> usize { - match self.kind { - ParamsKind::Small(_, len) => len, - ParamsKind::Large(ref vec) => vec.len(), - } - } - - // Truncates the parameter list to the given length. - pub(crate) fn truncate(&mut self, n: usize) { - match &mut self.kind { - ParamsKind::Small(_, len) => *len = n, - ParamsKind::Large(vec) => vec.truncate(n), - } - } - - /// Returns the value of the first parameter registered under the given key. - pub fn get(&self, key: impl AsRef<str>) -> Option<&'v str> { - let key = key.as_ref().as_bytes(); - - match &self.kind { - ParamsKind::Small(arr, len) => arr - .iter() - .take(*len) - .find(|param| param.key == key) - .map(Param::value_str), - ParamsKind::Large(vec) => vec - .iter() - .find(|param| param.key == key) - .map(Param::value_str), - } - } - - /// Returns an iterator over the parameters in the list. - pub fn iter(&self) -> ParamsIter<'_, 'k, 'v> { - ParamsIter::new(self) - } - - /// Returns `true` if there are no parameters in the list. - pub fn is_empty(&self) -> bool { - match self.kind { - ParamsKind::Small(_, len) => len == 0, - ParamsKind::Large(ref vec) => vec.is_empty(), - } - } - - /// Inserts a key value parameter pair into the list. - pub(crate) fn push(&mut self, key: &'k [u8], value: &'v [u8]) { - #[cold] - fn drain_to_vec<T: Default>(len: usize, elem: T, arr: &mut [T; SMALL]) -> Vec<T> { - let mut vec = Vec::with_capacity(len + 1); - vec.extend(arr.iter_mut().map(mem::take)); - vec.push(elem); - vec - } - - let param = Param { key, value }; - match &mut self.kind { - ParamsKind::Small(arr, len) => { - if *len == SMALL { - self.kind = ParamsKind::Large(drain_to_vec(*len, param, arr)); - return; - } - - arr[*len] = param; - *len += 1; - } - ParamsKind::Large(vec) => vec.push(param), - } - } - - // Applies a transformation function to each key. - pub(crate) fn for_each_key_mut(&mut self, f: impl Fn((usize, &mut &'k [u8]))) { - match &mut self.kind { - ParamsKind::Small(arr, len) => arr - .iter_mut() - .take(*len) - .map(|param| &mut param.key) - .enumerate() - .for_each(f), - ParamsKind::Large(vec) => vec - .iter_mut() - .map(|param| &mut param.key) - .enumerate() - .for_each(f), - } - } -} - -impl fmt::Debug for Params<'_, '_> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.iter()).finish() - } -} - -/// An iterator over the keys and values of a route's [parameters](crate::Params). -pub struct ParamsIter<'ps, 'k, 'v> { - kind: ParamsIterKind<'ps, 'k, 'v>, -} - -impl<'ps, 'k, 'v> ParamsIter<'ps, 'k, 'v> { - fn new(params: &'ps Params<'k, 'v>) -> Self { - let kind = match ¶ms.kind { - ParamsKind::Small(arr, len) => ParamsIterKind::Small(arr.iter().take(*len)), - ParamsKind::Large(vec) => ParamsIterKind::Large(vec.iter()), - }; - Self { kind } - } -} - -enum ParamsIterKind<'ps, 'k, 'v> { - Small(iter::Take<slice::Iter<'ps, Param<'k, 'v>>>), - Large(slice::Iter<'ps, Param<'k, 'v>>), -} - -impl<'ps, 'k, 'v> Iterator for ParamsIter<'ps, 'k, 'v> { - type Item = (&'k str, &'v str); - - fn next(&mut self) -> Option<Self::Item> { - match self.kind { - ParamsIterKind::Small(ref mut iter) => { - iter.next().map(|p| (p.key_str(), p.value_str())) - } - ParamsIterKind::Large(ref mut iter) => { - iter.next().map(|p| (p.key_str(), p.value_str())) - } - } - } -} - -impl ExactSizeIterator for ParamsIter<'_, '_, '_> { - fn len(&self) -> usize { - match self.kind { - ParamsIterKind::Small(ref iter) => iter.len(), - ParamsIterKind::Large(ref iter) => iter.len(), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn heap_alloc() { - let vec = vec![ - ("hello", "hello"), - ("world", "world"), - ("foo", "foo"), - ("bar", "bar"), - ("baz", "baz"), - ]; - - let mut params = Params::new(); - for (key, value) in vec.clone() { - params.push(key.as_bytes(), value.as_bytes()); - assert_eq!(params.get(key), Some(value)); - } - - match params.kind { - ParamsKind::Large(..) => {} - _ => panic!(), - } - - assert!(params.iter().eq(vec.clone())); - } - - #[test] - fn stack_alloc() { - let vec = vec![("hello", "hello"), ("world", "world"), ("baz", "baz")]; - - let mut params = Params::new(); - for (key, value) in vec.clone() { - params.push(key.as_bytes(), value.as_bytes()); - assert_eq!(params.get(key), Some(value)); - } - - match params.kind { - ParamsKind::Small(..) => {} - _ => panic!(), - } - - assert!(params.iter().eq(vec.clone())); - } - - #[test] - fn ignore_array_default() { - let params = Params::new(); - assert!(params.get("").is_none()); - } -} diff --git a/vendor/matchit/src/router.rs b/vendor/matchit/src/router.rs deleted file mode 100644 index 8256c4bc..00000000 --- a/vendor/matchit/src/router.rs +++ /dev/null @@ -1,147 +0,0 @@ -use crate::tree::Node; -use crate::{InsertError, MatchError, Params}; - -/// A zero-copy URL router. -/// -/// See [the crate documentation](crate) for details. -#[derive(Clone, Debug)] -pub struct Router<T> { - root: Node<T>, -} - -impl<T> Default for Router<T> { - fn default() -> Self { - Self { - root: Node::default(), - } - } -} - -impl<T> Router<T> { - /// Construct a new router. - pub fn new() -> Self { - Self::default() - } - - /// Insert a route into the router. - /// - /// # Examples - /// - /// ```rust - /// # use matchit::Router; - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// let mut router = Router::new(); - /// router.insert("/home", "Welcome!")?; - /// router.insert("/users/{id}", "A User")?; - /// # Ok(()) - /// # } - /// ``` - pub fn insert(&mut self, route: impl Into<String>, value: T) -> Result<(), InsertError> { - self.root.insert(route.into(), value) - } - - /// Tries to find a value in the router matching the given path. - /// - /// # Examples - /// - /// ```rust - /// # use matchit::Router; - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// let mut router = Router::new(); - /// router.insert("/home", "Welcome!")?; - /// - /// let matched = router.at("/home").unwrap(); - /// assert_eq!(*matched.value, "Welcome!"); - /// # Ok(()) - /// # } - /// ``` - pub fn at<'path>(&self, path: &'path str) -> Result<Match<'_, 'path, &T>, MatchError> { - match self.root.at(path.as_bytes()) { - Ok((value, params)) => Ok(Match { - // Safety: We only expose `&mut T` through `&mut self` - value: unsafe { &*value.get() }, - params, - }), - Err(e) => Err(e), - } - } - - /// Tries to find a value in the router matching the given path, - /// returning a mutable reference. - /// - /// # Examples - /// - /// ```rust - /// # use matchit::Router; - /// # fn main() -> Result<(), Box<dyn std::error::Error>> { - /// let mut router = Router::new(); - /// router.insert("/", 1)?; - /// - /// *router.at_mut("/").unwrap().value += 1; - /// assert_eq!(*router.at("/").unwrap().value, 2); - /// # Ok(()) - /// # } - /// ``` - pub fn at_mut<'path>( - &mut self, - path: &'path str, - ) -> Result<Match<'_, 'path, &mut T>, MatchError> { - match self.root.at(path.as_bytes()) { - Ok((value, params)) => Ok(Match { - // Safety: We have `&mut self` - value: unsafe { &mut *value.get() }, - params, - }), - Err(e) => Err(e), - } - } - - /// Remove a given route from the router. - /// - /// Returns the value stored under the route if it was found. - /// If the route was not found or invalid, `None` is returned. - /// - /// # Examples - /// - /// ```rust - /// # use matchit::Router; - /// let mut router = Router::new(); - /// - /// router.insert("/home", "Welcome!"); - /// assert_eq!(router.remove("/home"), Some("Welcome!")); - /// assert_eq!(router.remove("/home"), None); - /// - /// router.insert("/home/{id}/", "Hello!"); - /// assert_eq!(router.remove("/home/{id}/"), Some("Hello!")); - /// assert_eq!(router.remove("/home/{id}/"), None); - /// - /// router.insert("/home/{id}/", "Hello!"); - /// // the route does not match - /// assert_eq!(router.remove("/home/{user}"), None); - /// assert_eq!(router.remove("/home/{id}/"), Some("Hello!")); - /// - /// router.insert("/home/{id}/", "Hello!"); - /// // invalid route - /// assert_eq!(router.remove("/home/{id"), None); - /// assert_eq!(router.remove("/home/{id}/"), Some("Hello!")); - /// ``` - pub fn remove(&mut self, path: impl Into<String>) -> Option<T> { - self.root.remove(path.into()) - } - - #[cfg(feature = "__test_helpers")] - pub fn check_priorities(&self) -> Result<u32, (u32, u32)> { - self.root.check_priorities() - } -} - -/// A successful match consisting of the registered value -/// and URL parameters, returned by [`Router::at`](Router::at). -#[derive(Debug)] -pub struct Match<'k, 'v, V> { - /// The value stored under the matched node. - pub value: V, - - /// The route parameters. See [parameters](crate#parameters) for more details. - pub params: Params<'k, 'v>, -} diff --git a/vendor/matchit/src/tree.rs b/vendor/matchit/src/tree.rs deleted file mode 100644 index 69a01495..00000000 --- a/vendor/matchit/src/tree.rs +++ /dev/null @@ -1,878 +0,0 @@ -use crate::escape::{UnescapedRef, UnescapedRoute}; -use crate::{InsertError, MatchError, Params}; - -use std::cell::UnsafeCell; -use std::cmp::min; -use std::ops::Range; -use std::{fmt, mem}; - -/// A radix tree used for URL path matching. -/// -/// See [the crate documentation](crate) for details. -pub struct Node<T> { - // This node's prefix. - pub(crate) prefix: UnescapedRoute, - // The priority of this node. - // - // Nodes with more children are higher priority and searched first. - pub(crate) priority: u32, - // Whether this node contains a wildcard child. - pub(crate) wild_child: bool, - // The first character of any static children, for fast linear search. - pub(crate) indices: Vec<u8>, - // The type of this node. - pub(crate) node_type: NodeType, - pub(crate) children: Vec<Self>, - // The value stored at this node. - // - // See `Node::at` for why an `UnsafeCell` is necessary. - value: Option<UnsafeCell<T>>, - // Parameter name remapping, stored at nodes that hold values. - pub(crate) remapping: ParamRemapping, -} - -/// The types of nodes a tree can hold. -#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone)] -pub(crate) enum NodeType { - /// The root path. - Root, - /// A route parameter, e.g. `/{id}`. - Param, - /// A catch-all parameter, e.g. `/*file`. - CatchAll, - /// A static prefix, e.g. `/foo`. - Static, -} - -/// Safety: We expose `value` per Rust's usual borrowing rules, so we can just -/// delegate these traits. -unsafe impl<T: Send> Send for Node<T> {} -unsafe impl<T: Sync> Sync for Node<T> {} - -impl<T> Node<T> { - // Insert a route into the tree. - pub fn insert(&mut self, route: String, val: T) -> Result<(), InsertError> { - let route = UnescapedRoute::new(route.into_bytes()); - let (route, remapping) = normalize_params(route)?; - let mut remaining = route.as_ref(); - - self.priority += 1; - - // If the tree is empty, insert the root node. - if self.prefix.is_empty() && self.children.is_empty() { - let last = self.insert_route(remaining, val)?; - last.remapping = remapping; - self.node_type = NodeType::Root; - return Ok(()); - } - - let mut current = self; - 'walk: loop { - // Find the common prefix between the route and the current node. - let len = min(remaining.len(), current.prefix.len()); - let common_prefix = (0..len) - .find(|&i| { - remaining[i] != current.prefix[i] - // Make sure not confuse the start of a wildcard with an escaped `{`. - || remaining.is_escaped(i) != current.prefix.is_escaped(i) - }) - .unwrap_or(len); - - // If this node has a longer prefix than we need, we have to fork and extract the - // common prefix into a shared parent. - if current.prefix.len() > common_prefix { - // Move the non-matching suffix into a child node. - let suffix = current.prefix.as_ref().slice_off(common_prefix).to_owned(); - let child = Node { - prefix: suffix, - value: current.value.take(), - indices: current.indices.clone(), - wild_child: current.wild_child, - children: mem::take(&mut current.children), - remapping: mem::take(&mut current.remapping), - priority: current.priority - 1, - node_type: NodeType::Static, - }; - - // The current node now only holds the common prefix. - current.children = vec![child]; - current.indices = vec![current.prefix[common_prefix]]; - current.prefix = current - .prefix - .as_ref() - .slice_until(common_prefix) - .to_owned(); - current.wild_child = false; - continue; - } - - if remaining.len() == common_prefix { - // This node must not already contain a value. - if current.value.is_some() { - return Err(InsertError::conflict(&route, remaining, current)); - } - - // Insert the value. - current.value = Some(UnsafeCell::new(val)); - current.remapping = remapping; - return Ok(()); - } - - // Otherwise, the route has a remaining non-matching suffix. - // - // We have to search deeper. - remaining = remaining.slice_off(common_prefix); - let next = remaining[0]; - - // After matching against a wildcard the next character is always `/`. - // - // Continue searching in the child node if it already exists. - if current.node_type == NodeType::Param && current.children.len() == 1 { - debug_assert_eq!(next, b'/'); - current = &mut current.children[0]; - current.priority += 1; - continue 'walk; - } - - // Find a child node that matches the next character in the route. - for mut i in 0..current.indices.len() { - if next == current.indices[i] { - // Make sure not confuse the start of a wildcard with an escaped `{` or `}`. - if matches!(next, b'{' | b'}') && !remaining.is_escaped(0) { - continue; - } - - // Continue searching in the child. - i = current.update_child_priority(i); - current = &mut current.children[i]; - continue 'walk; - } - } - - // We couldn't find a matching child. - // - // If we're not inserting a wildcard we have to create a child. - if (!matches!(next, b'{') || remaining.is_escaped(0)) - && current.node_type != NodeType::CatchAll - { - current.indices.push(next); - let mut child = current.add_child(Node::default()); - child = current.update_child_priority(child); - - // Insert into the newly created node. - let last = current.children[child].insert_route(remaining, val)?; - last.remapping = remapping; - return Ok(()); - } - - // We're trying to insert a wildcard. - // - // If this node already has a wildcard child, we have to make sure it matches. - if current.wild_child { - // Wildcards are always the last child. - current = current.children.last_mut().unwrap(); - current.priority += 1; - - // Make sure the route parameter matches. - if let Some(wildcard) = remaining.get(..current.prefix.len()) { - if *wildcard != *current.prefix { - return Err(InsertError::conflict(&route, remaining, current)); - } - } - - // Catch-all routes cannot have children. - if current.node_type == NodeType::CatchAll { - return Err(InsertError::conflict(&route, remaining, current)); - } - - // Continue with the wildcard node. - continue 'walk; - } - - // Otherwise, create a new node for the wildcard and insert the route. - let last = current.insert_route(remaining, val)?; - last.remapping = remapping; - return Ok(()); - } - } - - /// Removes a route from the tree, returning the value if the route already existed. - /// - /// The provided path should be the same as the one used to insert the route, including - /// wildcards. - pub fn remove(&mut self, route: String) -> Option<T> { - let route = UnescapedRoute::new(route.into_bytes()); - let (route, remapping) = normalize_params(route).ok()?; - let mut remaining = route.unescaped(); - - // Check if we are removing the root node. - if remaining == self.prefix.unescaped() { - let value = self.value.take().map(UnsafeCell::into_inner); - - // If the root node has no children, we can reset it. - if self.children.is_empty() { - *self = Node::default(); - } - - return value; - } - - let mut current = self; - 'walk: loop { - // The path is longer than this node's prefix, search deeper. - if remaining.len() > current.prefix.len() { - let (prefix, rest) = remaining.split_at(current.prefix.len()); - - // The prefix matches. - if prefix == current.prefix.unescaped() { - let first = rest[0]; - remaining = rest; - - // If there is a single child node, we can continue searching in the child. - if current.children.len() == 1 { - // The route matches, remove the node. - if current.children[0].prefix.unescaped() == remaining { - return current.remove_child(0, &remapping); - } - - // Otherwise, continue searching. - current = &mut current.children[0]; - continue 'walk; - } - - // Find a child node that matches the next character in the route. - if let Some(i) = current.indices.iter().position(|&c| c == first) { - // The route matches, remove the node. - if current.children[i].prefix.unescaped() == remaining { - return current.remove_child(i, &remapping); - } - - // Otherwise, continue searching. - current = &mut current.children[i]; - continue 'walk; - } - - // If the node has a matching wildcard child, continue searching in the child. - if current.wild_child - && remaining.first().zip(remaining.get(2)) == Some((&b'{', &b'}')) - { - // The route matches, remove the node. - if current.children.last_mut().unwrap().prefix.unescaped() == remaining { - return current.remove_child(current.children.len() - 1, &remapping); - } - - current = current.children.last_mut().unwrap(); - continue 'walk; - } - } - } - - // Could not find a match. - return None; - } - } - - /// Remove the child node at the given index, if the route parameters match. - fn remove_child(&mut self, i: usize, remapping: &ParamRemapping) -> Option<T> { - // Require an exact match to remove a route. - // - // For example, `/{a}` cannot be used to remove `/{b}`. - if self.children[i].remapping != *remapping { - return None; - } - - // If the node does not have any children, we can remove it completely. - let value = if self.children[i].children.is_empty() { - // Removing a single child with no indices. - if self.children.len() == 1 && self.indices.is_empty() { - self.wild_child = false; - self.children.remove(0).value.take() - } else { - // Remove the child node. - let child = self.children.remove(i); - - match child.node_type { - // Remove the index if we removed a static prefix. - NodeType::Static => { - self.indices.remove(i); - } - // Otherwise, we removed a wildcard. - _ => self.wild_child = false, - } - - child.value - } - } - // Otherwise, remove the value but preserve the node. - else { - self.children[i].value.take() - }; - - value.map(UnsafeCell::into_inner) - } - - // Adds a child to this node, keeping wildcards at the end. - fn add_child(&mut self, child: Node<T>) -> usize { - let len = self.children.len(); - - if self.wild_child && len > 0 { - self.children.insert(len - 1, child); - len - 1 - } else { - self.children.push(child); - len - } - } - - // Increments priority of the given child node, reordering the children if necessary. - // - // Returns the new index of the node. - fn update_child_priority(&mut self, i: usize) -> usize { - self.children[i].priority += 1; - let priority = self.children[i].priority; - - // Move the node to the front as necessary. - let mut updated = i; - while updated > 0 && self.children[updated - 1].priority < priority { - self.children.swap(updated - 1, updated); - updated -= 1; - } - - // Update the position of the indices to match. - if updated != i { - self.indices[updated..=i].rotate_right(1); - } - - updated - } - - // Insert a route at this node. - fn insert_route( - &mut self, - mut prefix: UnescapedRef<'_>, - val: T, - ) -> Result<&mut Node<T>, InsertError> { - let mut current = self; - - loop { - // Search for a wildcard segment. - let wildcard = match find_wildcard(prefix)? { - Some(wildcard) => wildcard, - // There is no wildcard, simply insert into the current node. - None => { - current.value = Some(UnsafeCell::new(val)); - current.prefix = prefix.to_owned(); - return Ok(current); - } - }; - - // Insering a catch-all route. - if prefix[wildcard.clone()][1] == b'*' { - // Ensure there is no suffix after the parameter, e.g. `/foo/{*x}/bar`. - if wildcard.end != prefix.len() { - return Err(InsertError::InvalidCatchAll); - } - - // Add the prefix before the wildcard into the current node. - if wildcard.start > 0 { - current.prefix = prefix.slice_until(wildcard.start).to_owned(); - prefix = prefix.slice_off(wildcard.start); - } - - // Add the catch-all as a child node. - let child = Self { - prefix: prefix.to_owned(), - node_type: NodeType::CatchAll, - value: Some(UnsafeCell::new(val)), - priority: 1, - ..Self::default() - }; - - let i = current.add_child(child); - current.wild_child = true; - return Ok(&mut current.children[i]); - } - - // Otherwise, we're inserting a regular route parameter. - assert_eq!(prefix[wildcard.clone()][0], b'{'); - - // Add the prefix before the wildcard into the current node. - if wildcard.start > 0 { - current.prefix = prefix.slice_until(wildcard.start).to_owned(); - prefix = prefix.slice_off(wildcard.start); - } - - // Add the parameter as a child node. - let child = Self { - node_type: NodeType::Param, - prefix: prefix.slice_until(wildcard.len()).to_owned(), - ..Self::default() - }; - - let child = current.add_child(child); - current.wild_child = true; - current = &mut current.children[child]; - current.priority += 1; - - // If the route doesn't end in the wildcard, we have to insert the suffix as a child. - if wildcard.len() < prefix.len() { - prefix = prefix.slice_off(wildcard.len()); - let child = Self { - priority: 1, - ..Self::default() - }; - - let child = current.add_child(child); - current = &mut current.children[child]; - continue; - } - - // Finally, insert the value. - current.value = Some(UnsafeCell::new(val)); - return Ok(current); - } - } -} - -/// A wildcard node that was skipped during a tree search. -/// -/// Contains the state necessary to backtrack to the given node. -struct Skipped<'n, 'p, T> { - // The node that was skipped. - node: &'n Node<T>, - /// The path at the time we skipped this node. - path: &'p [u8], - // The number of parameters that were present. - params: usize, -} - -#[rustfmt::skip] -macro_rules! backtracker { - ($skipped_nodes:ident, $path:ident, $current:ident, $params:ident, $backtracking:ident, $walk:lifetime) => { - macro_rules! try_backtrack { - () => { - // Try backtracking to any matching wildcard nodes that we skipped while - // traversing the tree. - while let Some(skipped) = $skipped_nodes.pop() { - if skipped.path.ends_with($path) { - // Restore the search state. - $path = skipped.path; - $current = &skipped.node; - $params.truncate(skipped.params); - $backtracking = true; - continue $walk; - } - } - }; - } - }; -} - -impl<T> Node<T> { - // Returns the node matching the given path. - // - // Returning an `UnsafeCell` allows us to avoid duplicating the logic between `Node::at` and - // `Node::at_mut`, as Rust doesn't have a great way of abstracting over mutability. - pub fn at<'node, 'path>( - &'node self, - full_path: &'path [u8], - ) -> Result<(&'node UnsafeCell<T>, Params<'node, 'path>), MatchError> { - let mut current = self; - let mut path = full_path; - let mut backtracking = false; - let mut params = Params::new(); - let mut skipped_nodes: Vec<Skipped<'_, '_, T>> = Vec::new(); - - 'walk: loop { - // Initialize the backtracker. - backtracker!(skipped_nodes, path, current, params, backtracking, 'walk); - - // Reached the end of the search. - if path.len() <= current.prefix.len() { - // Check for an exact match. - if *path == *current.prefix { - // Found the matching value. - if let Some(ref value) = current.value { - // Remap the keys of any route parameters we accumulated during the search. - params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]); - return Ok((value, params)); - } - } - - // Try backtracking in case we skipped a wildcard that may match. - try_backtrack!(); - - // Otherwise, there are no matching routes in the tree. - return Err(MatchError::NotFound); - } - - // Otherwise, the path is longer than this node's prefix, search deeper. - let (prefix, rest) = path.split_at(current.prefix.len()); - - // The prefix does not match. - if *prefix != *current.prefix { - // Try backtracking in case we skipped a wildcard that may match. - try_backtrack!(); - - // Otherwise, there are no matching routes in the tree. - return Err(MatchError::NotFound); - } - - let previous = path; - path = rest; - - // If we are currently backtracking, avoid searching static children - // that we already searched. - if !backtracking { - let next = path[0]; - - // Find a child node that matches the next character in the path. - if let Some(i) = current.indices.iter().position(|&c| c == next) { - // Keep track of wildcard routes that we skip. - // - // We may end up needing to backtrack later in case we do not find a - // match. - if current.wild_child { - skipped_nodes.push(Skipped { - path: previous, - node: current, - params: params.len(), - }); - } - - // Continue searching. - current = ¤t.children[i]; - continue 'walk; - } - } - - // We didn't find a matching static child. - // - // If there are no wildcards, then there are no matching routes in the tree. - if !current.wild_child { - // Try backtracking in case we skipped a wildcard that may match. - try_backtrack!(); - return Err(MatchError::NotFound); - } - - // Continue searching in the wildcard child, which is kept at the end of the list. - current = current.children.last().unwrap(); - match current.node_type { - // Match against a route parameter. - NodeType::Param => { - // Check for more path segments. - let i = match path.iter().position(|&c| c == b'/') { - // Found another segment. - Some(i) => i, - // This is the last path segment. - None => { - let value = match current.value { - // Found the matching value. - Some(ref value) => value, - None => { - // Try backtracking in case we skipped a wildcard that may match. - try_backtrack!(); - - // Otherwise, there are no matching routes in the tree. - return Err(MatchError::NotFound); - } - }; - - // Store the parameter value. - // Parameters are normalized so the key is irrelevant for now. - params.push(b"", path); - - // Remap the keys of any route parameters we accumulated during the search. - params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]); - - return Ok((value, params)); - } - }; - - // Found another path segment. - let (param, rest) = path.split_at(i); - - // If there is a static child, continue the search. - if let [child] = current.children.as_slice() { - // Store the parameter value. - // Parameters are normalized so the key is irrelevant for now. - params.push(b"", param); - - // Continue searching. - path = rest; - current = child; - backtracking = false; - continue 'walk; - } - - // Try backtracking in case we skipped a wildcard that may match. - try_backtrack!(); - - // Otherwise, there are no matching routes in the tree. - return Err(MatchError::NotFound); - } - NodeType::CatchAll => { - // Catch-all segments are only allowed at the end of the route, meaning - // this node must contain the value. - let value = match current.value { - // Found the matching value. - Some(ref value) => value, - // Otherwise, there are no matching routes in the tree. - None => return Err(MatchError::NotFound), - }; - - // Remap the keys of any route parameters we accumulated during the search. - params.for_each_key_mut(|(i, key)| *key = ¤t.remapping[i]); - - // Store the final catch-all parameter (`{*...}`). - let key = ¤t.prefix[2..current.prefix.len() - 1]; - params.push(key, path); - - return Ok((value, params)); - } - _ => unreachable!(), - } - } - } - - /// Test helper that ensures route priorities are consistent. - #[cfg(feature = "__test_helpers")] - pub fn check_priorities(&self) -> Result<u32, (u32, u32)> { - let mut priority: u32 = 0; - for child in &self.children { - priority += child.check_priorities()?; - } - - if self.value.is_some() { - priority += 1; - } - - if self.priority != priority { - return Err((self.priority, priority)); - } - - Ok(priority) - } -} - -/// An ordered list of route parameters keys for a specific route. -/// -/// To support conflicting routes like `/{a}/foo` and `/{b}/bar`, route parameters -/// are normalized before being inserted into the tree. Parameter remapping are -/// stored at nodes containing values, containing the "true" names of all route parameters -/// for the given route. -type ParamRemapping = Vec<Vec<u8>>; - -/// Returns `path` with normalized route parameters, and a parameter remapping -/// to store at the node for this route. -/// -/// Note that the parameter remapping may contain unescaped characters. -fn normalize_params( - mut path: UnescapedRoute, -) -> Result<(UnescapedRoute, ParamRemapping), InsertError> { - let mut start = 0; - let mut original = ParamRemapping::new(); - - // Parameter names are normalized alphabetically. - let mut next = b'a'; - - loop { - // Find a wildcard to normalize. - let mut wildcard = match find_wildcard(path.as_ref().slice_off(start))? { - Some(wildcard) => wildcard, - // No wildcard, we are done. - None => return Ok((path, original)), - }; - - wildcard.start += start; - wildcard.end += start; - - // Ensure the parameter has a valid name. - if wildcard.len() < 2 { - return Err(InsertError::InvalidParam); - } - - // We don't need to normalize catch-all parameters, as they are always - // at the end of a route. - if path[wildcard.clone()][1] == b'*' { - start = wildcard.end; - continue; - } - - // Normalize the parameter. - let removed = path.splice(wildcard.clone(), vec![b'{', next, b'}']); - - // Preserve the original name for remapping. - let mut removed = removed.skip(1).collect::<Vec<_>>(); - removed.pop(); - original.push(removed); - - next += 1; - if next > b'z' { - panic!("Too many route parameters."); - } - - // Continue the search after the parameter we just normalized. - start = wildcard.start + 3; - } -} - -/// Restores `route` to it's original, denormalized form. -pub(crate) fn denormalize_params(route: &mut UnescapedRoute, params: &ParamRemapping) { - let mut start = 0; - let mut i = 0; - - loop { - // Find a wildcard to denormalize. - let mut wildcard = match find_wildcard(route.as_ref().slice_off(start)).unwrap() { - Some(w) => w, - None => return, - }; - - wildcard.start += start; - wildcard.end += start; - - // Get the corresponding parameter remapping. - let mut next = match params.get(i) { - Some(param) => param.clone(), - None => return, - }; - - // Denormalize this parameter. - next.insert(0, b'{'); - next.push(b'}'); - let _ = route.splice(wildcard.clone(), next.clone()); - - i += 1; - start = wildcard.start + next.len(); - } -} - -// Searches for a wildcard segment and checks the path for invalid characters. -fn find_wildcard(path: UnescapedRef<'_>) -> Result<Option<Range<usize>>, InsertError> { - for (start, &c) in path.iter().enumerate() { - // Found an unescaped closing brace without a corresponding opening brace. - if c == b'}' && !path.is_escaped(start) { - return Err(InsertError::InvalidParam); - } - - // Keep going until we find an unescaped opening brace. - if c != b'{' || path.is_escaped(start) { - continue; - } - - // Ensure there is a non-empty parameter name. - if path.get(start + 1) == Some(&b'}') { - return Err(InsertError::InvalidParam); - } - - // Find the corresponding closing brace. - for (i, &c) in path.iter().enumerate().skip(start + 2) { - match c { - b'}' => { - // This closing brace was escaped, keep searching. - if path.is_escaped(i) { - continue; - } - - // Ensure catch-all parameters have a non-empty name. - if path.get(i - 1) == Some(&b'*') { - return Err(InsertError::InvalidParam); - } - - if let Some(&c) = path.get(i + 1) { - // Prefixes after route parameters are not supported. - if c != b'/' { - return Err(InsertError::InvalidParamSegment); - } - } - - return Ok(Some(start..i + 1)); - } - // `*` and `/` are invalid in parameter names. - b'*' | b'/' => return Err(InsertError::InvalidParam), - _ => {} - } - } - - // Missing closing brace. - return Err(InsertError::InvalidParam); - } - - Ok(None) -} - -impl<T> Clone for Node<T> -where - T: Clone, -{ - fn clone(&self) -> Self { - let value = self.value.as_ref().map(|value| { - // Safety: We only expose `&mut T` through `&mut self`. - let value = unsafe { &*value.get() }; - UnsafeCell::new(value.clone()) - }); - - Self { - value, - prefix: self.prefix.clone(), - wild_child: self.wild_child, - node_type: self.node_type.clone(), - indices: self.indices.clone(), - children: self.children.clone(), - remapping: self.remapping.clone(), - priority: self.priority, - } - } -} - -impl<T> Default for Node<T> { - fn default() -> Self { - Self { - remapping: ParamRemapping::new(), - prefix: UnescapedRoute::default(), - wild_child: false, - node_type: NodeType::Static, - indices: Vec::new(), - children: Vec::new(), - value: None, - priority: 0, - } - } -} - -impl<T> fmt::Debug for Node<T> -where - T: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // Safety: We only expose `&mut T` through `&mut self`. - let value = unsafe { self.value.as_ref().map(|x| &*x.get()) }; - - let mut f = f.debug_struct("Node"); - f.field("value", &value) - .field("prefix", &self.prefix) - .field("node_type", &self.node_type) - .field("children", &self.children); - - // Extra information for debugging purposes. - #[cfg(test)] - { - let indices = self - .indices - .iter() - .map(|&x| char::from_u32(x as _)) - .collect::<Vec<_>>(); - - let params = self - .remapping - .iter() - .map(|x| std::str::from_utf8(x).unwrap()) - .collect::<Vec<_>>(); - - f.field("indices", &indices).field("params", ¶ms); - } - - f.finish() - } -} diff --git a/vendor/matchit/tests/insert.rs b/vendor/matchit/tests/insert.rs deleted file mode 100644 index 5513c1c6..00000000 --- a/vendor/matchit/tests/insert.rs +++ /dev/null @@ -1,243 +0,0 @@ -use matchit::{InsertError, Router}; - -struct InsertTest(Vec<(&'static str, Result<(), InsertError>)>); - -impl InsertTest { - fn run(self) { - let mut router = Router::new(); - for (route, expected) in self.0 { - let got = router.insert(route, route.to_owned()); - assert_eq!(got, expected, "{route}"); - } - } -} - -fn conflict(with: &'static str) -> InsertError { - InsertError::Conflict { with: with.into() } -} - -#[test] -fn wildcard_conflict() { - InsertTest(vec![ - ("/cmd/{tool}/{sub}", Ok(())), - ("/cmd/vet", Ok(())), - ("/foo/bar", Ok(())), - ("/foo/{name}", Ok(())), - ("/foo/{names}", Err(conflict("/foo/{name}"))), - ("/cmd/{*path}", Err(conflict("/cmd/{tool}/{sub}"))), - ("/cmd/{xxx}/names", Ok(())), - ("/cmd/{tool}/{xxx}/foo", Ok(())), - ("/src/{*filepath}", Ok(())), - ("/src/{file}", Err(conflict("/src/{*filepath}"))), - ("/src/static.json", Ok(())), - ("/src/$filepathx", Ok(())), - ("/src/", Ok(())), - ("/src/foo/bar", Ok(())), - ("/src1/", Ok(())), - ("/src1/{*filepath}", Ok(())), - ("/src2{*filepath}", Ok(())), - ("/src2/{*filepath}", Ok(())), - ("/src2/", Ok(())), - ("/src2", Ok(())), - ("/src3", Ok(())), - ("/src3/{*filepath}", Ok(())), - ("/search/{query}", Ok(())), - ("/search/valid", Ok(())), - ("/user_{name}", Ok(())), - ("/user_x", Ok(())), - ("/user_{bar}", Err(conflict("/user_{name}"))), - ("/id{id}", Ok(())), - ("/id/{id}", Ok(())), - ]) - .run() -} - -#[test] -fn invalid_catchall() { - InsertTest(vec![ - ("/non-leading-{*catchall}", Ok(())), - ("/foo/bar{*catchall}", Ok(())), - ("/src/{*filepath}/x", Err(InsertError::InvalidCatchAll)), - ("/src2/", Ok(())), - ("/src2/{*filepath}/x", Err(InsertError::InvalidCatchAll)), - ]) - .run() -} - -#[test] -fn catchall_root_conflict() { - InsertTest(vec![("/", Ok(())), ("/{*filepath}", Ok(()))]).run() -} - -#[test] -fn child_conflict() { - InsertTest(vec![ - ("/cmd/vet", Ok(())), - ("/cmd/{tool}", Ok(())), - ("/cmd/{tool}/{sub}", Ok(())), - ("/cmd/{tool}/misc", Ok(())), - ("/cmd/{tool}/{bad}", Err(conflict("/cmd/{tool}/{sub}"))), - ("/src/AUTHORS", Ok(())), - ("/src/{*filepath}", Ok(())), - ("/user_x", Ok(())), - ("/user_{name}", Ok(())), - ("/id/{id}", Ok(())), - ("/id{id}", Ok(())), - ("/{id}", Ok(())), - ("/{*filepath}", Err(conflict("/{id}"))), - ]) - .run() -} - -#[test] -fn duplicates() { - InsertTest(vec![ - ("/", Ok(())), - ("/", Err(conflict("/"))), - ("/doc/", Ok(())), - ("/doc/", Err(conflict("/doc/"))), - ("/src/{*filepath}", Ok(())), - ("/src/{*filepath}", Err(conflict("/src/{*filepath}"))), - ("/search/{query}", Ok(())), - ("/search/{query}", Err(conflict("/search/{query}"))), - ("/user_{name}", Ok(())), - ("/user_{name}", Err(conflict("/user_{name}"))), - ]) - .run() -} - -#[test] -fn unnamed_param() { - InsertTest(vec![ - ("/{}", Err(InsertError::InvalidParam)), - ("/user{}/", Err(InsertError::InvalidParam)), - ("/cmd/{}/", Err(InsertError::InvalidParam)), - ("/src/{*}", Err(InsertError::InvalidParam)), - ]) - .run() -} - -#[test] -fn double_params() { - InsertTest(vec![ - ("/{foo}{bar}", Err(InsertError::InvalidParamSegment)), - ("/{foo}{bar}/", Err(InsertError::InvalidParamSegment)), - ("/{foo}{{*bar}/", Err(InsertError::InvalidParamSegment)), - ]) - .run() -} - -#[test] -fn normalized_conflict() { - InsertTest(vec![ - ("/x/{foo}/bar", Ok(())), - ("/x/{bar}/bar", Err(conflict("/x/{foo}/bar"))), - ("/{y}/bar/baz", Ok(())), - ("/{y}/baz/baz", Ok(())), - ("/{z}/bar/bat", Ok(())), - ("/{z}/bar/baz", Err(conflict("/{y}/bar/baz"))), - ]) - .run() -} - -#[test] -fn more_conflicts() { - InsertTest(vec![ - ("/con{tact}", Ok(())), - ("/who/are/{*you}", Ok(())), - ("/who/foo/hello", Ok(())), - ("/whose/{users}/{name}", Ok(())), - ("/who/are/foo", Ok(())), - ("/who/are/foo/bar", Ok(())), - ("/con{nection}", Err(conflict("/con{tact}"))), - ( - "/whose/{users}/{user}", - Err(conflict("/whose/{users}/{name}")), - ), - ]) - .run() -} - -#[test] -fn catchall_static_overlap() { - InsertTest(vec![ - ("/bar", Ok(())), - ("/bar/", Ok(())), - ("/bar/{*foo}", Ok(())), - ]) - .run(); - - InsertTest(vec![ - ("/foo", Ok(())), - ("/{*bar}", Ok(())), - ("/bar", Ok(())), - ("/baz", Ok(())), - ("/baz/{split}", Ok(())), - ("/", Ok(())), - ("/{*bar}", Err(conflict("/{*bar}"))), - ("/{*zzz}", Err(conflict("/{*bar}"))), - ("/{xxx}", Err(conflict("/{*bar}"))), - ]) - .run(); - - InsertTest(vec![ - ("/{*bar}", Ok(())), - ("/bar", Ok(())), - ("/bar/x", Ok(())), - ("/bar_{x}", Ok(())), - ("/bar_{x}", Err(conflict("/bar_{x}"))), - ("/bar_{x}/y", Ok(())), - ("/bar/{x}", Ok(())), - ]) - .run(); -} - -#[test] -fn duplicate_conflict() { - InsertTest(vec![ - ("/hey", Ok(())), - ("/hey/users", Ok(())), - ("/hey/user", Ok(())), - ("/hey/user", Err(conflict("/hey/user"))), - ]) - .run() -} - -#[test] -fn invalid_param() { - InsertTest(vec![ - ("{", Err(InsertError::InvalidParam)), - ("}", Err(InsertError::InvalidParam)), - ("x{y", Err(InsertError::InvalidParam)), - ("x}", Err(InsertError::InvalidParam)), - ("/{foo}s", Err(InsertError::InvalidParamSegment)), - ]) - .run(); -} - -#[test] -fn escaped_param() { - InsertTest(vec![ - ("{{", Ok(())), - ("}}", Ok(())), - ("xx}}", Ok(())), - ("}}yy", Ok(())), - ("}}yy{{}}", Ok(())), - ("}}yy{{}}{{}}y{{", Ok(())), - ("}}yy{{}}{{}}y{{", Err(conflict("}yy{}{}y{"))), - ("/{{yy", Ok(())), - ("/{yy}", Ok(())), - ("/foo", Ok(())), - ("/foo/{{", Ok(())), - ("/foo/{{/{x}", Ok(())), - ("/foo/{ba{{r}", Ok(())), - ("/bar/{ba}}r}", Ok(())), - ("/xxx/{x{{}}y}", Ok(())), - ]) - .run() -} - -#[test] -fn bare_catchall() { - InsertTest(vec![("{*foo}", Ok(())), ("foo/{*bar}", Ok(()))]).run() -} diff --git a/vendor/matchit/tests/match.rs b/vendor/matchit/tests/match.rs deleted file mode 100644 index 90130fbc..00000000 --- a/vendor/matchit/tests/match.rs +++ /dev/null @@ -1,1047 +0,0 @@ -use matchit::{MatchError, Router}; - -// https://github.com/ibraheemdev/matchit/issues/22 -#[test] -fn partial_overlap() { - let mut x = Router::new(); - x.insert("/foo_bar", "Welcome!").unwrap(); - x.insert("/foo/bar", "Welcome!").unwrap(); - assert_eq!(x.at("/foo/").unwrap_err(), MatchError::NotFound); - - let mut x = Router::new(); - x.insert("/foo", "Welcome!").unwrap(); - x.insert("/foo/bar", "Welcome!").unwrap(); - assert_eq!(x.at("/foo/").unwrap_err(), MatchError::NotFound); -} - -// https://github.com/ibraheemdev/matchit/issues/31 -#[test] -fn wildcard_overlap() { - let mut router = Router::new(); - router.insert("/path/foo", "foo").unwrap(); - router.insert("/path/{*rest}", "wildcard").unwrap(); - - assert_eq!(router.at("/path/foo").map(|m| *m.value), Ok("foo")); - assert_eq!(router.at("/path/bar").map(|m| *m.value), Ok("wildcard")); - assert_eq!(router.at("/path/foo/").map(|m| *m.value), Ok("wildcard")); - - let mut router = Router::new(); - router.insert("/path/foo/{arg}", "foo").unwrap(); - router.insert("/path/{*rest}", "wildcard").unwrap(); - - assert_eq!(router.at("/path/foo/myarg").map(|m| *m.value), Ok("foo")); - assert_eq!( - router.at("/path/foo/myarg/").map(|m| *m.value), - Ok("wildcard") - ); - assert_eq!( - router.at("/path/foo/myarg/bar/baz").map(|m| *m.value), - Ok("wildcard") - ); -} - -// https://github.com/ibraheemdev/matchit/issues/12 -#[test] -fn overlapping_param_backtracking() { - let mut matcher = Router::new(); - - matcher.insert("/{object}/{id}", "object with id").unwrap(); - matcher - .insert("/secret/{id}/path", "secret with id and path") - .unwrap(); - - let matched = matcher.at("/secret/978/path").unwrap(); - assert_eq!(matched.params.get("id"), Some("978")); - - let matched = matcher.at("/something/978").unwrap(); - assert_eq!(matched.params.get("id"), Some("978")); - assert_eq!(matched.params.get("object"), Some("something")); - - let matched = matcher.at("/secret/978").unwrap(); - assert_eq!(matched.params.get("id"), Some("978")); -} - -struct MatchTest { - routes: Vec<&'static str>, - matches: Vec<( - &'static str, - &'static str, - Result<Vec<(&'static str, &'static str)>, ()>, - )>, -} - -impl MatchTest { - fn run(self) { - let mut router = Router::new(); - - for route in self.routes { - assert_eq!(router.insert(route, route.to_owned()), Ok(()), "{route}"); - } - - router.check_priorities().unwrap(); - - for (path, route, params) in self.matches { - match router.at(path) { - Ok(x) => { - assert_eq!(x.value, route); - - let got = x.params.iter().collect::<Vec<_>>(); - assert_eq!(params.unwrap(), got); - - router.at_mut(path).unwrap().value.push_str("Z"); - assert!(router.at(path).unwrap().value.contains("Z")); - router.at_mut(path).unwrap().value.pop(); - } - Err(_) => params.unwrap_err(), - } - } - } -} - -macro_rules! p { - ($($k:expr => $v:expr),* $(,)?) => { - Ok(vec![$(($k, $v)),*]) - }; -} - -// https://github.com/ibraheemdev/matchit/issues/42 -#[test] -fn bare_catchall() { - MatchTest { - routes: vec!["{*foo}", "foo/{*bar}"], - matches: vec![ - ("x/y", "{*foo}", p! { "foo" => "x/y" }), - ("/x/y", "{*foo}", p! { "foo" => "/x/y" }), - ("/foo/x/y", "{*foo}", p! { "foo" => "/foo/x/y" }), - ("foo/x/y", "foo/{*bar}", p! { "bar" => "x/y" }), - ], - } - .run() -} - -#[test] -fn normalized() { - MatchTest { - routes: vec![ - "/x/{foo}/bar", - "/x/{bar}/baz", - "/{foo}/{baz}/bax", - "/{foo}/{bar}/baz", - "/{fod}/{baz}/{bax}/foo", - "/{fod}/baz/bax/foo", - "/{foo}/baz/bax", - "/{bar}/{bay}/bay", - "/s", - "/s/s", - "/s/s/s", - "/s/s/s/s", - "/s/s/{s}/x", - "/s/s/{y}/d", - ], - matches: vec![ - ("/x/foo/bar", "/x/{foo}/bar", p! { "foo" => "foo" }), - ("/x/foo/baz", "/x/{bar}/baz", p! { "bar" => "foo" }), - ( - "/y/foo/baz", - "/{foo}/{bar}/baz", - p! { "foo" => "y", "bar" => "foo" }, - ), - ( - "/y/foo/bax", - "/{foo}/{baz}/bax", - p! { "foo" => "y", "baz" => "foo" }, - ), - ( - "/y/baz/baz", - "/{foo}/{bar}/baz", - p! { "foo" => "y", "bar" => "baz" }, - ), - ("/y/baz/bax/foo", "/{fod}/baz/bax/foo", p! { "fod" => "y" }), - ( - "/y/baz/b/foo", - "/{fod}/{baz}/{bax}/foo", - p! { "fod" => "y", "baz" => "baz", "bax" => "b" }, - ), - ("/y/baz/bax", "/{foo}/baz/bax", p! { "foo" => "y" }), - ( - "/z/bar/bay", - "/{bar}/{bay}/bay", - p! { "bar" => "z", "bay" => "bar" }, - ), - ("/s", "/s", p! {}), - ("/s/s", "/s/s", p! {}), - ("/s/s/s", "/s/s/s", p! {}), - ("/s/s/s/s", "/s/s/s/s", p! {}), - ("/s/s/s/x", "/s/s/{s}/x", p! { "s" => "s" }), - ("/s/s/s/d", "/s/s/{y}/d", p! { "y" => "s" }), - ], - } - .run() -} - -#[test] -fn blog() { - MatchTest { - routes: vec![ - "/{page}", - "/posts/{year}/{month}/{post}", - "/posts/{year}/{month}/index", - "/posts/{year}/top", - "/static/{*path}", - "/favicon.ico", - ], - matches: vec![ - ("/about", "/{page}", p! { "page" => "about" }), - ( - "/posts/2021/01/rust", - "/posts/{year}/{month}/{post}", - p! { "year" => "2021", "month" => "01", "post" => "rust" }, - ), - ( - "/posts/2021/01/index", - "/posts/{year}/{month}/index", - p! { "year" => "2021", "month" => "01" }, - ), - ( - "/posts/2021/top", - "/posts/{year}/top", - p! { "year" => "2021" }, - ), - ( - "/static/foo.png", - "/static/{*path}", - p! { "path" => "foo.png" }, - ), - ("/favicon.ico", "/favicon.ico", p! {}), - ], - } - .run() -} - -#[test] -fn double_overlap() { - MatchTest { - routes: vec![ - "/{object}/{id}", - "/secret/{id}/path", - "/secret/978", - "/other/{object}/{id}/", - "/other/an_object/{id}", - "/other/static/path", - "/other/long/static/path/", - ], - matches: vec![ - ( - "/secret/978/path", - "/secret/{id}/path", - p! { "id" => "978" }, - ), - ( - "/some_object/978", - "/{object}/{id}", - p! { "object" => "some_object", "id" => "978" }, - ), - ("/secret/978", "/secret/978", p! {}), - ("/super_secret/978/", "/{object}/{id}", Err(())), - ( - "/other/object/1/", - "/other/{object}/{id}/", - p! { "object" => "object", "id" => "1" }, - ), - ("/other/object/1/2", "/other/{object}/{id}", Err(())), - ( - "/other/an_object/1", - "/other/an_object/{id}", - p! { "id" => "1" }, - ), - ("/other/static/path", "/other/static/path", p! {}), - ( - "/other/long/static/path/", - "/other/long/static/path/", - p! {}, - ), - ], - } - .run() -} - -#[test] -fn catchall_off_by_one() { - MatchTest { - routes: vec!["/foo/{*catchall}", "/bar", "/bar/", "/bar/{*catchall}"], - matches: vec![ - ("/foo", "", Err(())), - ("/foo/", "", Err(())), - ("/foo/x", "/foo/{*catchall}", p! { "catchall" => "x" }), - ("/bar", "/bar", p! {}), - ("/bar/", "/bar/", p! {}), - ("/bar/x", "/bar/{*catchall}", p! { "catchall" => "x" }), - ], - } - .run() -} - -#[test] -fn overlap() { - MatchTest { - routes: vec![ - "/foo", - "/bar", - "/{*bar}", - "/baz", - "/baz/", - "/baz/x", - "/baz/{xxx}", - "/", - "/xxx/{*x}", - "/xxx/", - ], - matches: vec![ - ("/foo", "/foo", p! {}), - ("/bar", "/bar", p! {}), - ("/baz", "/baz", p! {}), - ("/baz/", "/baz/", p! {}), - ("/baz/x", "/baz/x", p! {}), - ("/???", "/{*bar}", p! { "bar" => "???" }), - ("/", "/", p! {}), - ("", "", Err(())), - ("/xxx/y", "/xxx/{*x}", p! { "x" => "y" }), - ("/xxx/", "/xxx/", p! {}), - ("/xxx", "/{*bar}", p! { "bar" => "xxx" }), - ], - } - .run() -} - -#[test] -fn missing_trailing_slash_param() { - MatchTest { - routes: vec!["/foo/{object}/{id}", "/foo/bar/baz", "/foo/secret/978/"], - matches: vec![ - ("/foo/secret/978/", "/foo/secret/978/", p! {}), - ( - "/foo/secret/978", - "/foo/{object}/{id}", - p! { "object" => "secret", "id" => "978" }, - ), - ], - } - .run() -} - -#[test] -fn extra_trailing_slash_param() { - MatchTest { - routes: vec!["/foo/{object}/{id}", "/foo/bar/baz", "/foo/secret/978"], - matches: vec![ - ("/foo/secret/978/", "", Err(())), - ("/foo/secret/978", "/foo/secret/978", p! {}), - ], - } - .run() -} - -#[test] -fn missing_trailing_slash_catch_all() { - MatchTest { - routes: vec!["/foo/{*bar}", "/foo/bar/baz", "/foo/secret/978/"], - matches: vec![ - ( - "/foo/secret/978", - "/foo/{*bar}", - p! { "bar" => "secret/978" }, - ), - ("/foo/secret/978/", "/foo/secret/978/", p! {}), - ], - } - .run() -} - -#[test] -fn extra_trailing_slash_catch_all() { - MatchTest { - routes: vec!["/foo/{*bar}", "/foo/bar/baz", "/foo/secret/978"], - matches: vec![ - ( - "/foo/secret/978/", - "/foo/{*bar}", - p! { "bar" => "secret/978/" }, - ), - ("/foo/secret/978", "/foo/secret/978", p! {}), - ], - } - .run() -} - -#[test] -fn double_overlap_trailing_slash() { - MatchTest { - routes: vec![ - "/{object}/{id}", - "/secret/{id}/path", - "/secret/978/", - "/other/{object}/{id}/", - "/other/an_object/{id}", - "/other/static/path", - "/other/long/static/path/", - ], - matches: vec![ - ("/secret/978/path/", "", Err(())), - ("/object/id/", "", Err(())), - ("/object/id/path", "", Err(())), - ("/other/object/1", "", Err(())), - ("/other/object/1/2", "", Err(())), - ( - "/other/an_object/1/", - "/other/{object}/{id}/", - p! { "object" => "an_object", "id" => "1" }, - ), - ( - "/other/static/path/", - "/other/{object}/{id}/", - p! { "object" => "static", "id" => "path" }, - ), - ("/other/long/static/path", "", Err(())), - ("/other/object/static/path", "", Err(())), - ], - } - .run() -} - -#[test] -fn trailing_slash_overlap() { - MatchTest { - routes: vec!["/foo/{x}/baz/", "/foo/{x}/baz", "/foo/bar/bar"], - matches: vec![ - ("/foo/x/baz/", "/foo/{x}/baz/", p! { "x" => "x" }), - ("/foo/x/baz", "/foo/{x}/baz", p! { "x" => "x" }), - ("/foo/bar/bar", "/foo/bar/bar", p! {}), - ], - } - .run() -} - -#[test] -fn trailing_slash() { - MatchTest { - routes: vec![ - "/hi", - "/b/", - "/search/{query}", - "/cmd/{tool}/", - "/src/{*filepath}", - "/x", - "/x/y", - "/y/", - "/y/z", - "/0/{id}", - "/0/{id}/1", - "/1/{id}/", - "/1/{id}/2", - "/aa", - "/a/", - "/admin", - "/admin/static", - "/admin/{category}", - "/admin/{category}/{page}", - "/doc", - "/doc/rust_faq.html", - "/doc/rust1.26.html", - "/no/a", - "/no/b", - "/no/a/b/{*other}", - "/api/{page}/{name}", - "/api/hello/{name}/bar/", - "/api/bar/{name}", - "/api/baz/foo", - "/api/baz/foo/bar", - "/foo/{p}", - ], - matches: vec![ - ("/hi/", "", Err(())), - ("/b", "", Err(())), - ("/search/rustacean/", "", Err(())), - ("/cmd/vet", "", Err(())), - ("/src", "", Err(())), - ("/src/", "", Err(())), - ("/x/", "", Err(())), - ("/y", "", Err(())), - ("/0/rust/", "", Err(())), - ("/1/rust", "", Err(())), - ("/a", "", Err(())), - ("/admin/", "", Err(())), - ("/doc/", "", Err(())), - ("/admin/static/", "", Err(())), - ("/admin/cfg/", "", Err(())), - ("/admin/cfg/users/", "", Err(())), - ("/api/hello/x/bar", "", Err(())), - ("/api/baz/foo/", "", Err(())), - ("/api/baz/bax/", "", Err(())), - ("/api/bar/huh/", "", Err(())), - ("/api/baz/foo/bar/", "", Err(())), - ("/api/world/abc/", "", Err(())), - ("/foo/pp/", "", Err(())), - ("/", "", Err(())), - ("/no", "", Err(())), - ("/no/", "", Err(())), - ("/no/a/b", "", Err(())), - ("/no/a/b/", "", Err(())), - ("/_", "", Err(())), - ("/_/", "", Err(())), - ("/api", "", Err(())), - ("/api/", "", Err(())), - ("/api/hello/x/foo", "", Err(())), - ("/api/baz/foo/bad", "", Err(())), - ("/foo/p/p", "", Err(())), - ], - } - .run() -} - -#[test] -fn backtracking_trailing_slash() { - MatchTest { - routes: vec!["/a/{b}/{c}", "/a/b/{c}/d/"], - matches: vec![("/a/b/c/d", "", Err(()))], - } - .run() -} - -#[test] -fn root_trailing_slash() { - MatchTest { - routes: vec!["/foo", "/bar", "/{baz}"], - matches: vec![("/", "", Err(()))], - } - .run() -} - -#[test] -fn catchall_overlap() { - MatchTest { - routes: vec!["/yyy/{*x}", "/yyy{*x}"], - matches: vec![ - ("/yyy/y", "/yyy/{*x}", p! { "x" => "y" }), - ("/yyy/", "/yyy{*x}", p! { "x" => "/" }), - ], - } - .run(); -} - -#[test] -fn escaped() { - MatchTest { - routes: vec![ - "/", - "/{{", - "/}}", - "/{{x", - "/}}y{{", - "/xy{{", - "/{{/xyz", - "/{ba{{r}", - "/{ba{{r}/", - "/{ba{{r}/x", - "/baz/{xxx}", - "/baz/{xxx}/xy{{", - "/baz/{xxx}/}}xy{{{{", - "/{{/{x}", - "/xxx/", - "/xxx/{x}}{{}}}}{{}}{{{{}}y}", - ], - matches: vec![ - ("/", "/", p! {}), - ("/{", "/{{", p! {}), - ("/}", "/}}", p! {}), - ("/{x", "/{{x", p! {}), - ("/}y{", "/}}y{{", p! {}), - ("/xy{", "/xy{{", p! {}), - ("/{/xyz", "/{{/xyz", p! {}), - ("/foo", "/{ba{{r}", p! { "ba{r" => "foo" }), - ("/{{", "/{ba{{r}", p! { "ba{r" => "{{" }), - ("/{{}}/", "/{ba{{r}/", p! { "ba{r" => "{{}}" }), - ("/{{}}{{/x", "/{ba{{r}/x", p! { "ba{r" => "{{}}{{" }), - ("/baz/x", "/baz/{xxx}", p! { "xxx" => "x" }), - ("/baz/x/xy{", "/baz/{xxx}/xy{{", p! { "xxx" => "x" }), - ("/baz/x/xy{{", "", Err(())), - ("/baz/x/}xy{{", "/baz/{xxx}/}}xy{{{{", p! { "xxx" => "x" }), - ("/{/{{", "/{{/{x}", p! { "x" => "{{" }), - ("/xxx", "/{ba{{r}", p! { "ba{r" => "xxx" }), - ("/xxx/", "/xxx/", p!()), - ( - "/xxx/foo", - "/xxx/{x}}{{}}}}{{}}{{{{}}y}", - p! { "x}{}}{}{{}y" => "foo" }, - ), - ], - } - .run() -} - -#[test] -fn basic() { - MatchTest { - routes: vec![ - "/hi", - "/contact", - "/co", - "/c", - "/a", - "/ab", - "/doc/", - "/doc/rust_faq.html", - "/doc/rust1.26.html", - "/ʯ", - "/β", - "/sd!here", - "/sd$here", - "/sd&here", - "/sd'here", - "/sd(here", - "/sd)here", - "/sd+here", - "/sd,here", - "/sd;here", - "/sd=here", - ], - matches: vec![ - ("/a", "/a", p! {}), - ("", "/", Err(())), - ("/hi", "/hi", p! {}), - ("/contact", "/contact", p! {}), - ("/co", "/co", p! {}), - ("", "/con", Err(())), - ("", "/cona", Err(())), - ("", "/no", Err(())), - ("/ab", "/ab", p! {}), - ("/ʯ", "/ʯ", p! {}), - ("/β", "/β", p! {}), - ("/sd!here", "/sd!here", p! {}), - ("/sd$here", "/sd$here", p! {}), - ("/sd&here", "/sd&here", p! {}), - ("/sd'here", "/sd'here", p! {}), - ("/sd(here", "/sd(here", p! {}), - ("/sd)here", "/sd)here", p! {}), - ("/sd+here", "/sd+here", p! {}), - ("/sd,here", "/sd,here", p! {}), - ("/sd;here", "/sd;here", p! {}), - ("/sd=here", "/sd=here", p! {}), - ], - } - .run() -} - -#[test] -fn wildcard() { - MatchTest { - routes: vec![ - "/", - "/cmd/{tool}/", - "/cmd/{tool2}/{sub}", - "/cmd/whoami", - "/cmd/whoami/root", - "/cmd/whoami/root/", - "/src", - "/src/", - "/src/{*filepath}", - "/search/", - "/search/{query}", - "/search/actix-web", - "/search/google", - "/user_{name}", - "/user_{name}/about", - "/files/{dir}/{*filepath}", - "/doc/", - "/doc/rust_faq.html", - "/doc/rust1.26.html", - "/info/{user}/public", - "/info/{user}/project/{project}", - "/info/{user}/project/rustlang", - "/aa/{*xx}", - "/ab/{*xx}", - "/ab/hello{*xx}", - "/{cc}", - "/c1/{dd}/e", - "/c1/{dd}/e1", - "/{cc}/cc", - "/{cc}/{dd}/ee", - "/{cc}/{dd}/{ee}/ff", - "/{cc}/{dd}/{ee}/{ff}/gg", - "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", - "/get/test/abc/", - "/get/{param}/abc/", - "/something/{paramname}/thirdthing", - "/something/secondthing/test", - "/get/abc", - "/get/{param}", - "/get/abc/123abc", - "/get/abc/{param}", - "/get/abc/123abc/xxx8", - "/get/abc/123abc/{param}", - "/get/abc/123abc/xxx8/1234", - "/get/abc/123abc/xxx8/{param}", - "/get/abc/123abc/xxx8/1234/ffas", - "/get/abc/123abc/xxx8/1234/{param}", - "/get/abc/123abc/xxx8/1234/kkdd/12c", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - "/get/abc/{param}/test", - "/get/abc/123abd/{param}", - "/get/abc/123abddd/{param}", - "/get/abc/123/{param}", - "/get/abc/123abg/{param}", - "/get/abc/123abf/{param}", - "/get/abc/123abfff/{param}", - ], - matches: vec![ - ("/", "/", p! {}), - ("/cmd/test", "/cmd/{tool}/", Err(())), - ("/cmd/test/", "/cmd/{tool}/", p! { "tool" => "test" }), - ( - "/cmd/test/3", - "/cmd/{tool2}/{sub}", - p! { "tool2" => "test", "sub" => "3" }, - ), - ("/cmd/who", "/cmd/{tool}/", Err(())), - ("/cmd/who/", "/cmd/{tool}/", p! { "tool" => "who" }), - ("/cmd/whoami", "/cmd/whoami", p! {}), - ("/cmd/whoami/", "/cmd/{tool}/", p! { "tool" => "whoami" }), - ( - "/cmd/whoami/r", - "/cmd/{tool2}/{sub}", - p! { "tool2" => "whoami", "sub" => "r" }, - ), - ("/cmd/whoami/r/", "/cmd/{tool}/{sub}", Err(())), - ("/cmd/whoami/root", "/cmd/whoami/root", p! {}), - ("/cmd/whoami/root/", "/cmd/whoami/root/", p! {}), - ("/src", "/src", p! {}), - ("/src/", "/src/", p! {}), - ( - "/src/some/file.png", - "/src/{*filepath}", - p! { "filepath" => "some/file.png" }, - ), - ("/search/", "/search/", p! {}), - ( - "/search/actix", - "/search/{query}", - p! { "query" => "actix" }, - ), - ("/search/actix-web", "/search/actix-web", p! {}), - ( - "/search/someth!ng+in+ünìcodé", - "/search/{query}", - p! { "query" => "someth!ng+in+ünìcodé" }, - ), - ("/search/someth!ng+in+ünìcodé/", "", Err(())), - ( - "/user_rustacean", - "/user_{name}", - p! { "name" => "rustacean" }, - ), - ( - "/user_rustacean/about", - "/user_{name}/about", - p! { "name" => "rustacean" }, - ), - ( - "/files/js/inc/framework.js", - "/files/{dir}/{*filepath}", - p! { "dir" => "js", "filepath" => "inc/framework.js" }, - ), - ( - "/info/gordon/public", - "/info/{user}/public", - p! { "user" => "gordon" }, - ), - ( - "/info/gordon/project/rust", - "/info/{user}/project/{project}", - p! { "user" => "gordon", "project" => "rust" }, - ), - ( - "/info/gordon/project/rustlang", - "/info/{user}/project/rustlang", - p! { "user" => "gordon" }, - ), - ("/aa/", "/", Err(())), - ("/aa/aa", "/aa/{*xx}", p! { "xx" => "aa" }), - ("/ab/ab", "/ab/{*xx}", p! { "xx" => "ab" }), - ("/ab/hello-world", "/ab/hello{*xx}", p! { "xx" => "-world" }), - ("/a", "/{cc}", p! { "cc" => "a" }), - ("/all", "/{cc}", p! { "cc" => "all" }), - ("/d", "/{cc}", p! { "cc" => "d" }), - ("/ad", "/{cc}", p! { "cc" => "ad" }), - ("/dd", "/{cc}", p! { "cc" => "dd" }), - ("/dddaa", "/{cc}", p! { "cc" => "dddaa" }), - ("/aa", "/{cc}", p! { "cc" => "aa" }), - ("/aaa", "/{cc}", p! { "cc" => "aaa" }), - ("/aaa/cc", "/{cc}/cc", p! { "cc" => "aaa" }), - ("/ab", "/{cc}", p! { "cc" => "ab" }), - ("/abb", "/{cc}", p! { "cc" => "abb" }), - ("/abb/cc", "/{cc}/cc", p! { "cc" => "abb" }), - ("/allxxxx", "/{cc}", p! { "cc" => "allxxxx" }), - ("/alldd", "/{cc}", p! { "cc" => "alldd" }), - ("/all/cc", "/{cc}/cc", p! { "cc" => "all" }), - ("/a/cc", "/{cc}/cc", p! { "cc" => "a" }), - ("/c1/d/e", "/c1/{dd}/e", p! { "dd" => "d" }), - ("/c1/d/e1", "/c1/{dd}/e1", p! { "dd" => "d" }), - ( - "/c1/d/ee", - "/{cc}/{dd}/ee", - p! { "cc" => "c1", "dd" => "d" }, - ), - ("/cc/cc", "/{cc}/cc", p! { "cc" => "cc" }), - ("/ccc/cc", "/{cc}/cc", p! { "cc" => "ccc" }), - ("/deedwjfs/cc", "/{cc}/cc", p! { "cc" => "deedwjfs" }), - ("/acllcc/cc", "/{cc}/cc", p! { "cc" => "acllcc" }), - ("/get/test/abc/", "/get/test/abc/", p! {}), - ("/get/te/abc/", "/get/{param}/abc/", p! { "param" => "te" }), - ( - "/get/testaa/abc/", - "/get/{param}/abc/", - p! { "param" => "testaa" }, - ), - ("/get/xx/abc/", "/get/{param}/abc/", p! { "param" => "xx" }), - ("/get/tt/abc/", "/get/{param}/abc/", p! { "param" => "tt" }), - ("/get/a/abc/", "/get/{param}/abc/", p! { "param" => "a" }), - ("/get/t/abc/", "/get/{param}/abc/", p! { "param" => "t" }), - ("/get/aa/abc/", "/get/{param}/abc/", p! { "param" => "aa" }), - ( - "/get/abas/abc/", - "/get/{param}/abc/", - p! { "param" => "abas" }, - ), - ( - "/something/secondthing/test", - "/something/secondthing/test", - p! {}, - ), - ( - "/something/abcdad/thirdthing", - "/something/{paramname}/thirdthing", - p! { "paramname" => "abcdad" }, - ), - ( - "/something/secondthingaaaa/thirdthing", - "/something/{paramname}/thirdthing", - p! { "paramname" => "secondthingaaaa" }, - ), - ( - "/something/se/thirdthing", - "/something/{paramname}/thirdthing", - p! { "paramname" => "se" }, - ), - ( - "/something/s/thirdthing", - "/something/{paramname}/thirdthing", - p! { "paramname" => "s" }, - ), - ("/c/d/ee", "/{cc}/{dd}/ee", p! { "cc" => "c", "dd" => "d" }), - ( - "/c/d/e/ff", - "/{cc}/{dd}/{ee}/ff", - p! { "cc" => "c", "dd" => "d", "ee" => "e" }, - ), - ( - "/c/d/e/f/gg", - "/{cc}/{dd}/{ee}/{ff}/gg", - p! { "cc" => "c", "dd" => "d", "ee" => "e", "ff" => "f" }, - ), - ( - "/c/d/e/f/g/hh", - "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", - p! { "cc" => "c", "dd" => "d", "ee" => "e", "ff" => "f", "gg" => "g" }, - ), - ( - "/cc/dd/ee/ff/gg/hh", - "/{cc}/{dd}/{ee}/{ff}/{gg}/hh", - p! { "cc" => "cc", "dd" => "dd", "ee" => "ee", "ff" => "ff", "gg" => "gg" }, - ), - ("/get/abc", "/get/abc", p! {}), - ("/get/a", "/get/{param}", p! { "param" => "a" }), - ("/get/abz", "/get/{param}", p! { "param" => "abz" }), - ("/get/12a", "/get/{param}", p! { "param" => "12a" }), - ("/get/abcd", "/get/{param}", p! { "param" => "abcd" }), - ("/get/abc/123abc", "/get/abc/123abc", p! {}), - ("/get/abc/12", "/get/abc/{param}", p! { "param" => "12" }), - ( - "/get/abc/123ab", - "/get/abc/{param}", - p! { "param" => "123ab" }, - ), - ("/get/abc/xyz", "/get/abc/{param}", p! { "param" => "xyz" }), - ( - "/get/abc/123abcddxx", - "/get/abc/{param}", - p! { "param" => "123abcddxx" }, - ), - ("/get/abc/123abc/xxx8", "/get/abc/123abc/xxx8", p! {}), - ( - "/get/abc/123abc/x", - "/get/abc/123abc/{param}", - p! { "param" => "x" }, - ), - ( - "/get/abc/123abc/xxx", - "/get/abc/123abc/{param}", - p! { "param" => "xxx" }, - ), - ( - "/get/abc/123abc/abc", - "/get/abc/123abc/{param}", - p! { "param" => "abc" }, - ), - ( - "/get/abc/123abc/xxx8xxas", - "/get/abc/123abc/{param}", - p! { "param" => "xxx8xxas" }, - ), - ( - "/get/abc/123abc/xxx8/1234", - "/get/abc/123abc/xxx8/1234", - p! {}, - ), - ( - "/get/abc/123abc/xxx8/1", - "/get/abc/123abc/xxx8/{param}", - p! { "param" => "1" }, - ), - ( - "/get/abc/123abc/xxx8/123", - "/get/abc/123abc/xxx8/{param}", - p! { "param" => "123" }, - ), - ( - "/get/abc/123abc/xxx8/78k", - "/get/abc/123abc/xxx8/{param}", - p! { "param" => "78k" }, - ), - ( - "/get/abc/123abc/xxx8/1234xxxd", - "/get/abc/123abc/xxx8/{param}", - p! { "param" => "1234xxxd" }, - ), - ( - "/get/abc/123abc/xxx8/1234/ffas", - "/get/abc/123abc/xxx8/1234/ffas", - p! {}, - ), - ( - "/get/abc/123abc/xxx8/1234/f", - "/get/abc/123abc/xxx8/1234/{param}", - p! { "param" => "f" }, - ), - ( - "/get/abc/123abc/xxx8/1234/ffa", - "/get/abc/123abc/xxx8/1234/{param}", - p! { "param" => "ffa" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kka", - "/get/abc/123abc/xxx8/1234/{param}", - p! { "param" => "kka" }, - ), - ( - "/get/abc/123abc/xxx8/1234/ffas321", - "/get/abc/123abc/xxx8/1234/{param}", - p! { "param" => "ffas321" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/12c", - "/get/abc/123abc/xxx8/1234/kkdd/12c", - p! {}, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/1", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - p! { "param" => "1" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/12", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - p! { "param" => "12" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/12b", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - p! { "param" => "12b" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/34", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - p! { "param" => "34" }, - ), - ( - "/get/abc/123abc/xxx8/1234/kkdd/12c2e3", - "/get/abc/123abc/xxx8/1234/kkdd/{param}", - p! { "param" => "12c2e3" }, - ), - ( - "/get/abc/12/test", - "/get/abc/{param}/test", - p! { "param" => "12" }, - ), - ( - "/get/abc/123abdd/test", - "/get/abc/{param}/test", - p! { "param" => "123abdd" }, - ), - ( - "/get/abc/123abdddf/test", - "/get/abc/{param}/test", - p! { "param" => "123abdddf" }, - ), - ( - "/get/abc/123ab/test", - "/get/abc/{param}/test", - p! { "param" => "123ab" }, - ), - ( - "/get/abc/123abgg/test", - "/get/abc/{param}/test", - p! { "param" => "123abgg" }, - ), - ( - "/get/abc/123abff/test", - "/get/abc/{param}/test", - p! { "param" => "123abff" }, - ), - ( - "/get/abc/123abffff/test", - "/get/abc/{param}/test", - p! { "param" => "123abffff" }, - ), - ( - "/get/abc/123abd/test", - "/get/abc/123abd/{param}", - p! { "param" => "test" }, - ), - ( - "/get/abc/123abddd/test", - "/get/abc/123abddd/{param}", - p! { "param" => "test" }, - ), - ( - "/get/abc/123/test22", - "/get/abc/123/{param}", - p! { "param" => "test22" }, - ), - ( - "/get/abc/123abg/test", - "/get/abc/123abg/{param}", - p! { "param" => "test" }, - ), - ( - "/get/abc/123abf/testss", - "/get/abc/123abf/{param}", - p! { "param" => "testss" }, - ), - ( - "/get/abc/123abfff/te", - "/get/abc/123abfff/{param}", - p! { "param" => "te" }, - ), - ], - } - .run() -} diff --git a/vendor/matchit/tests/remove.rs b/vendor/matchit/tests/remove.rs deleted file mode 100644 index 3237ccde..00000000 --- a/vendor/matchit/tests/remove.rs +++ /dev/null @@ -1,265 +0,0 @@ -use matchit::Router; - -struct RemoveTest { - routes: Vec<&'static str>, - ops: Vec<(Operation, &'static str, Option<&'static str>)>, - remaining: Vec<&'static str>, -} - -enum Operation { - Insert, - Remove, -} - -use Operation::*; - -impl RemoveTest { - fn run(self) { - let mut router = Router::new(); - - for route in self.routes.iter() { - assert_eq!(router.insert(*route, route.to_owned()), Ok(()), "{route}"); - } - - for (op, route, expected) in self.ops.iter() { - match op { - Insert => { - assert_eq!(router.insert(*route, route), Ok(()), "{route}") - } - Remove => { - assert_eq!(router.remove(*route), *expected, "removing {route}",) - } - } - } - - for route in self.remaining { - assert!(matches!(router.at(route), Ok(_)), "remaining {route}"); - } - } -} - -#[test] -fn normalized() { - RemoveTest { - routes: vec![ - "/x/{foo}/bar", - "/x/{bar}/baz", - "/{foo}/{baz}/bax", - "/{foo}/{bar}/baz", - "/{fod}/{baz}/{bax}/foo", - "/{fod}/baz/bax/foo", - "/{foo}/baz/bax", - "/{bar}/{bay}/bay", - "/s", - "/s/s", - "/s/s/s", - "/s/s/s/s", - "/s/s/{s}/x", - "/s/s/{y}/d", - ], - ops: vec![ - (Remove, "/x/{foo}/bar", Some("/x/{foo}/bar")), - (Remove, "/x/{bar}/baz", Some("/x/{bar}/baz")), - (Remove, "/{foo}/{baz}/bax", Some("/{foo}/{baz}/bax")), - (Remove, "/{foo}/{bar}/baz", Some("/{foo}/{bar}/baz")), - ( - Remove, - "/{fod}/{baz}/{bax}/foo", - Some("/{fod}/{baz}/{bax}/foo"), - ), - (Remove, "/{fod}/baz/bax/foo", Some("/{fod}/baz/bax/foo")), - (Remove, "/{foo}/baz/bax", Some("/{foo}/baz/bax")), - (Remove, "/{bar}/{bay}/bay", Some("/{bar}/{bay}/bay")), - (Remove, "/s", Some("/s")), - (Remove, "/s/s", Some("/s/s")), - (Remove, "/s/s/s", Some("/s/s/s")), - (Remove, "/s/s/s/s", Some("/s/s/s/s")), - (Remove, "/s/s/{s}/x", Some("/s/s/{s}/x")), - (Remove, "/s/s/{y}/d", Some("/s/s/{y}/d")), - ], - remaining: vec![], - } - .run(); -} - -#[test] -fn test() { - RemoveTest { - routes: vec!["/home", "/home/{id}"], - ops: vec![ - (Remove, "/home", Some("/home")), - (Remove, "/home", None), - (Remove, "/home/{id}", Some("/home/{id}")), - (Remove, "/home/{id}", None), - ], - remaining: vec![], - } - .run(); -} - -#[test] -fn blog() { - RemoveTest { - routes: vec![ - "/{page}", - "/posts/{year}/{month}/{post}", - "/posts/{year}/{month}/index", - "/posts/{year}/top", - "/static/{*path}", - "/favicon.ico", - ], - ops: vec![ - (Remove, "/{page}", Some("/{page}")), - ( - Remove, - "/posts/{year}/{month}/{post}", - Some("/posts/{year}/{month}/{post}"), - ), - ( - Remove, - "/posts/{year}/{month}/index", - Some("/posts/{year}/{month}/index"), - ), - (Remove, "/posts/{year}/top", Some("/posts/{year}/top")), - (Remove, "/static/{*path}", Some("/static/{*path}")), - (Remove, "/favicon.ico", Some("/favicon.ico")), - ], - remaining: vec![], - } - .run() -} - -#[test] -fn catchall() { - RemoveTest { - routes: vec!["/foo/{*catchall}", "/bar", "/bar/", "/bar/{*catchall}"], - ops: vec![ - (Remove, "/foo/{*catchall}", Some("/foo/{*catchall}")), - (Remove, "/bar/", Some("/bar/")), - (Insert, "/foo/*catchall", Some("/foo/*catchall")), - (Remove, "/bar/{*catchall}", Some("/bar/{*catchall}")), - ], - remaining: vec!["/bar", "/foo/*catchall"], - } - .run(); -} - -#[test] -fn overlapping_routes() { - RemoveTest { - routes: vec![ - "/home", - "/home/{id}", - "/users", - "/users/{id}", - "/users/{id}/posts", - "/users/{id}/posts/{post_id}", - "/articles", - "/articles/{category}", - "/articles/{category}/{id}", - ], - ops: vec![ - (Remove, "/home", Some("/home")), - (Insert, "/home", Some("/home")), - (Remove, "/home/{id}", Some("/home/{id}")), - (Insert, "/home/{id}", Some("/home/{id}")), - (Remove, "/users", Some("/users")), - (Insert, "/users", Some("/users")), - (Remove, "/users/{id}", Some("/users/{id}")), - (Insert, "/users/{id}", Some("/users/{id}")), - (Remove, "/users/{id}/posts", Some("/users/{id}/posts")), - (Insert, "/users/{id}/posts", Some("/users/{id}/posts")), - ( - Remove, - "/users/{id}/posts/{post_id}", - Some("/users/{id}/posts/{post_id}"), - ), - ( - Insert, - "/users/{id}/posts/{post_id}", - Some("/users/{id}/posts/{post_id}"), - ), - (Remove, "/articles", Some("/articles")), - (Insert, "/articles", Some("/articles")), - (Remove, "/articles/{category}", Some("/articles/{category}")), - (Insert, "/articles/{category}", Some("/articles/{category}")), - ( - Remove, - "/articles/{category}/{id}", - Some("/articles/{category}/{id}"), - ), - ( - Insert, - "/articles/{category}/{id}", - Some("/articles/{category}/{id}"), - ), - ], - remaining: vec![ - "/home", - "/home/{id}", - "/users", - "/users/{id}", - "/users/{id}/posts", - "/users/{id}/posts/{post_id}", - "/articles", - "/articles/{category}", - "/articles/{category}/{id}", - ], - } - .run(); -} - -#[test] -fn trailing_slash() { - RemoveTest { - routes: vec!["/{home}/", "/foo"], - ops: vec![ - (Remove, "/", None), - (Remove, "/{home}", None), - (Remove, "/foo/", None), - (Remove, "/foo", Some("/foo")), - (Remove, "/{home}", None), - (Remove, "/{home}/", Some("/{home}/")), - ], - remaining: vec![], - } - .run(); -} - -#[test] -fn remove_root() { - RemoveTest { - routes: vec!["/"], - ops: vec![(Remove, "/", Some("/"))], - remaining: vec![], - } - .run(); -} - -#[test] -fn check_escaped_params() { - RemoveTest { - routes: vec![ - "/foo/{id}", - "/foo/{id}/bar", - "/bar/{user}/{id}", - "/bar/{user}/{id}/baz", - "/baz/{product}/{user}/{id}", - ], - ops: vec![ - (Remove, "/foo/{a}", None), - (Remove, "/foo/{a}/bar", None), - (Remove, "/bar/{a}/{b}", None), - (Remove, "/bar/{a}/{b}/baz", None), - (Remove, "/baz/{a}/{b}/{c}", None), - ], - remaining: vec![ - "/foo/{id}", - "/foo/{id}/bar", - "/bar/{user}/{id}", - "/bar/{user}/{id}/baz", - "/baz/{product}/{user}/{id}", - ], - } - .run(); -} |
