From c0182b02f9f3e6c7412fc5d2a07c33a9d39da702 Mon Sep 17 00:00:00 2001 From: Bobby Holley Date: Fri, 18 Jan 2019 12:32:22 -0800 Subject: [PATCH] Bug 1521187 - Add a dependency on derive_more. r=emilio Differential Revision: https://phabricator.services.mozilla.com/D17028 --HG-- rename : third_party/rust/semver/.cargo-checksum.json => third_party/rust/semver-0.6.0/.cargo-checksum.json rename : third_party/rust/semver/Cargo.toml => third_party/rust/semver-0.6.0/Cargo.toml rename : third_party/rust/semver/README.md => third_party/rust/semver-0.6.0/README.md rename : third_party/rust/semver/src/lib.rs => third_party/rust/semver-0.6.0/src/lib.rs rename : third_party/rust/semver/src/version.rs => third_party/rust/semver-0.6.0/src/version.rs rename : third_party/rust/semver/src/version_req.rs => third_party/rust/semver-0.6.0/src/version_req.rs --- Cargo.lock | 34 +- gfx/wr/Cargo.lock | 53 +- gfx/wr/webrender_api/Cargo.toml | 1 + servo/components/selectors/Cargo.toml | 1 + servo/components/style/Cargo.toml | 1 + .../rust/derive_more/.cargo-checksum.json | 1 + third_party/rust/derive_more/CHANGELOG.md | 106 +++ third_party/rust/derive_more/Cargo.toml | 47 + third_party/rust/derive_more/LICENSE | 21 + third_party/rust/derive_more/README.md | 184 ++++ .../rust/derive_more/src/add_assign_like.rs | 36 + third_party/rust/derive_more/src/add_like.rs | 158 ++++ .../rust/derive_more/src/constructor.rs | 45 + third_party/rust/derive_more/src/deref.rs | 64 ++ third_party/rust/derive_more/src/deref_mut.rs | 63 ++ third_party/rust/derive_more/src/display.rs | 220 +++++ third_party/rust/derive_more/src/from.rs | 132 +++ third_party/rust/derive_more/src/from_str.rs | 70 ++ third_party/rust/derive_more/src/index.rs | 75 ++ third_party/rust/derive_more/src/index_mut.rs | 74 ++ third_party/rust/derive_more/src/into.rs | 53 ++ third_party/rust/derive_more/src/lib.rs | 293 +++++++ .../rust/derive_more/src/mul_assign_like.rs | 56 ++ third_party/rust/derive_more/src/mul_like.rs | 97 +++ third_party/rust/derive_more/src/not_like.rs | 159 ++++ third_party/rust/derive_more/src/try_into.rs | 91 ++ third_party/rust/derive_more/src/utils.rs | 105 +++ .../rust/rustc_version/.cargo-checksum.json | 2 +- third_party/rust/rustc_version/Cargo.toml | 29 +- third_party/rust/rustc_version/README.md | 2 +- third_party/rust/rustc_version/src/lib.rs | 42 +- .../rust/semver-0.6.0/.cargo-checksum.json | 1 + third_party/rust/semver-0.6.0/Cargo.toml | 25 + third_party/rust/semver-0.6.0/LICENSE-APACHE | 201 +++++ third_party/rust/semver-0.6.0/LICENSE-MIT | 25 + third_party/rust/semver-0.6.0/README.md | 103 +++ third_party/rust/semver-0.6.0/src/lib.rs | 178 ++++ third_party/rust/semver-0.6.0/src/version.rs | 650 ++++++++++++++ .../rust/semver-0.6.0/src/version_req.rs | 824 ++++++++++++++++++ .../rust/semver-0.6.0/tests/deprecation.rs | 22 + .../rust/semver-0.6.0/tests/regression.rs | 25 + third_party/rust/semver/.cargo-checksum.json | 2 +- third_party/rust/semver/Cargo.toml | 52 +- third_party/rust/semver/README.md | 2 +- third_party/rust/semver/src/lib.rs | 4 + third_party/rust/semver/src/version.rs | 109 +++ third_party/rust/semver/src/version_req.rs | 81 +- third_party/rust/semver/tests/serde.rs | 90 ++ toolkit/library/rust/shared/Cargo.toml | 4 +- 49 files changed, 4639 insertions(+), 74 deletions(-) create mode 100644 third_party/rust/derive_more/.cargo-checksum.json create mode 100644 third_party/rust/derive_more/CHANGELOG.md create mode 100644 third_party/rust/derive_more/Cargo.toml create mode 100644 third_party/rust/derive_more/LICENSE create mode 100644 third_party/rust/derive_more/README.md create mode 100644 third_party/rust/derive_more/src/add_assign_like.rs create mode 100644 third_party/rust/derive_more/src/add_like.rs create mode 100644 third_party/rust/derive_more/src/constructor.rs create mode 100644 third_party/rust/derive_more/src/deref.rs create mode 100644 third_party/rust/derive_more/src/deref_mut.rs create mode 100644 third_party/rust/derive_more/src/display.rs create mode 100644 third_party/rust/derive_more/src/from.rs create mode 100644 third_party/rust/derive_more/src/from_str.rs create mode 100644 third_party/rust/derive_more/src/index.rs create mode 100644 third_party/rust/derive_more/src/index_mut.rs create mode 100644 third_party/rust/derive_more/src/into.rs create mode 100644 third_party/rust/derive_more/src/lib.rs create mode 100644 third_party/rust/derive_more/src/mul_assign_like.rs create mode 100644 third_party/rust/derive_more/src/mul_like.rs create mode 100644 third_party/rust/derive_more/src/not_like.rs create mode 100644 third_party/rust/derive_more/src/try_into.rs create mode 100644 third_party/rust/derive_more/src/utils.rs create mode 100644 third_party/rust/semver-0.6.0/.cargo-checksum.json create mode 100644 third_party/rust/semver-0.6.0/Cargo.toml create mode 100644 third_party/rust/semver-0.6.0/LICENSE-APACHE create mode 100644 third_party/rust/semver-0.6.0/LICENSE-MIT create mode 100644 third_party/rust/semver-0.6.0/README.md create mode 100644 third_party/rust/semver-0.6.0/src/lib.rs create mode 100644 third_party/rust/semver-0.6.0/src/version.rs create mode 100644 third_party/rust/semver-0.6.0/src/version_req.rs create mode 100644 third_party/rust/semver-0.6.0/tests/deprecation.rs create mode 100644 third_party/rust/semver-0.6.0/tests/regression.rs create mode 100644 third_party/rust/semver/tests/serde.rs diff --git a/Cargo.lock b/Cargo.lock index 3bbc59a3a12d..8c7cd658694f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -735,6 +735,17 @@ dependencies = [ "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_more" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "devd-rs" version = "0.2.1" @@ -1113,7 +1124,7 @@ dependencies = [ "profiler_helper 0.1.0", "rkv 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rsdparsa_capi 0.1.0", - "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "u2fhid 0.2.3", "webrender_bindings 0.1.0", "xpcom 0.1.0", @@ -2185,10 +2196,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rustc_version" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2224,7 +2235,7 @@ name = "scroll" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2244,6 +2255,7 @@ version = "0.21.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2263,6 +2275,14 @@ dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver-parser" version = "0.7.0" @@ -2433,6 +2453,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.25.0 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", "fallible 0.0.1", "fxhash 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3032,6 +3053,7 @@ dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.5 (registry+https://github.com/rust-lang/crates.io-index)", "malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3269,6 +3291,7 @@ dependencies = [ "checksum darling 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f593353cad5af2df6d54810de2b61aa8acba5b5fbc70b0d75e7cc5bdd80aca73" "checksum darling_core 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "168c246e87e727d58575d9b4595491010627f0cdc910e3e6ea3b36db2b9a9d9a" "checksum darling_macro 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99c4eff4bcbeaf6a22578012ff79c95910338668278d1901e528bd34a22f575d" +"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum devd-rs 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e7c9ac481c38baf400d3b732e4a06850dfaa491d1b6379a249d9d40d14c2434c" "checksum diff 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3c2b69f912779fbb121ceb775d74d51e915af17aaebc38d28a592843a2dd0a3a" "checksum digest 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "03b072242a8cbaf9c145665af9d250c59af3b958f83ed6824e13533cf76d5b90" @@ -3402,7 +3425,7 @@ dependencies = [ "checksum runloop 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5d79b4b604167921892e84afbbaad9d5ad74e091bf6c511d9dbfb0593f09fabd" "checksum rust-ini 0.10.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8a654c5bda722c699be6b0fe4c0d90de218928da5b724c3e467fc48865c37263" "checksum rustc-demangle 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "76d7ba1feafada44f2d38eed812bd2489a03c0f5abb975799251518b68848649" -"checksum rustc_version 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0568787116e13c652377b6846f5931454a363a8fdf8ae50463ee40935b278b" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum scoped-tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f417c22df063e9450888a7561788e9bd46d3bb3c1466435b4eccb903807f147d" @@ -3411,6 +3434,7 @@ dependencies = [ "checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383" "checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb" "checksum semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" diff --git a/gfx/wr/Cargo.lock b/gfx/wr/Cargo.lock index f8ebb68b2fed..ca5e0dfd1922 100644 --- a/gfx/wr/Cargo.lock +++ b/gfx/wr/Cargo.lock @@ -326,6 +326,17 @@ dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "derive_more" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "digest" version = "0.8.0" @@ -763,7 +774,7 @@ name = "malloc_size_of_derive" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -867,7 +878,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-traits 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1056,7 +1067,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.6" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1072,7 +1083,7 @@ name = "quote" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1182,6 +1193,14 @@ dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "safe-transmute" version = "0.10.1" @@ -1197,6 +1216,19 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" version = "1.0.80" @@ -1218,7 +1250,7 @@ name = "serde_derive" version = "1.0.80" source = "git+https://github.com/servo/serde?branch=deserialize_from_enums9#e0cc925c259cb74ce41377e4fe02713adfa6d836" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1331,7 +1363,7 @@ name = "syn" version = "0.15.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1341,7 +1373,7 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.17 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1628,6 +1660,7 @@ dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-graphics 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", + "derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)", "dwrote 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.19.4 (registry+https://github.com/rust-lang/crates.io-index)", "ipc-channel 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1849,6 +1882,7 @@ dependencies = [ "checksum crossbeam-utils 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2760899e32a1d58d5abb31129f8fae5de75220bc2176e77ff7c627ae45c918d9" "checksum crossbeam-utils 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "677d453a17e8bd2b913fa38e8b9cf04bcdbb5be790aa294f2389661d72036015" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" +"checksum derive_more 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871" "checksum digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f47366984d3ad862010e22c7ce81a7dbcaebbdfb37241a620f8b6596ee135c" "checksum dlib 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "77e51249a9d823a4cb79e3eca6dcd756153e8ed0157b6c04775d04bf1b13b76a" "checksum downcast-rs 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "18df8ce4470c189d18aa926022da57544f31e154631eb4cfe796aea97051fe6c" @@ -1932,7 +1966,7 @@ dependencies = [ "checksum pkg-config 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "110d5ee3593dbb73f56294327fe5668bcc997897097cbc76b51e7aed3f52452f" "checksum plane-split 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9b1d9a84aa3bbc2dafd06856bdb1dc333eb1d442ad8987b9d596c7344b3ed969" "checksum png 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9adebf7fb91ccf5eac9da1a8e00e83cb8ae882c3e8d8e4ad59da73cb8c82a2c9" -"checksum proc-macro2 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "effdb53b25cdad54f8f48843d67398f7ef2e14f12c1b4cb4effc549a6462a4d6" +"checksum proc-macro2 0.4.25 (registry+https://github.com/rust-lang/crates.io-index)" = "d3797b7142c9aa74954e351fc089bbee7958cebbff6bf2815e7ffff0b19f547d" "checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" "checksum quote 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e44651a0dc4cdd99f71c83b561e221f714912d11af1a4dff0631f923d53af035" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" @@ -1947,9 +1981,12 @@ dependencies = [ "checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum ron 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "da06feaa07f69125ab9ddc769b11de29090122170b402547f64b86fe16ebc399" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum safe-transmute 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9604873ffe1980bc1f179103704a65c8aca141c248d9e52b7af95ff10578166e" "checksum scoped_threadpool 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" "checksum serde_bytes 0.10.4 (registry+https://github.com/rust-lang/crates.io-index)" = "adb6e51a6b3696b301bc221d785f898b4457c619b51d7ce195a6d20baecb37b3" "checksum serde_derive 1.0.80 (git+https://github.com/servo/serde?branch=deserialize_from_enums9)" = "" diff --git a/gfx/wr/webrender_api/Cargo.toml b/gfx/wr/webrender_api/Cargo.toml index be2d4109f4fb..04046b0305ff 100644 --- a/gfx/wr/webrender_api/Cargo.toml +++ b/gfx/wr/webrender_api/Cargo.toml @@ -17,6 +17,7 @@ app_units = "0.7" bincode = "1.0" bitflags = "1.0" byteorder = "1.2.1" +derive_more = "0.13" ipc-channel = {version = "0.11.0", optional = true} euclid = { version = "0.19.4", features = ["serde"] } malloc_size_of_derive = "0.1" diff --git a/servo/components/selectors/Cargo.toml b/servo/components/selectors/Cargo.toml index b2437831b81e..bb8e5d7f81b6 100644 --- a/servo/components/selectors/Cargo.toml +++ b/servo/components/selectors/Cargo.toml @@ -23,6 +23,7 @@ bench = [] bitflags = "1.0" matches = "0.1" cssparser = "0.25" +derive_more = "0.13" log = "0.4" fxhash = "0.2" phf = "0.7.18" diff --git a/servo/components/style/Cargo.toml b/servo/components/style/Cargo.toml index b7e36aa17e41..0c860746cf28 100644 --- a/servo/components/style/Cargo.toml +++ b/servo/components/style/Cargo.toml @@ -31,6 +31,7 @@ bitflags = "1.0" byteorder = "1.0" cssparser = "0.25" crossbeam-channel = { version = "0.3", optional = true } +derive_more = "0.13" new_debug_unreachable = "1.0" encoding_rs = {version = "0.8", optional = true} euclid = "0.19" diff --git a/third_party/rust/derive_more/.cargo-checksum.json b/third_party/rust/derive_more/.cargo-checksum.json new file mode 100644 index 000000000000..9b72b42ae6b8 --- /dev/null +++ b/third_party/rust/derive_more/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"CHANGELOG.md":"8dd6b99908dd99a77f73de68804735d44c7e5d2164cec1661d74c6da97348824","Cargo.toml":"7fa9a84baf9411a5d9b3f5ed32571ac14f5dd0d92b045e5db13216c8a7ae86f1","LICENSE":"8a35369f3ca263b3c62fbb5032947e53b6bfebc6c8a4d1bb982de1c069f6fba5","README.md":"239e573158b39cb25609bfe6281fc50f7b34ed87e6ba602aa8e8df53309850b0","src/add_assign_like.rs":"eac655e68e5b1af22bb93825814969be9fd8877ce2c3ded01656809afe8f0e45","src/add_like.rs":"2ca7dd6fd22b29a374310ff59dd4186f8e8e0c044b0cded951406ae4b3edcdb3","src/constructor.rs":"6a434160d3841445876bc76edd55a81ea5f4b6016f288d8d8d89d407c9b50db7","src/deref.rs":"921a44cc335ca76109a1f921152602abee9bdc72503e31985cf8d6ee67c3676e","src/deref_mut.rs":"67c0d22344c9a0f7ee25e68af7b55930dbd661b810a8dc1b8915c622ea933494","src/display.rs":"24e26eb561c1e6a019bfb82d5c071577976ad74108c38eba3cc3659fc725fbea","src/from.rs":"c86e2a90fedbcd132e4d71694a3bf6ee21475a28f44b9421af1b737956c16302","src/from_str.rs":"cb47df454bf4ec27f1fce1cd5224bca47d745822cd8083a6eb99c989c11b1db8","src/index.rs":"b9999b321c0c87c8516c91bfd92cb74f9d13f830301a6fe760f798665885601f","src/index_mut.rs":"5e41bdc106a48dade5d7696a19b174bcdbd8bc86152375941c49684c9d861e4b","src/into.rs":"4b561410460c13b51f168f9544bbf73912e11a6af6152fae8925f059a7fe004d","src/lib.rs":"5c2d1a965fbcd67deabf27394ce85a6772321c3011ab646281274a39f9e6b5ee","src/mul_assign_like.rs":"7c9e11288f7296d2854a167749232e748467cd2a2859bea7bef10f26d4c91584","src/mul_like.rs":"bac8745c58850e47d583d3f8be2886b13424abcb8fadcfcdd63b9dfb458f61b8","src/not_like.rs":"ed4fa1201aac47673e9f7842bb184747beddea195a7cedaaf56716751e9b732c","src/try_into.rs":"18992d9aa567960f5616b020e78bbd6e56191c799d88bcd379ce837a600bd169","src/utils.rs":"843a3bac04601d2f6158fbd27f9e1c54987ee4801dddb069fbe4436a4b89660f"},"package":"3f57d78cf3bd45270dad4e70c21ec77a960b36c7a841ff9db76aaa775a8fb871"} \ No newline at end of file diff --git a/third_party/rust/derive_more/CHANGELOG.md b/third_party/rust/derive_more/CHANGELOG.md new file mode 100644 index 000000000000..337f6b3fe718 --- /dev/null +++ b/third_party/rust/derive_more/CHANGELOG.md @@ -0,0 +1,106 @@ +# Change Log + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## 0.13.0 - 2018-10-19 +- Updated to `syn` v0.15 +- Extended Display-like derives to support custom formats + +## 0.12.0 - 2018-09-19 + +### Changed +- Updated to `syn` v0.14, `quote` v0.6 and `proc-macro2` v0.4 + +## 0.11.0 - 2018-05-12 + +### Changed +- Updated to latest version of `syn` and `quote` + +### Fixed +- Changed some URLs in the docs so they were correct on crates.io and docs.rs +- The `Result` type is now referenced in the derives using its absolute path + (`::std::result::Result`) to make sure that the derives don't accidentally use + another `Result` type that is in scope. + +## 0.10.0 - 2018-03-29 + +### Added +- Allow deriving of `TryInto` +- Allow deriving of `Deref` +- Allow deriving of `DerefMut` + +## 0.9.0 - 2018-03-18 + +### Added +- Allow deriving of `Display`, `Binary`, `Octal`, `LowerHex`, `UpperHex`, `LowerExp`, `UpperExp`, `Pointer` +- Allow deriving of `Index` +- Allow deriving of `IndexMut` + +### Fixed +- Allow cross crate inlining of derived methods + +### Internal changes +- Fix most `clippy` warnings + +## 0.8.0 - 2018-03-10 + +### Added +- Allow deriving of `FromStr` + +### Changed +- Updated to latest version of `syn` and `quote` + +## 0.7.1 - 2018-01-25 + +### Fixed +- Add `#[allow(missing_docs)]` to the Constructor definition + +### Internal changes +- Run `rustfmt` on the code + + +## 0.7.0 - 2017-07-25 + +### Changed +- Changed code to work with newer version of the `syn` library. + +## 0.6.2 - 2017-04-23 + +### Changed +- Deriving `From`, `Into` and `Constructor` now works for empty structs. + + +## 0.6.1 - 2017-03-08 + +### Changed +- The `new()` method that is created when deriving `Constructor` is now public. + This makes it a lot more useful. + + +## 0.6.0 - 2017-02-20 + +### Added + +- Derives for `Into`, `Constructor` and `MulAssign`-like + +### Changed + +- `From` is now derived for enum variants with multiple fields. + +### Fixed + +- Derivations now support generics. + + +## 0.5.0 - 2017-02-02 + +### Added + +- Lots of docs. +- Derives for `Neg`-like and `AddAssign`-like. + +### Changed +- `From` can now be derived for structs with multiple fields. diff --git a/third_party/rust/derive_more/Cargo.toml b/third_party/rust/derive_more/Cargo.toml new file mode 100644 index 000000000000..12e67e917c67 --- /dev/null +++ b/third_party/rust/derive_more/Cargo.toml @@ -0,0 +1,47 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + +[package] +name = "derive_more" +version = "0.13.0" +authors = ["Jelte Fennema "] +include = ["src/**/*.rs", "Cargo.toml", "LICENSE", "README.md", "CHANGELOG.md"] +description = "Adds #[derive(x)] macros for more traits" +documentation = "https://jeltef.github.io/derive_more/derive_more/" +readme = "README.md" +keywords = ["derive", "Add", "From", "Constructor", "implementation"] +categories = ["development-tools", "development-tools::procedural-macro-helpers"] +license = "MIT" +repository = "https://github.com/JelteF/derive_more" + +[lib] +name = "derive_more" +proc-macro = true +[dependencies.proc-macro2] +version = "0.4.19" + +[dependencies.quote] +version = "0.6" + +[dependencies.syn] +version = "0.15" +features = ["extra-traits"] +[build-dependencies.rustc_version] +version = "0.2.2" + +[features] +nightly = [] +[badges.appveyor] +repository = "JelteF/derive_more" + +[badges.travis-ci] +repository = "JelteF/derive_more" diff --git a/third_party/rust/derive_more/LICENSE b/third_party/rust/derive_more/LICENSE new file mode 100644 index 000000000000..602cf050e231 --- /dev/null +++ b/third_party/rust/derive_more/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2016 Jelte Fennema + +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/third_party/rust/derive_more/README.md b/third_party/rust/derive_more/README.md new file mode 100644 index 000000000000..03af37bbf9e8 --- /dev/null +++ b/third_party/rust/derive_more/README.md @@ -0,0 +1,184 @@ +# `derive_more` + +[![Build Status](https://api.travis-ci.org/JelteF/derive_more.svg?branch=master)](https://travis-ci.org/JelteF/derive_more) +[![Latest Version](https://img.shields.io/crates/v/derive_more.svg)](https://crates.io/crates/derive_more) +[![Rust Documentation](https://img.shields.io/badge/api-rustdoc-blue.svg)](https://jeltef.github.io/derive_more/derive_more/) +[![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/JelteF/derive_more/master/LICENSE) + +Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`], +[`Not`] or [`From`]. +However, when wrapping these types inside your own structs or enums you lose the +implementations of these traits and are required to recreate them. +This is especially annoying when your own structures are very simple, such as when using the +commonly advised newtype pattern (e.g. `MyInt(i32)`). + +This library tries to remove these annoyances and the corresponding boilerplate code. +It does this by allowing you to derive lots of commonly used traits for both structs and enums. + +## Example code + +By using this library the following code just works: + + +```rust +#[macro_use] +extern crate derive_more; + +#[derive(Debug, Eq, PartialEq, From, Add)] +struct MyInt(i32); + +#[derive(Debug, Eq, PartialEq, From, Into, Constructor, Mul)] +struct Point2D { + x: i32, + y: i32, +} + +#[derive(Debug, Eq, PartialEq, From, Add)] +enum MyEnum { + Int(i32), + UnsignedInt(u32), + Nothing, +} + +fn main() { + let my_11 = MyInt(5) + 6.into(); + assert_eq!(MyInt(11), MyInt(5) + 6.into()); + assert_eq!(Point2D { x: 5, y: 6 } * 10, (50, 60).into()); + assert_eq!((5, 6), Point2D { x: 5, y: 6 }.into()); + assert_eq!(Point2D { x: 5, y: 6 }, Point2D::new(5, 6)); + assert_eq!(MyEnum::Int(15), (MyEnum::Int(8) + 7.into()).unwrap()) +} +``` + +## The derivable traits + +Below are all the traits that you can derive using this library. +Some trait derivations are so similar that the further documentation will only show a single one +of them. +You can recognize these by the "-like" suffix in their name. +The trait name before that will be the only one that is used throughout the further +documentation. + +**NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't +automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]` + +### Conversion traits +These are traits that are used to convert automatically between types. + +1. [`From`] +2. [`Into`] +3. [`FromStr`] +4. [`TryInto`] (nightly-only as of writing) + +### Formatting traits +These traits are used for converting a struct to a string in different ways. + +1. `Display`-like, contains [`Display`], [`Binary`], [`Octal`], [`LowerHex`], [`UpperHex`], + [`LowerExp`], [`UpperExp`], [`Pointer`] + +### Operators +These are traits that can be used for operator overloading. + +1. [`Index`] +2. [`Deref`] +3. `Not`-like, contains [`Not`] and [`Neg`] +4. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`] +5. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`] +6. [`IndexMut`] +7. [`DerefMut`] +8. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`] + and [`BitXorAssign`] +9. `MulAssign`-like, contains [`MulAssign`], [`DivAssign`], [`RemAssign`], [`ShrAssign`] and + [`ShlAssign`] + +### Static methods +These don't derive traits, but derive static methods instead. + +1. `Constructor`, this derives a `new` method that can be used as a constructor. This is very + basic if you need more customization for your constructor, check out the [`derive-new`] crate. + + +## Generated code + +It is important to understand what code gets generated when using one of the derives from this +crate. +That is why the links below explain what code gets generated for a trait for each group from +before. + +1. [`#[derive(From)]`](https://jeltef.github.io/derive_more/derive_more/from.html) +2. [`#[derive(Into)]`](https://jeltef.github.io/derive_more/derive_more/into.html) +3. [`#[derive(FromStr)]`](https://jeltef.github.io/derive_more/derive_more/from_str.html) +4. [`#[derive(TryInto)]`](https://jeltef.github.io/derive_more/derive_more/try_into.html) +5. [`#[derive(Display)]`](https://jeltef.github.io/derive_more/derive_more/display.html) +6. [`#[derive(Index)]`](https://jeltef.github.io/derive_more/derive_more/index_op.html) +7. [`#[derive(Deref)]`](https://jeltef.github.io/derive_more/derive_more/deref.html) +8. [`#[derive(Not)]`](https://jeltef.github.io/derive_more/derive_more/not.html) +9. [`#[derive(Add)]`](https://jeltef.github.io/derive_more/derive_more/add.html) +10. [`#[derive(Mul)]`](https://jeltef.github.io/derive_more/derive_more/mul.html) +11. [`#[derive(IndexMut)]`](https://jeltef.github.io/derive_more/derive_more/index_mut.html) +12. [`#[derive(DerefMut)]`](https://jeltef.github.io/derive_more/derive_more/deref_mut.html) +13. [`#[derive(AddAssign)]`](https://jeltef.github.io/derive_more/derive_more/add_assign.html) +14. [`#[derive(MulAssign)]`](https://jeltef.github.io/derive_more/derive_more/mul_assign.html) +15. [`#[derive(Constructor)]`](https://jeltef.github.io/derive_more/derive_more/constructor.html) + +If you want to be sure what code is generated for your specific type I recommend using the +[`cargo-expand`] utility. +This will show you your code with all macros and derives expanded. + +## Installation + +This library requires Rust 1.15 or higher, so this needs to be installed. +Then add the following to `Cargo.toml`: + +```toml +[dependencies] +derive_more = "0.13.0" +``` + +And this to the top of your Rust file: + +```rust +#[macro_use] +extern crate derive_more; +``` + +[`cargo-expand`]: https://github.com/dtolnay/cargo-expand +[`derive-new`]: https://github.com/nrc/derive-new +[`From`]: https://doc.rust-lang.org/core/convert/trait.From.html +[`Into`]: https://doc.rust-lang.org/core/convert/trait.Into.html +[`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html +[`TryInto`]: https://doc.rust-lang.org/core/convert/trait.TryInto.html +[`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html +[`Binary`]: https://doc.rust-lang.org/std/fmt/trait.Binary.html +[`Octal`]: https://doc.rust-lang.org/std/fmt/trait.Octal.html +[`LowerHex`]: https://doc.rust-lang.org/std/fmt/trait.LowerHex.html +[`UpperHex`]: https://doc.rust-lang.org/std/fmt/trait.UpperHex.html +[`LowerExp`]: https://doc.rust-lang.org/std/fmt/trait.LowerExp.html +[`UpperExp`]: https://doc.rust-lang.org/std/fmt/trait.UpperExp.html +[`Pointer`]: https://doc.rust-lang.org/std/fmt/trait.Pointer.html +[`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html +[`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +[`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html +[`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html +[`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html +[`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html +[`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html +[`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html +[`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html +[`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html +[`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html +[`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html +[`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html +[`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html +[`IndexMut`]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html +[`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html +[`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html +[`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html +[`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html +[`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html +[`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html +[`MulAssign`]: https://doc.rust-lang.org/std/ops/trait.MulAssign.html +[`DivAssign`]: https://doc.rust-lang.org/std/ops/trait.DivAssign.html +[`RemAssign`]: https://doc.rust-lang.org/std/ops/trait.RemAssign.html +[`ShrAssign`]: https://doc.rust-lang.org/std/ops/trait.ShrAssign.html +[`ShlAssign`]: https://doc.rust-lang.org/std/ops/trait.ShlAssign.html diff --git a/third_party/rust/derive_more/src/add_assign_like.rs b/third_party/rust/derive_more/src/add_assign_like.rs new file mode 100644 index 000000000000..4b2179e40d1f --- /dev/null +++ b/third_party/rust/derive_more/src/add_assign_like.rs @@ -0,0 +1,36 @@ +use add_like::{struct_exprs, tuple_exprs}; +use proc_macro2::{Span, TokenStream}; +use syn::{Data, DeriveInput, Fields, Ident}; +use utils::{add_extra_ty_param_bound_op, named_to_vec, unnamed_to_vec}; + +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let method_name = trait_name.to_string(); + let method_name = method_name.trim_right_matches("Assign"); + let method_name = method_name.to_lowercase(); + let method_ident = Ident::new(&(method_name.to_string() + "_assign"), Span::call_site()); + let input_type = &input.ident; + + let generics = add_extra_ty_param_bound_op(&input.generics, &trait_ident); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let exprs = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => tuple_exprs(&unnamed_to_vec(fields), &method_ident), + Fields::Named(ref fields) => struct_exprs(&named_to_vec(fields), &method_ident), + _ => panic!(format!("Unit structs cannot use derive({})", trait_name)), + }, + + _ => panic!(format!("Only structs can use derive({})", trait_name)), + }; + + quote!( + impl#impl_generics ::std::ops::#trait_ident for #input_type#ty_generics #where_clause { + #[inline] + fn #method_ident(&mut self, rhs: #input_type#ty_generics) { + #(#exprs; + )* + } + } + ) +} diff --git a/third_party/rust/derive_more/src/add_like.rs b/third_party/rust/derive_more/src/add_like.rs new file mode 100644 index 000000000000..c615d75065dd --- /dev/null +++ b/third_party/rust/derive_more/src/add_like.rs @@ -0,0 +1,158 @@ +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; +use std::iter; +use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident, Index}; +use utils::{ + add_extra_type_param_bound_op_output, field_idents, named_to_vec, numbered_vars, unnamed_to_vec, +}; + +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let method_name = trait_name.to_lowercase(); + let method_ident = Ident::new(&method_name, Span::call_site()); + let input_type = &input.ident; + + let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let (output_type, block) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => ( + quote!(#input_type#ty_generics), + tuple_content(input_type, &unnamed_to_vec(fields), &method_ident), + ), + Fields::Named(ref fields) => ( + quote!(#input_type#ty_generics), + struct_content(input_type, &named_to_vec(fields), &method_ident), + ), + _ => panic!(format!("Unit structs cannot use derive({})", trait_name)), + }, + Data::Enum(ref data_enum) => ( + quote!(::std::result::Result<#input_type#ty_generics, &'static str>), + enum_content(input_type, data_enum, &method_ident), + ), + + _ => panic!(format!( + "Only structs and enums can use derive({})", + trait_name + )), + }; + + quote!( + impl#impl_generics ::std::ops::#trait_ident for #input_type#ty_generics #where_clause { + type Output = #output_type; + #[inline] + fn #method_ident(self, rhs: #input_type#ty_generics) -> #output_type { + #block + } + } + ) +} + +fn tuple_content( + input_type: &T, + fields: &[&Field], + method_ident: &Ident, +) -> TokenStream { + let exprs = tuple_exprs(fields, method_ident); + quote!(#input_type(#(#exprs),*)) +} + +pub fn tuple_exprs(fields: &[&Field], method_ident: &Ident) -> Vec { + let mut exprs = vec![]; + + for i in 0..fields.len() { + let i = Index::from(i); + // generates `self.0.add(rhs.0)` + let expr = quote!(self.#i.#method_ident(rhs.#i)); + exprs.push(expr); + } + exprs +} + +fn struct_content(input_type: &Ident, fields: &[&Field], method_ident: &Ident) -> TokenStream { + // It's safe to unwrap because struct fields always have an identifier + let exprs = struct_exprs(fields, method_ident); + let field_names = field_idents(fields); + + quote!(#input_type{#(#field_names: #exprs),*}) +} + +pub fn struct_exprs(fields: &[&Field], method_ident: &Ident) -> Vec { + let mut exprs = vec![]; + + for field in fields { + // It's safe to unwrap because struct fields always have an identifier + let field_id = field.ident.as_ref().unwrap(); + // generates `x: self.x.add(rhs.x)` + let expr = quote!(self.#field_id.#method_ident(rhs.#field_id)); + exprs.push(expr) + } + exprs +} + +fn enum_content(input_type: &Ident, data_enum: &DataEnum, method_ident: &Ident) -> TokenStream { + let mut matches = vec![]; + let mut method_iter = iter::repeat(method_ident); + + for variant in &data_enum.variants { + let subtype = &variant.ident; + let subtype = quote!(#input_type::#subtype); + + match variant.fields { + Fields::Unnamed(ref fields) => { + // The patern that is outputted should look like this: + // (Subtype(left_vars), TypePath(right_vars)) => Ok(TypePath(exprs)) + let size = unnamed_to_vec(fields).len(); + let l_vars = &numbered_vars(size, "l_"); + let r_vars = &numbered_vars(size, "r_"); + let method_iter = method_iter.by_ref(); + let matcher = quote!{ + (#subtype(#(#l_vars),*), + #subtype(#(#r_vars),*)) => { + ::std::result::Result::Ok(#subtype(#(#l_vars.#method_iter(#r_vars)),*)) + } + }; + matches.push(matcher); + } + Fields::Named(ref fields) => { + // The patern that is outputted should look like this: + // (Subtype{a: __l_a, ...}, Subtype{a: __r_a, ...} => { + // Ok(Subtype{a: __l_a.add(__r_a), ...}) + // } + let field_vec = named_to_vec(fields); + let size = field_vec.len(); + let field_names = &field_idents(&field_vec); + let l_vars = &numbered_vars(size, "l_"); + let r_vars = &numbered_vars(size, "r_"); + let method_iter = method_iter.by_ref(); + let matcher = quote!{ + (#subtype{#(#field_names: #l_vars),*}, + #subtype{#(#field_names: #r_vars),*}) => { + ::std::result::Result::Ok(#subtype{#(#field_names: #l_vars.#method_iter(#r_vars)),*}) + } + }; + matches.push(matcher); + } + Fields::Unit => { + let message = format!("Cannot {}() unit variants", method_ident.to_string()); + matches.push(quote!((#subtype, #subtype) => ::std::result::Result::Err(#message))); + } + } + } + + if data_enum.variants.len() > 1 { + // In the strange case where there's only one enum variant this is would be an unreachable + // match. + let message = format!( + "Trying to {} mismatched enum variants", + method_ident.to_string() + ); + matches.push(quote!(_ => ::std::result::Result::Err(#message))); + } + quote!( + match (self, rhs) { + #(#matches),* + } + ) +} diff --git a/third_party/rust/derive_more/src/constructor.rs b/third_party/rust/derive_more/src/constructor.rs new file mode 100644 index 000000000000..a026bc3165d1 --- /dev/null +++ b/third_party/rust/derive_more/src/constructor.rs @@ -0,0 +1,45 @@ +use proc_macro2::TokenStream; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{field_idents, get_field_types, named_to_vec, numbered_vars, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(Constructor)]` into an implementation of `Constructor` +pub fn expand(input: &DeriveInput, _: &str) -> TokenStream { + let input_type = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let ((body, vars), fields) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + let field_vec = unnamed_to_vec(fields); + (tuple_body(input_type, &field_vec), field_vec) + } + Fields::Named(ref fields) => { + let field_vec = named_to_vec(fields); + (struct_body(input_type, &field_vec), field_vec) + } + Fields::Unit => (struct_body(input_type, &[]), vec![]), + }, + _ => panic!("Only structs can derive a constructor"), + }; + let original_types = &get_field_types(&fields); + quote!{ + #[allow(missing_docs)] + impl#impl_generics #input_type#ty_generics #where_clause { + #[inline] + pub fn new(#(#vars: #original_types),*) -> #input_type#ty_generics { + #body + } + } + } +} + +fn tuple_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec) { + let vars = &numbered_vars(fields.len(), ""); + (quote!(#return_type(#(#vars),*)), vars.clone()) +} + +fn struct_body(return_type: &Ident, fields: &[&Field]) -> (TokenStream, Vec) { + let field_names: &Vec = &field_idents(fields).iter().map(|f| (**f).clone()).collect(); + let vars = field_names; + let ret_vars = field_names.clone(); + (quote!(#return_type{#(#field_names: #vars),*}), ret_vars) +} diff --git a/third_party/rust/derive_more/src/deref.rs b/third_party/rust/derive_more/src/deref.rs new file mode 100644 index 000000000000..cc2f54449e01 --- /dev/null +++ b/third_party/rust/derive_more/src/deref.rs @@ -0,0 +1,64 @@ +use proc_macro2::{Span, TokenStream}; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{add_extra_ty_param_bound, named_to_vec, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(Index)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident); + let input_type = &input.ident; + let field_vec: Vec<&Field>; + let member = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + field_vec = unnamed_to_vec(fields); + tuple_from_str(trait_name, &field_vec) + } + Fields::Named(ref fields) => { + field_vec = named_to_vec(fields); + struct_from_str(trait_name, &field_vec) + } + Fields::Unit => panic_one_field(trait_name), + }, + _ => panic_one_field(trait_name), + }; + let field_type = &field_vec[0].ty; + + let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + // let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let casted_trait = "e!(<#field_type as #trait_path>); + quote!{ + impl#impl_generics #trait_path for #input_type#ty_generics #where_clause + { + type Target = #casted_trait::Target; + #[inline] + fn deref(&self) -> &Self::Target { + #casted_trait::deref(&#member) + } + } + } +} + +fn panic_one_field(trait_name: &str) -> ! { + panic!(format!( + "Only structs with one field can derive({})", + trait_name + )) +} + +fn tuple_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> (TokenStream) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + quote!(self.0) +} + +fn struct_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> TokenStream { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_ident = &field.ident; + quote!(self.#field_ident) +} diff --git a/third_party/rust/derive_more/src/deref_mut.rs b/third_party/rust/derive_more/src/deref_mut.rs new file mode 100644 index 000000000000..a77de9771af8 --- /dev/null +++ b/third_party/rust/derive_more/src/deref_mut.rs @@ -0,0 +1,63 @@ +use proc_macro2::{Span, TokenStream}; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{add_extra_ty_param_bound, named_to_vec, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(Index)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident); + let input_type = &input.ident; + let field_vec: Vec<&Field>; + let member = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + field_vec = unnamed_to_vec(fields); + tuple_from_str(trait_name, &field_vec) + } + Fields::Named(ref fields) => { + field_vec = named_to_vec(fields); + struct_from_str(trait_name, &field_vec) + } + Fields::Unit => panic_one_field(trait_name), + }, + _ => panic_one_field(trait_name), + }; + let field_type = &field_vec[0].ty; + + let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + // let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let casted_trait = "e!(<#field_type as #trait_path>); + quote!{ + impl#impl_generics #trait_path for #input_type#ty_generics #where_clause + { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + #casted_trait::deref_mut(&mut #member) + } + } + } +} + +fn panic_one_field(trait_name: &str) -> ! { + panic!(format!( + "Only structs with one field can derive({})", + trait_name + )) +} + +fn tuple_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> (TokenStream) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + quote!(self.0) +} + +fn struct_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> TokenStream { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_ident = &field.ident; + quote!(self.#field_ident) +} diff --git a/third_party/rust/derive_more/src/display.rs b/third_party/rust/derive_more/src/display.rs new file mode 100644 index 000000000000..1ea3455c7e57 --- /dev/null +++ b/third_party/rust/derive_more/src/display.rs @@ -0,0 +1,220 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use std::fmt::Display; +use syn::{ + parse::{Error, Result}, + spanned::Spanned, + Attribute, Data, DeriveInput, Fields, Lit, Meta, MetaNameValue, NestedMeta, +}; + +/// Provides the hook to expand `#[derive(Display)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> Result { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let trait_path = "e!(::std::fmt::#trait_ident); + let trait_attr = match trait_name { + "Display" => "display", + "Binary" => "binary", + "Octal" => "octal", + "LowerHex" => "lower_hex", + "UpperHex" => "upper_hex", + "LowerExp" => "lower_exp", + "UpperExp" => "upper_exp", + "Pointer" => "pointer", + _ => unimplemented!(), + }; + + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let name = &input.ident; + + let arms = State { + trait_path, + trait_attr, + input, + } + .get_match_arms()?; + + Ok(quote! { + impl #impl_generics #trait_path for #name #ty_generics #where_clause + { + #[inline] + fn fmt(&self, _derive_more_Display_formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + match self { + #arms + _ => Ok(()) // This is needed for empty enums + } + } + } + }) +} + +struct State<'a, 'b> { + trait_path: &'b TokenStream, + trait_attr: &'static str, + input: &'a DeriveInput, +} + +impl<'a, 'b> State<'a, 'b> { + fn get_proper_syntax(&self) -> impl Display { + format!( + r#"Proper syntax: #[{}(fmt = "My format", "arg1", "arg2")]"#, + self.trait_attr + ) + } + fn get_matcher(&self, fields: &Fields) -> TokenStream { + match fields { + Fields::Unit => TokenStream::new(), + Fields::Unnamed(fields) => { + let fields: TokenStream = (0..fields.unnamed.len()) + .map(|n| { + let i = Ident::new(&format!("_{}", n), Span::call_site()); + quote!(#i,) + }) + .collect(); + quote!((#fields)) + } + Fields::Named(fields) => { + let fields: TokenStream = fields + .named + .iter() + .map(|f| { + let i = f.ident.as_ref().unwrap(); + quote!(#i,) + }) + .collect(); + quote!({#fields}) + } + } + } + fn find_meta(&self, attrs: &[Attribute]) -> Result> { + let mut it = attrs + .iter() + .filter_map(|a| a.interpret_meta()) + .filter(|m| m.name() == self.trait_attr); + + let meta = it.next(); + if it.next().is_some() { + Err(Error::new(meta.span(), "Too many formats given")) + } else { + Ok(meta) + } + } + fn get_meta_fmt(&self, meta: Meta) -> Result { + let list = match &meta { + Meta::List(list) => list, + _ => return Err(Error::new(meta.span(), self.get_proper_syntax())), + }; + + let fmt = match &list.nested[0] { + NestedMeta::Meta(Meta::NameValue(MetaNameValue { + ident, + lit: Lit::Str(s), + .. + })) + if ident == "fmt" => + { + s + } + _ => return Err(Error::new(list.nested[0].span(), self.get_proper_syntax())), + }; + + let args = list + .nested + .iter() + .skip(1) // skip fmt = "..." + .try_fold(TokenStream::new(), |args, arg| { + let arg = match arg { + NestedMeta::Literal(Lit::Str(s)) => s, + NestedMeta::Meta(Meta::Word(i)) => { + return Ok(quote_spanned!(list.span()=> #args #i,)) + } + _ => return Err(Error::new(arg.span(), self.get_proper_syntax())), + }; + let arg: TokenStream = match arg.parse() { + Ok(arg) => arg, + Err(e) => return Err(Error::new(arg.span(), e)), + }; + Ok(quote_spanned!(list.span()=> #args #arg,)) + })?; + + Ok(quote_spanned!(meta.span()=> write!(_derive_more_Display_formatter, #fmt, #args))) + } + fn infer_fmt(&self, fields: &Fields, name: &Ident) -> Result { + let fields = match fields { + Fields::Unit => { + return Ok(quote!(write!( + _derive_more_Display_formatter, + stringify!(#name) + ))); + } + Fields::Named(fields) => &fields.named, + Fields::Unnamed(fields) => &fields.unnamed, + }; + if fields.len() == 0 { + return Ok(quote!(write!( + _derive_more_Display_formatter, + stringify!(#name) + ))); + } else if fields.len() > 1 { + return Err(Error::new( + fields.span(), + "Can not automatically infer format for types with more than 1 field", + )); + } + + let trait_path = self.trait_path; + if let Some(ident) = &fields.iter().next().as_ref().unwrap().ident { + Ok(quote!(#trait_path::fmt(#ident, _derive_more_Display_formatter))) + } else { + Ok(quote!(#trait_path::fmt(_0, _derive_more_Display_formatter))) + } + } + fn get_match_arms(&self) -> Result { + match &self.input.data { + Data::Enum(e) => { + if let Some(meta) = self.find_meta(&self.input.attrs)? { + let fmt = self.get_meta_fmt(meta)?; + e.variants.iter().try_for_each(|v| { + if let Some(meta) = self.find_meta(&v.attrs)? { + Err(Error::new( + meta.span(), + "Can not have a format on the variant when the whole enum has one", + )) + } else { + Ok(()) + } + })?; + Ok(quote_spanned!(self.input.span()=> _ => #fmt,)) + } else { + e.variants.iter().try_fold(TokenStream::new(), |arms, v| { + let matcher = self.get_matcher(&v.fields); + let fmt = if let Some(meta) = self.find_meta(&v.attrs)? { + self.get_meta_fmt(meta)? + } else { + self.infer_fmt(&v.fields, &v.ident)? + }; + let name = &self.input.ident; + let v_name = &v.ident; + Ok(quote_spanned!(self.input.span()=> #arms #name::#v_name #matcher => #fmt,)) + }) + } + } + Data::Struct(s) => { + let matcher = self.get_matcher(&s.fields); + let fmt = if let Some(meta) = self.find_meta(&self.input.attrs)? { + self.get_meta_fmt(meta)? + } else { + self.infer_fmt(&s.fields, &self.input.ident)? + }; + let name = &self.input.ident; + Ok(quote_spanned!(self.input.span()=> #name #matcher => #fmt,)) + } + Data::Union(_) => { + let meta = self.find_meta(&self.input.attrs)?.ok_or(Error::new( + self.input.span(), + "Can not automatically infer format for unions", + ))?; + let fmt = self.get_meta_fmt(meta)?; + Ok(quote_spanned!(self.input.span()=> _ => #fmt,)) + } + } + } +} diff --git a/third_party/rust/derive_more/src/from.rs b/third_party/rust/derive_more/src/from.rs new file mode 100644 index 000000000000..2dbcad791a7a --- /dev/null +++ b/third_party/rust/derive_more/src/from.rs @@ -0,0 +1,132 @@ +use std::collections::HashMap; +use std::ops::Index; + +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{Data, DataEnum, DeriveInput, Field, Fields}; +use utils::{field_idents, get_field_types, named_to_vec, number_idents, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(From)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => tuple_from(input, &unnamed_to_vec(fields)), + Fields::Named(ref fields) => struct_from(input, &named_to_vec(fields)), + Fields::Unit => struct_from(input, &[]), + }, + Data::Enum(ref data_enum) => enum_from(input, data_enum), + _ => panic!(format!( + "Only structs and enums can use derive({})", + trait_name + )), + } +} + +pub fn from_impl(input: &DeriveInput, fields: &[&Field], body: T) -> TokenStream { + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let input_type = &input.ident; + let original_types = &get_field_types(fields); + quote!{ + impl#impl_generics ::std::convert::From<(#(#original_types),*)> for + #input_type#ty_generics #where_clause { + + #[allow(unused_variables)] + #[inline] + fn from(original: (#(#original_types),*)) -> #input_type#ty_generics { + #body + } + } + } +} + +fn tuple_from(input: &DeriveInput, fields: &[&Field]) -> TokenStream { + let input_type = &input.ident; + let body = tuple_body(input_type, fields); + from_impl(input, fields, body) +} + +fn tuple_body(return_type: T, fields: &[&Field]) -> TokenStream { + if fields.len() == 1 { + quote!(#return_type(original)) + } else { + let field_names = &number_idents(fields.len()); + quote!(#return_type(#(original.#field_names),*)) + } +} + +fn struct_from(input: &DeriveInput, fields: &[&Field]) -> TokenStream { + let input_type = &input.ident; + let body = struct_body(input_type, fields); + from_impl(input, fields, body) +} + +fn struct_body(return_type: T, fields: &[&Field]) -> TokenStream { + if fields.len() == 1 { + let field_name = &fields[0].ident; + quote!(#return_type{#field_name: original}) + } else { + let argument_field_names = &number_idents(fields.len()); + let field_names = &field_idents(fields); + quote!(#return_type{#(#field_names: original.#argument_field_names),*}) + } +} + +fn enum_from(input: &DeriveInput, data_enum: &DataEnum) -> TokenStream { + let mut type_signature_counts = HashMap::new(); + let input_type = &input.ident; + + for variant in &data_enum.variants { + match variant.fields { + Fields::Unnamed(ref fields) => { + let original_types = unnamed_to_vec(fields).iter().map(|f| &f.ty).collect(); + let counter = type_signature_counts.entry(original_types).or_insert(0); + *counter += 1; + } + Fields::Named(ref fields) => { + let original_types = named_to_vec(fields).iter().map(|f| &f.ty).collect(); + let counter = type_signature_counts.entry(original_types).or_insert(0); + *counter += 1; + } + Fields::Unit => { + let counter = type_signature_counts.entry(vec![]).or_insert(0); + *counter += 1; + } + } + } + + let mut tokens = TokenStream::new(); + + for variant in &data_enum.variants { + match variant.fields { + Fields::Unnamed(ref fields) => { + let field_vec = &unnamed_to_vec(fields); + let original_types = get_field_types(field_vec); + + if *type_signature_counts.index(&original_types) == 1 { + let variant_ident = &variant.ident; + let body = tuple_body(quote!(#input_type::#variant_ident), field_vec); + from_impl(input, field_vec, body).to_tokens(&mut tokens) + } + } + + Fields::Named(ref fields) => { + let field_vec = &named_to_vec(fields); + let original_types = get_field_types(field_vec); + + if *type_signature_counts.index(&original_types) == 1 { + let variant_ident = &variant.ident; + let body = struct_body(quote!(#input_type::#variant_ident), field_vec); + from_impl(input, field_vec, body).to_tokens(&mut tokens) + } + } + Fields::Unit => { + if *type_signature_counts.index(&vec![]) == 1 { + let variant_ident = &variant.ident; + let body = struct_body(quote!(#input_type::#variant_ident), &[]); + from_impl(input, &[], body).to_tokens(&mut tokens) + } + } + } + } + tokens +} diff --git a/third_party/rust/derive_more/src/from_str.rs b/third_party/rust/derive_more/src/from_str.rs new file mode 100644 index 000000000000..9d619b61b04d --- /dev/null +++ b/third_party/rust/derive_more/src/from_str.rs @@ -0,0 +1,70 @@ +use proc_macro2::TokenStream; +use syn::{Data, DeriveInput, Field, Fields, Ident, Type}; +use utils::{add_extra_ty_param_bound, named_to_vec, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(FromStr)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_path = "e!(::std::str::FromStr); + let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + let input_type = &input.ident; + let (result, field_type) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + tuple_from_str(input_type, trait_name, &unnamed_to_vec(fields)) + } + Fields::Named(ref fields) => { + struct_from_str(input_type, trait_name, &named_to_vec(fields)) + } + Fields::Unit => panic_one_field(trait_name), + }, + _ => panic_one_field(trait_name), + }; + quote!{ + impl#impl_generics #trait_path for #input_type#ty_generics #where_clause + { + type Err = <#field_type as #trait_path>::Err; + #[inline] + fn from_str(src: &str) -> ::std::result::Result { + return ::std::result::Result::Ok(#result) + } + } + } +} + +fn panic_one_field(trait_name: &str) -> ! { + panic!(format!( + "Only structs with one field can derive({})", + trait_name + )) +} + +fn tuple_from_str<'a>( + input_type: &Ident, + trait_name: &str, + fields: &[&'a Field], +) -> (TokenStream, &'a Type) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_type = &field.ty; + (quote!(#input_type(#field_type::from_str(src)?)), field_type) +} + +fn struct_from_str<'a>( + input_type: &Ident, + trait_name: &str, + fields: &[&'a Field], +) -> (TokenStream, &'a Type) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_type = &field.ty; + let field_ident = &field.ident; + ( + quote!(#input_type{#field_ident: #field_type::from_str(src)?}), + field_type, + ) +} diff --git a/third_party/rust/derive_more/src/index.rs b/third_party/rust/derive_more/src/index.rs new file mode 100644 index 000000000000..a535e09513e4 --- /dev/null +++ b/third_party/rust/derive_more/src/index.rs @@ -0,0 +1,75 @@ +use proc_macro2::{Span, TokenStream}; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{add_where_clauses_for_new_ident, named_to_vec, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(Index)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let index_type = &Ident::new("__IdxT", Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident<#index_type>); + let input_type = &input.ident; + let field_vec: Vec<&Field>; + let member = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + field_vec = unnamed_to_vec(fields); + tuple_from_str(trait_name, &field_vec) + } + Fields::Named(ref fields) => { + field_vec = named_to_vec(fields); + struct_from_str(trait_name, &field_vec) + } + Fields::Unit => panic_one_field(trait_name), + }, + _ => panic_one_field(trait_name), + }; + let field_type = &field_vec[0].ty; + let type_where_clauses = quote!{ + where #field_type: #trait_path + }; + + let new_generics = add_where_clauses_for_new_ident( + &input.generics, + &field_vec, + index_type, + type_where_clauses, + ); + + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let (_, ty_generics, _) = input.generics.split_for_impl(); + // let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let casted_trait = "e!(<#field_type as #trait_path>); + quote!{ + impl#impl_generics #trait_path for #input_type#ty_generics #where_clause + { + type Output = #casted_trait::Output; + #[inline] + fn index(&self, idx: #index_type) -> &Self::Output { + #casted_trait::index(&#member, idx) + } + } + } +} + +fn panic_one_field(trait_name: &str) -> ! { + panic!(format!( + "Only structs with one field can derive({})", + trait_name + )) +} + +fn tuple_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> (TokenStream) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + quote!(self.0) +} + +fn struct_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> TokenStream { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_ident = &field.ident; + quote!(self.#field_ident) +} diff --git a/third_party/rust/derive_more/src/index_mut.rs b/third_party/rust/derive_more/src/index_mut.rs new file mode 100644 index 000000000000..5999fe717693 --- /dev/null +++ b/third_party/rust/derive_more/src/index_mut.rs @@ -0,0 +1,74 @@ +use proc_macro2::{Span, TokenStream}; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{add_where_clauses_for_new_ident, named_to_vec, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(IndexMut)]` into an implementation of `From` +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let index_type = &Ident::new("__IdxT", Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident<#index_type>); + let input_type = &input.ident; + let field_vec: Vec<&Field>; + let member = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + field_vec = unnamed_to_vec(fields); + tuple_from_str(trait_name, &field_vec) + } + Fields::Named(ref fields) => { + field_vec = named_to_vec(fields); + struct_from_str(trait_name, &field_vec) + } + Fields::Unit => panic_one_field(trait_name), + }, + _ => panic_one_field(trait_name), + }; + let field_type = &field_vec[0].ty; + let type_where_clauses = quote!{ + where #field_type: #trait_path + }; + + let new_generics = add_where_clauses_for_new_ident( + &input.generics, + &field_vec, + index_type, + type_where_clauses, + ); + + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let (_, ty_generics, _) = input.generics.split_for_impl(); + // let generics = add_extra_ty_param_bound(&input.generics, trait_path); + let casted_trait = "e!(<#field_type as #trait_path>); + quote!{ + impl#impl_generics #trait_path for #input_type#ty_generics #where_clause + { + #[inline] + fn index_mut(&mut self, idx: #index_type) -> &mut Self::Output { + #casted_trait::index_mut(&mut #member, idx) + } + } + } +} + +fn panic_one_field(trait_name: &str) -> ! { + panic!(format!( + "Only structs with one field can derive({})", + trait_name + )) +} + +fn tuple_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> (TokenStream) { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + quote!(self.0) +} + +fn struct_from_str<'a>(trait_name: &str, fields: &[&'a Field]) -> TokenStream { + if fields.len() != 1 { + panic_one_field(trait_name) + }; + let field = &fields[0]; + let field_ident = &field.ident; + quote!(self.#field_ident) +} diff --git a/third_party/rust/derive_more/src/into.rs b/third_party/rust/derive_more/src/into.rs new file mode 100644 index 000000000000..add48287f7d3 --- /dev/null +++ b/third_party/rust/derive_more/src/into.rs @@ -0,0 +1,53 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use syn::{Data, DeriveInput, Field, Fields}; +use utils::{field_idents, get_field_types, named_to_vec, number_idents, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(Into)]` into an implementation of `Into` +pub fn expand(input: &DeriveInput, _: &str) -> TokenStream { + let input_type = &input.ident; + let field_vec: Vec<_>; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let (field_names, fields) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + field_vec = unnamed_to_vec(fields); + (tuple_field_names(&field_vec), field_vec) + } + Fields::Named(ref fields) => { + field_vec = named_to_vec(fields); + (struct_field_names(&field_vec), field_vec) + } + Fields::Unit => (vec![], vec![]), + }, + _ => panic!("Only structs can derive Into"), + }; + + let original_types = &get_field_types(&fields); + + quote!{ + impl#impl_generics ::std::convert::From<#input_type#ty_generics> for + (#(#original_types),*) #where_clause { + + #[allow(unused_variables)] + #[inline] + fn from(original: #input_type#ty_generics) -> (#(#original_types),*) { + (#(original.#field_names),*) + } + } + } +} + +fn tuple_field_names(fields: &[&Field]) -> Vec { + number_idents(fields.len()) + .iter() + .map(|f| f.into_token_stream()) + .collect() +} + +fn struct_field_names(fields: &[&Field]) -> Vec { + field_idents(fields) + .iter() + .map(|f| (*f).into_token_stream()) + .collect() +} diff --git a/third_party/rust/derive_more/src/lib.rs b/third_party/rust/derive_more/src/lib.rs new file mode 100644 index 000000000000..774c5252a7a1 --- /dev/null +++ b/third_party/rust/derive_more/src/lib.rs @@ -0,0 +1,293 @@ +//! # `derive_more` +//! Rust has lots of builtin traits that are implemented for its basic types, such as [`Add`], +//! [`Not`] or [`From`]. +//! However, when wrapping these types inside your own structs or enums you lose the +//! implementations of these traits and are required to recreate them. +//! This is especially annoying when your own structures are very simple, such as when using the +//! commonly advised newtype pattern (e.g. `MyInt(i32)`). +//! +//! This library tries to remove these annoyances and the corresponding boilerplate code. +//! It does this by allowing you to derive lots of commonly used traits for both structs and enums. +//! +//! ## Example code +//! +//! By using this library the following code just works: +//! +//! +//! ```rust +//! #[macro_use] +//! extern crate derive_more; +//! +//! #[derive(Debug, Eq, PartialEq, From, Add)] +//! struct MyInt(i32); +//! +//! #[derive(Debug, Eq, PartialEq, From, Into, Constructor, Mul)] +//! struct Point2D { +//! x: i32, +//! y: i32, +//! } +//! +//! #[derive(Debug, Eq, PartialEq, From, Add)] +//! enum MyEnum { +//! Int(i32), +//! UnsignedInt(u32), +//! Nothing, +//! } +//! +//! fn main() { +//! let my_11 = MyInt(5) + 6.into(); +//! assert_eq!(MyInt(11), MyInt(5) + 6.into()); +//! assert_eq!(Point2D { x: 5, y: 6 } * 10, (50, 60).into()); +//! assert_eq!((5, 6), Point2D { x: 5, y: 6 }.into()); +//! assert_eq!(Point2D { x: 5, y: 6 }, Point2D::new(5, 6)); +//! assert_eq!(MyEnum::Int(15), (MyEnum::Int(8) + 7.into()).unwrap()) +//! } +//! ``` +//! +//! ## The derivable traits +//! +//! Below are all the traits that you can derive using this library. +//! Some trait derivations are so similar that the further documentation will only show a single one +//! of them. +//! You can recognize these by the "-like" suffix in their name. +//! The trait name before that will be the only one that is used throughout the further +//! documentation. +//! +//! **NOTE**: You still have to derive each trait separately. So `#[derive(Mul)]` doesn't +//! automatically derive `Div` as well. To derive both you should do `#[derive(Mul, Div)]` +//! +//! ### Conversion traits +//! These are traits that are used to convert automatically between types. +//! +//! 1. [`From`] +//! 2. [`Into`] +//! 3. [`FromStr`] +//! 4. [`TryInto`] (nightly-only as of writing) +//! +//! ### Formatting traits +//! These traits are used for converting a struct to a string in different ways. +//! +//! 1. `Display`-like, contains [`Display`], [`Binary`], [`Octal`], [`LowerHex`], [`UpperHex`], +//! [`LowerExp`], [`UpperExp`], [`Pointer`] +//! +//! ### Operators +//! These are traits that can be used for operator overloading. +//! +//! 1. [`Index`] +//! 2. [`Deref`] +//! 3. `Not`-like, contains [`Not`] and [`Neg`] +//! 4. `Add`-like, contains [`Add`], [`Sub`], [`BitAnd`], [`BitOr`] and [`BitXor`] +//! 5. `Mul`-like, contains [`Mul`], [`Div`], [`Rem`], [`Shr`] and [`Shl`] +//! 6. [`IndexMut`] +//! 7. [`DerefMut`] +//! 8. `AddAssign`-like, contains [`AddAssign`], [`SubAssign`], [`BitAndAssign`], [`BitOrAssign`] +//! and [`BitXorAssign`] +//! 9. `MulAssign`-like, contains [`MulAssign`], [`DivAssign`], [`RemAssign`], [`ShrAssign`] and +//! [`ShlAssign`] +//! +//! ### Static methods +//! These don't derive traits, but derive static methods instead. +//! +//! 1. `Constructor`, this derives a `new` method that can be used as a constructor. This is very +//! basic if you need more customization for your constructor, check out the [`derive-new`] crate. +//! +//! +//! ## Generated code +//! +//! It is important to understand what code gets generated when using one of the derives from this +//! crate. +//! That is why the links below explain what code gets generated for a trait for each group from +//! before. +//! +//! 1. [`#[derive(From)]`](https://jeltef.github.io/derive_more/derive_more/from.html) +//! 2. [`#[derive(Into)]`](https://jeltef.github.io/derive_more/derive_more/into.html) +//! 3. [`#[derive(FromStr)]`](https://jeltef.github.io/derive_more/derive_more/from_str.html) +//! 4. [`#[derive(TryInto)]`](https://jeltef.github.io/derive_more/derive_more/try_into.html) +//! 5. [`#[derive(Display)]`](https://jeltef.github.io/derive_more/derive_more/display.html) +//! 6. [`#[derive(Index)]`](https://jeltef.github.io/derive_more/derive_more/index_op.html) +//! 7. [`#[derive(Deref)]`](https://jeltef.github.io/derive_more/derive_more/deref.html) +//! 8. [`#[derive(Not)]`](https://jeltef.github.io/derive_more/derive_more/not.html) +//! 9. [`#[derive(Add)]`](https://jeltef.github.io/derive_more/derive_more/add.html) +//! 10. [`#[derive(Mul)]`](https://jeltef.github.io/derive_more/derive_more/mul.html) +//! 11. [`#[derive(IndexMut)]`](https://jeltef.github.io/derive_more/derive_more/index_mut.html) +//! 12. [`#[derive(DerefMut)]`](https://jeltef.github.io/derive_more/derive_more/deref_mut.html) +//! 13. [`#[derive(AddAssign)]`](https://jeltef.github.io/derive_more/derive_more/add_assign.html) +//! 14. [`#[derive(MulAssign)]`](https://jeltef.github.io/derive_more/derive_more/mul_assign.html) +//! 15. [`#[derive(Constructor)]`](https://jeltef.github.io/derive_more/derive_more/constructor.html) +//! +//! If you want to be sure what code is generated for your specific type I recommend using the +//! [`cargo-expand`] utility. +//! This will show you your code with all macros and derives expanded. +//! +//! ## Installation +//! +//! This library requires Rust 1.15 or higher, so this needs to be installed. +//! Then add the following to `Cargo.toml`: +//! +//! ```toml +//! [dependencies] +//! derive_more = "0.13.0" +//! ``` +//! +//! And this to the top of your Rust file: +//! +//! ```rust +//! #[macro_use] +//! extern crate derive_more; +//! # fn main () {} +//! ``` +//! +//! [`cargo-expand`]: https://github.com/dtolnay/cargo-expand +//! [`derive-new`]: https://github.com/nrc/derive-new +//! [`From`]: https://doc.rust-lang.org/core/convert/trait.From.html +//! [`Into`]: https://doc.rust-lang.org/core/convert/trait.Into.html +//! [`FromStr`]: https://doc.rust-lang.org/std/str/trait.FromStr.html +//! [`TryInto`]: https://doc.rust-lang.org/core/convert/trait.TryInto.html +//! [`Display`]: https://doc.rust-lang.org/std/fmt/trait.Display.html +//! [`Binary`]: https://doc.rust-lang.org/std/fmt/trait.Binary.html +//! [`Octal`]: https://doc.rust-lang.org/std/fmt/trait.Octal.html +//! [`LowerHex`]: https://doc.rust-lang.org/std/fmt/trait.LowerHex.html +//! [`UpperHex`]: https://doc.rust-lang.org/std/fmt/trait.UpperHex.html +//! [`LowerExp`]: https://doc.rust-lang.org/std/fmt/trait.LowerExp.html +//! [`UpperExp`]: https://doc.rust-lang.org/std/fmt/trait.UpperExp.html +//! [`Pointer`]: https://doc.rust-lang.org/std/fmt/trait.Pointer.html +//! [`Index`]: https://doc.rust-lang.org/std/ops/trait.Index.html +//! [`Deref`]: https://doc.rust-lang.org/std/ops/trait.Deref.html +//! [`Not`]: https://doc.rust-lang.org/std/ops/trait.Not.html +//! [`Neg`]: https://doc.rust-lang.org/std/ops/trait.Neg.html +//! [`Add`]: https://doc.rust-lang.org/std/ops/trait.Add.html +//! [`Sub`]: https://doc.rust-lang.org/std/ops/trait.Sub.html +//! [`BitAnd`]: https://doc.rust-lang.org/std/ops/trait.BitAnd.html +//! [`BitOr`]: https://doc.rust-lang.org/std/ops/trait.BitOr.html +//! [`BitXor`]: https://doc.rust-lang.org/std/ops/trait.BitXor.html +//! [`Mul`]: https://doc.rust-lang.org/std/ops/trait.Mul.html +//! [`Div`]: https://doc.rust-lang.org/std/ops/trait.Div.html +//! [`Rem`]: https://doc.rust-lang.org/std/ops/trait.Rem.html +//! [`Shr`]: https://doc.rust-lang.org/std/ops/trait.Shr.html +//! [`Shl`]: https://doc.rust-lang.org/std/ops/trait.Shl.html +//! [`IndexMut`]: https://doc.rust-lang.org/std/ops/trait.IndexMut.html +//! [`DerefMut`]: https://doc.rust-lang.org/std/ops/trait.DerefMut.html +//! [`AddAssign`]: https://doc.rust-lang.org/std/ops/trait.AddAssign.html +//! [`SubAssign`]: https://doc.rust-lang.org/std/ops/trait.SubAssign.html +//! [`BitAndAssign`]: https://doc.rust-lang.org/std/ops/trait.BitAndAssign.html +//! [`BitOrAssign`]: https://doc.rust-lang.org/std/ops/trait.BitOrAssign.html +//! [`BitXorAssign`]: https://doc.rust-lang.org/std/ops/trait.BitXorAssign.html +//! [`MulAssign`]: https://doc.rust-lang.org/std/ops/trait.MulAssign.html +//! [`DivAssign`]: https://doc.rust-lang.org/std/ops/trait.DivAssign.html +//! [`RemAssign`]: https://doc.rust-lang.org/std/ops/trait.RemAssign.html +//! [`ShrAssign`]: https://doc.rust-lang.org/std/ops/trait.ShrAssign.html +//! [`ShlAssign`]: https://doc.rust-lang.org/std/ops/trait.ShlAssign.html + +#![recursion_limit = "128"] +extern crate proc_macro; +extern crate proc_macro2; +#[macro_use] +extern crate quote; +extern crate syn; + +use proc_macro::TokenStream; +use syn::parse::Error as ParseError; + +mod utils; + +mod add_assign_like; +mod add_like; +mod constructor; +mod deref; +mod deref_mut; +mod display; +mod from; +mod from_str; +mod index; +mod index_mut; +mod into; +mod mul_assign_like; +mod mul_like; +mod not_like; +mod try_into; + +// This trait describes the possible return types of +// the derives. A derive can generally be infallible and +// return a TokenStream, or it can be fallible and return +// a Result. +trait Output { + fn process(self) -> TokenStream; +} + +impl Output for proc_macro2::TokenStream { + fn process(self) -> TokenStream { + self.into() + } +} + +impl Output for Result { + fn process(self) -> TokenStream { + match self { + Ok(ts) => ts.into(), + Err(e) => e.to_compile_error().into(), + } + } +} + +macro_rules! create_derive( + ($mod_:ident, $trait_:ident, $fn_name: ident $(,$attribute:ident)*) => { + #[proc_macro_derive($trait_, attributes($($attribute),*))] + #[doc(hidden)] + pub fn $fn_name(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + Output::process($mod_::expand(&ast, stringify!($trait_))) + } + } +); + +create_derive!(from, From, from_derive); + +create_derive!(into, Into, into_derive); + +create_derive!(constructor, Constructor, constructor_derive); + +create_derive!(not_like, Not, not_derive); +create_derive!(not_like, Neg, neg_derive); + +create_derive!(add_like, Add, add_derive); +create_derive!(add_like, Sub, sub_derive); +create_derive!(add_like, BitAnd, bit_and_derive); +create_derive!(add_like, BitOr, bit_or_derive); +create_derive!(add_like, BitXor, bit_xor_derive); + +create_derive!(mul_like, Mul, mul_derive); +create_derive!(mul_like, Div, div_derive); +create_derive!(mul_like, Rem, rem_derive); +create_derive!(mul_like, Shr, shr_derive); +create_derive!(mul_like, Shl, shl_derive); + +create_derive!(add_assign_like, AddAssign, add_assign_derive); +create_derive!(add_assign_like, SubAssign, sub_assign_derive); +create_derive!(add_assign_like, BitAndAssign, bit_and_assign_derive); +create_derive!(add_assign_like, BitOrAssign, bit_or_assign_derive); +create_derive!(add_assign_like, BitXorAssign, bit_xor_assign_derive); + +create_derive!(mul_assign_like, MulAssign, mul_assign_derive); +create_derive!(mul_assign_like, DivAssign, div_assign_derive); +create_derive!(mul_assign_like, RemAssign, rem_assign_derive); +create_derive!(mul_assign_like, ShrAssign, shr_assign_derive); +create_derive!(mul_assign_like, ShlAssign, shl_assign_derive); + +create_derive!(from_str, FromStr, from_str_derive); + +create_derive!(display, Display, display_derive, display); +create_derive!(display, Binary, binary_derive, binary); +create_derive!(display, Octal, octal_derive, octal); +create_derive!(display, LowerHex, lower_hex_derive, lower_hex); +create_derive!(display, UpperHex, upper_hex_derive, upper_hex); +create_derive!(display, LowerExp, lower_exp_derive, lower_exp); +create_derive!(display, UpperExp, upper_exp_derive, upper_exp); +create_derive!(display, Pointer, pointer_derive, pointer); + +create_derive!(index, Index, index_derive); +create_derive!(index_mut, IndexMut, index_mut_derive); + +create_derive!(try_into, TryInto, try_into_derive); + +create_derive!(deref, Deref, deref_derive); +create_derive!(deref_mut, DerefMut, deref_mut_derive); diff --git a/third_party/rust/derive_more/src/mul_assign_like.rs b/third_party/rust/derive_more/src/mul_assign_like.rs new file mode 100644 index 000000000000..1b919860fd89 --- /dev/null +++ b/third_party/rust/derive_more/src/mul_assign_like.rs @@ -0,0 +1,56 @@ +use mul_like::{struct_exprs, tuple_exprs}; +use proc_macro2::{Span, TokenStream}; +use std::collections::HashSet; +use std::iter; +use syn::{Data, DeriveInput, Fields, Ident}; +use utils::{add_where_clauses_for_new_ident, get_field_types_iter, named_to_vec, unnamed_to_vec}; + +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident); + let method_name = trait_name.to_string(); + let method_name = method_name.trim_right_matches("Assign"); + let method_name = method_name.to_lowercase(); + let method_ident = Ident::new(&(method_name.to_string() + "_assign"), Span::call_site()); + let input_type = &input.ident; + + let (exprs, fields) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + let field_vec = unnamed_to_vec(fields); + (tuple_exprs(&field_vec, &method_ident), field_vec) + } + Fields::Named(ref fields) => { + let field_vec = named_to_vec(fields); + (struct_exprs(&field_vec, &method_ident), field_vec) + } + _ => panic!(format!("Unit structs cannot use derive({})", trait_name)), + }, + + _ => panic!(format!("Only structs can use derive({})", trait_name)), + }; + + let scalar_ident = &Ident::new("__RhsT", Span::call_site()); + let tys: &HashSet<_> = &get_field_types_iter(&fields).collect(); + let scalar_iter = iter::repeat(scalar_ident); + let trait_path_iter = iter::repeat(trait_path); + + let type_where_clauses = quote!{ + where #(#tys: #trait_path_iter<#scalar_iter>),* + }; + + let new_generics = + add_where_clauses_for_new_ident(&input.generics, &fields, scalar_ident, type_where_clauses); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let (_, ty_generics, _) = input.generics.split_for_impl(); + + quote!( + impl#impl_generics #trait_path<#scalar_ident> for #input_type#ty_generics #where_clause{ + #[inline] + fn #method_ident(&mut self, rhs: #scalar_ident#ty_generics) { + #(#exprs; + )* + } + } + ) +} diff --git a/third_party/rust/derive_more/src/mul_like.rs b/third_party/rust/derive_more/src/mul_like.rs new file mode 100644 index 000000000000..c1c85031ba6a --- /dev/null +++ b/third_party/rust/derive_more/src/mul_like.rs @@ -0,0 +1,97 @@ +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; +use std::collections::HashSet; +use std::iter; +use syn::{Data, DeriveInput, Field, Fields, Ident}; +use utils::{ + add_where_clauses_for_new_ident, field_idents, get_field_types_iter, named_to_vec, + number_idents, unnamed_to_vec, +}; + +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let trait_path = "e!(::std::ops::#trait_ident); + let method_name = trait_name.to_lowercase(); + let method_ident = &Ident::new(&method_name, Span::call_site()); + let input_type = &input.ident; + + let (block, fields) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => { + let field_vec = unnamed_to_vec(fields); + ( + tuple_content(input_type, &field_vec, method_ident), + field_vec, + ) + } + Fields::Named(ref fields) => { + let field_vec = named_to_vec(fields); + ( + struct_content(input_type, &field_vec, method_ident), + field_vec, + ) + } + _ => panic!(format!("Unit structs cannot use derive({})", trait_name)), + }, + _ => panic!(format!("Only structs can use derive({})", trait_name)), + }; + + let scalar_ident = &Ident::new("__RhsT", Span::call_site()); + let tys: &HashSet<_> = &get_field_types_iter(&fields).collect(); + let tys2 = tys; + let scalar_iter = iter::repeat(scalar_ident); + let trait_path_iter = iter::repeat(trait_path); + + let type_where_clauses = quote!{ + where #(#tys: #trait_path_iter<#scalar_iter, Output=#tys2>),* + }; + + let new_generics = + add_where_clauses_for_new_ident(&input.generics, &fields, scalar_ident, type_where_clauses); + let (impl_generics, _, where_clause) = new_generics.split_for_impl(); + let (_, ty_generics, _) = input.generics.split_for_impl(); + + quote!( + impl#impl_generics #trait_path<#scalar_ident> for #input_type#ty_generics #where_clause { + type Output = #input_type#ty_generics; + #[inline] + fn #method_ident(self, rhs: #scalar_ident) -> #input_type#ty_generics { + #block + } + } + + ) +} + +fn tuple_content<'a, T: ToTokens>( + input_type: &T, + fields: &[&'a Field], + method_ident: &Ident, +) -> TokenStream { + let exprs = tuple_exprs(fields, method_ident); + quote!(#input_type(#(#exprs),*)) +} + +pub fn tuple_exprs(fields: &[&Field], method_ident: &Ident) -> Vec { + number_idents(fields.len()) + .iter() + .map(|i| quote!(self.#i.#method_ident(rhs))) + .collect() +} + +fn struct_content<'a, T: ToTokens>( + input_type: &T, + fields: &[&'a Field], + method_ident: &Ident, +) -> TokenStream { + let exprs = struct_exprs(fields, method_ident); + let field_names = field_idents(fields); + quote!(#input_type{#(#field_names: #exprs),*}) +} + +pub fn struct_exprs(fields: &[&Field], method_ident: &Ident) -> Vec { + field_idents(fields) + .iter() + .map(|f| quote!(self.#f.#method_ident(rhs))) + .collect() +} diff --git a/third_party/rust/derive_more/src/not_like.rs b/third_party/rust/derive_more/src/not_like.rs new file mode 100644 index 000000000000..89d3586c52f4 --- /dev/null +++ b/third_party/rust/derive_more/src/not_like.rs @@ -0,0 +1,159 @@ +use proc_macro2::{Span, TokenStream}; +use quote::ToTokens; +use std::iter; +use syn::{Data, DataEnum, DeriveInput, Field, Fields, Ident, Index}; +use utils::{add_extra_type_param_bound_op_output, named_to_vec, unnamed_to_vec}; + +pub fn expand(input: &DeriveInput, trait_name: &str) -> TokenStream { + let trait_ident = Ident::new(trait_name, Span::call_site()); + let method_name = trait_name.to_lowercase(); + let method_ident = &Ident::new(&method_name, Span::call_site()); + let input_type = &input.ident; + + let generics = add_extra_type_param_bound_op_output(&input.generics, &trait_ident); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let (output_type, block) = match input.data { + Data::Struct(ref data_struct) => match data_struct.fields { + Fields::Unnamed(ref fields) => ( + quote!(#input_type#ty_generics), + tuple_content(input_type, &unnamed_to_vec(fields), method_ident), + ), + Fields::Named(ref fields) => ( + quote!(#input_type#ty_generics), + struct_content(input_type, &named_to_vec(fields), method_ident), + ), + _ => panic!(format!("Unit structs cannot use derive({})", trait_name)), + }, + Data::Enum(ref data_enum) => enum_output_type_and_content(input, data_enum, method_ident), + + _ => panic!(format!( + "Only structs and enums can use derive({})", + trait_name + )), + }; + + quote!( + impl#impl_generics ::std::ops::#trait_ident for #input_type#ty_generics #where_clause { + type Output = #output_type; + fn #method_ident(self) -> #output_type { + #block + } + } + ) +} + +fn tuple_content( + input_type: &T, + fields: &[&Field], + method_ident: &Ident, +) -> TokenStream { + let mut exprs = vec![]; + + for i in 0..fields.len() { + let i = Index::from(i); + // generates `self.0.add()` + let expr = quote!(self.#i.#method_ident()); + exprs.push(expr); + } + + quote!(#input_type(#(#exprs),*)) +} + +fn struct_content(input_type: &Ident, fields: &[&Field], method_ident: &Ident) -> TokenStream { + let mut exprs = vec![]; + + for field in fields { + // It's safe to unwrap because struct fields always have an identifier + let field_id = field.ident.as_ref(); + // generates `x: self.x.not()` + let expr = quote!(#field_id: self.#field_id.#method_ident()); + exprs.push(expr) + } + + quote!(#input_type{#(#exprs),*}) +} + +fn enum_output_type_and_content( + input: &DeriveInput, + data_enum: &DataEnum, + method_ident: &Ident, +) -> (TokenStream, TokenStream) { + let input_type = &input.ident; + let (_, ty_generics, _) = input.generics.split_for_impl(); + let mut matches = vec![]; + let mut method_iter = iter::repeat(method_ident); + // If the enum contains unit types that means it can error. + let has_unit_type = data_enum.variants.iter().any(|v| v.fields == Fields::Unit); + + for variant in &data_enum.variants { + let subtype = &variant.ident; + let subtype = quote!(#input_type::#subtype); + + match variant.fields { + Fields::Unnamed(ref fields) => { + // The patern that is outputted should look like this: + // (Subtype(vars)) => Ok(TypePath(exprs)) + let size = unnamed_to_vec(fields).len(); + let vars: &Vec<_> = &(0..size) + .map(|i| Ident::new(&format!("__{}", i), Span::call_site())) + .collect(); + let method_iter = method_iter.by_ref(); + let mut body = quote!(#subtype(#(#vars.#method_iter()),*)); + if has_unit_type { + body = quote!(::std::result::Result::Ok(#body)) + } + let matcher = quote!{ + #subtype(#(#vars),*) => { + #body + } + }; + matches.push(matcher); + } + Fields::Named(ref fields) => { + // The patern that is outputted should look like this: + // (Subtype{a: __l_a, ...} => { + // Ok(Subtype{a: __l_a.neg(__r_a), ...}) + // } + let field_vec = named_to_vec(fields); + let size = field_vec.len(); + let field_names: &Vec<_> = &field_vec + .iter() + .map(|f| f.ident.as_ref().unwrap()) + .collect(); + let vars: &Vec<_> = &(0..size) + .map(|i| Ident::new(&format!("__{}", i), Span::call_site())) + .collect(); + let method_iter = method_iter.by_ref(); + let mut body = quote!(#subtype{#(#field_names: #vars.#method_iter()),*}); + if has_unit_type { + body = quote!(::std::result::Result::Ok(#body)) + } + let matcher = quote!{ + #subtype{#(#field_names: #vars),*} => { + #body + } + }; + matches.push(matcher); + } + Fields::Unit => { + let message = format!("Cannot {}() unit variants", method_ident.to_string()); + matches.push(quote!(#subtype => ::std::result::Result::Err(#message))); + } + } + } + + let body = quote!( + match self { + #(#matches),* + } + ); + + let output_type = if has_unit_type { + quote!(::std::result::Result<#input_type#ty_generics, &'static str>) + } else { + quote!(#input_type#ty_generics) + }; + + (output_type, body) +} diff --git a/third_party/rust/derive_more/src/try_into.rs b/third_party/rust/derive_more/src/try_into.rs new file mode 100644 index 000000000000..8a55dbbcc321 --- /dev/null +++ b/third_party/rust/derive_more/src/try_into.rs @@ -0,0 +1,91 @@ +use proc_macro2::TokenStream; +use quote::ToTokens; +use std::collections::HashMap; +use syn::{Data, DataEnum, DeriveInput, Fields}; +use utils::{field_idents, named_to_vec, numbered_vars, unnamed_to_vec}; + +/// Provides the hook to expand `#[derive(TryInto)]` into an implementation of `TryInto` +pub fn expand(input: &DeriveInput, _: &str) -> TokenStream { + match input.data { + Data::Enum(ref data_enum) => enum_try_into(input, data_enum), + _ => panic!("Only enums can derive TryInto"), + } +} + +fn enum_try_into(input: &DeriveInput, data_enum: &DataEnum) -> TokenStream { + let mut variants_per_types = HashMap::new(); + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let input_type = &input.ident; + + for variant in &data_enum.variants { + let original_types = match variant.fields { + Fields::Unnamed(ref fields) => unnamed_to_vec(fields).iter().map(|f| &f.ty).collect(), + Fields::Named(ref fields) => named_to_vec(fields).iter().map(|f| &f.ty).collect(), + Fields::Unit => vec![], + }; + variants_per_types + .entry(original_types) + .or_insert_with(Vec::new) + .push(variant); + } + + let mut tokens = TokenStream::new(); + + for (ref original_types, ref variants) in variants_per_types { + let mut matchers = vec![]; + let vars = &numbered_vars(original_types.len(), ""); + for variant in variants.iter() { + let subtype = &variant.ident; + let subtype = quote!(#input_type::#subtype); + matchers.push(match variant.fields { + Fields::Unnamed(_) => quote!(#subtype(#(#vars),*)), + Fields::Named(ref fields) => { + let field_vec = &named_to_vec(fields); + let field_names = &field_idents(field_vec); + quote!(#subtype{#(#field_names: #vars),*}) + } + Fields::Unit => quote!(#subtype), + }); + } + + let vars = if vars.len() == 1 { + quote!(#(#vars)*) + } else { + quote!((#(#vars),*)) + }; + + let output_type = if original_types.len() == 1 { + format!("{}", quote!(#(#original_types)*)) + } else { + let types = original_types + .iter() + .map(|t| format!("{}", quote!(#t))) + .collect::>(); + format!("({})", types.join(", ")) + }; + let variants = variants + .iter() + .map(|v| format!("{}", v.ident)) + .collect::>() + .join(", "); + let message = format!("Only {} can be converted to {}", variants, output_type); + + let try_from = quote!{ + impl#impl_generics ::std::convert::TryFrom<#input_type#ty_generics> for + (#(#original_types),*) #where_clause { + type Error = &'static str; + + #[allow(unused_variables)] + #[inline] + fn try_from(value: #input_type#ty_generics) -> Result { + match value { + #(#matchers)|* => ::std::result::Result::Ok(#vars), + _ => ::std::result::Result::Err(#message), + } + } + } + }; + try_from.to_tokens(&mut tokens) + } + tokens +} diff --git a/third_party/rust/derive_more/src/utils.rs b/third_party/rust/derive_more/src/utils.rs new file mode 100644 index 000000000000..ecbf429fd3ba --- /dev/null +++ b/third_party/rust/derive_more/src/utils.rs @@ -0,0 +1,105 @@ +use proc_macro2::{Span, TokenStream}; +use syn::{ + parse_str, Field, FieldsNamed, FieldsUnnamed, GenericParam, + Generics, Ident, Index, Type, TypeParamBound, WhereClause, +}; + +pub fn numbered_vars(count: usize, prefix: &str) -> Vec { + (0..count) + .map(|i| Ident::new(&format!("__{}{}", prefix, i), Span::call_site())) + .collect() +} + +pub fn number_idents(count: usize) -> Vec { + (0..count).map(Index::from).collect() +} + +pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> { + fields + .iter() + .map(|f| { + f.ident + .as_ref() + .expect("Tried to get field names of a tuple struct") + }).collect() +} + +pub fn get_field_types_iter<'a>(fields: &'a [&'a Field]) -> Box + 'a> { + Box::new(fields.iter().map(|f| &f.ty)) +} + +pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> { + get_field_types_iter(fields).collect() +} + +pub fn add_extra_type_param_bound_op_output<'a>( + generics: &'a Generics, + trait_ident: &'a Ident, +) -> Generics { + let mut generics = generics.clone(); + for type_param in &mut generics.type_params_mut() { + let type_ident = &type_param.ident; + let bound: TypeParamBound = + parse_str("e!(::std::ops::#trait_ident).to_string()).unwrap(); + type_param.bounds.push(bound) + } + + generics +} + +pub fn add_extra_ty_param_bound_op<'a>(generics: &'a Generics, trait_ident: &'a Ident) -> Generics { + add_extra_ty_param_bound(generics, "e!(::std::ops::#trait_ident)) +} + +pub fn add_extra_ty_param_bound<'a>(generics: &'a Generics, bound: &'a TokenStream) -> Generics { + let mut generics = generics.clone(); + let bound: TypeParamBound = parse_str(&bound.to_string()).unwrap(); + for type_param in &mut generics.type_params_mut() { + type_param.bounds.push(bound.clone()) + } + + generics +} + +pub fn add_extra_generic_param(generics: &Generics, generic_param: TokenStream) -> Generics { + let generic_param: GenericParam = parse_str(&generic_param.to_string()).unwrap(); + let mut generics = generics.clone(); + generics.params.push(generic_param); + + generics +} + +pub fn add_extra_where_clauses(generics: &Generics, type_where_clauses: TokenStream) -> Generics { + let mut type_where_clauses: WhereClause = parse_str(&type_where_clauses.to_string()).unwrap(); + let mut new_generics = generics.clone(); + if let Some(old_where) = new_generics.where_clause { + type_where_clauses.predicates.extend(old_where.predicates) + } + new_generics.where_clause = Some(type_where_clauses); + + new_generics +} + +pub fn add_where_clauses_for_new_ident<'a>( + generics: &'a Generics, + fields: &[&'a Field], + type_ident: &Ident, + type_where_clauses: TokenStream, +) -> Generics { + let generic_param = if fields.len() > 1 { + quote!(#type_ident: ::std::marker::Copy) + } else { + quote!(#type_ident) + }; + + let generics = add_extra_where_clauses(generics, type_where_clauses); + add_extra_generic_param(&generics, generic_param) +} + +pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> { + fields.unnamed.iter().collect() +} + +pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> { + fields.named.iter().collect() +} diff --git a/third_party/rust/rustc_version/.cargo-checksum.json b/third_party/rust/rustc_version/.cargo-checksum.json index 2861f904a43a..f86fe1cf8b59 100644 --- a/third_party/rust/rustc_version/.cargo-checksum.json +++ b/third_party/rust/rustc_version/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"2f437f4dd58d6813bfa542ffb1ed4c970c3670739f92c41346230e7a5b05796a","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"b4cb2c1de00ae7382a77431d221a52e10a8a62170cdc1a2ad1c1e711bea7817f","src/errors.rs":"b28c2eeb1278fc3e8d68a64b177034faed67f6762335729d3a6d1e61be8fb034","src/lib.rs":"6a5d5ceb57cf03955af1dbb80a6401ca6d5eac65211d0594354b38b465ce7b45"},"package":"b9743a7670d88d5d52950408ecdb7c71d8986251ab604d4689dd2ca25c9bca69"} \ No newline at end of file +{"files":{"Cargo.toml":"80b9fb136c8c2945b4875b05b0f5a4b11e4722997e751f17d8d3f241d7c684db","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"58bd14a1dfa1d828e6e99f35c3b7c2149d08e2d990d6ca93f92ab8ffb43275b7","src/errors.rs":"b28c2eeb1278fc3e8d68a64b177034faed67f6762335729d3a6d1e61be8fb034","src/lib.rs":"92a32673f77961724bc52b872781f06d22d166f06838c9582c5adae3c5214f51"},"package":"138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"} \ No newline at end of file diff --git a/third_party/rust/rustc_version/Cargo.toml b/third_party/rust/rustc_version/Cargo.toml index 4a59bb4bbbff..3b252b85a26e 100644 --- a/third_party/rust/rustc_version/Cargo.toml +++ b/third_party/rust/rustc_version/Cargo.toml @@ -1,15 +1,26 @@ +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) + [package] name = "rustc_version" -version = "0.2.1" +version = "0.2.3" authors = ["Marvin Löbel "] -license = "MIT/Apache-2.0" - description = "A library for querying the version of a installed rustc compiler" +documentation = "https://docs.rs/rustc_version/" readme = "README.md" -documentation = "http://kimundi.github.io/rustc-version-rs/rustc_version/index.html" - -repository = "https://github.com/Kimundi/rustc-version-rs" keywords = ["version", "rustc"] - -[dependencies] -semver = "0.6" +license = "MIT/Apache-2.0" +repository = "https://github.com/Kimundi/rustc-version-rs" +[dependencies.semver] +version = "0.9" +[badges.travis-ci] +repository = "Kimundi/rustc-version-rs" diff --git a/third_party/rust/rustc_version/README.md b/third_party/rust/rustc_version/README.md index 4d49e8f9030a..f491ca964d85 100644 --- a/third_party/rust/rustc_version/README.md +++ b/third_party/rust/rustc_version/README.md @@ -18,7 +18,7 @@ At the point of the last update of this README, the latest published version cou Add the following dependency to your Cargo manifest... ```toml -[dependencies] +[build-dependencies] rustc_version = "0.2" ``` diff --git a/third_party/rust/rustc_version/src/lib.rs b/third_party/rust/rustc_version/src/lib.rs index 6d46331eae0a..c03828898fba 100644 --- a/third_party/rust/rustc_version/src/lib.rs +++ b/third_party/rust/rustc_version/src/lib.rs @@ -108,11 +108,8 @@ impl VersionMeta { pub fn for_command(cmd: Command) -> Result { let mut cmd = cmd; - let out = match cmd.arg("-vV").output() { - Err(e) => return Err(Error::CouldNotExecuteCommand(e)), - Ok(out) => out, - }; - let out = try!(str::from_utf8(&out.stdout)); + let out = cmd.arg("-vV").output().map_err(Error::CouldNotExecuteCommand)?; + let out = str::from_utf8(&out.stdout)?; version_meta_for(out) } @@ -120,7 +117,7 @@ impl VersionMeta { /// Returns the `rustc` SemVer version. pub fn version() -> Result { - Ok(try!(version_meta()).semver) + Ok(version_meta()?.semver) } /// Returns the `rustc` SemVer version and additional metadata @@ -129,7 +126,6 @@ pub fn version_meta() -> Result { let cmd = env::var_os("RUSTC").unwrap_or_else(|| OsString::from("rustc")); VersionMeta::for_command(Command::new(cmd)) - } /// Parses a "rustc -vV" output string and returns @@ -145,18 +141,19 @@ pub fn version_meta_for(verbose_version_string: &str) -> Result { let short_version_string = out[0]; fn expect_prefix<'a>(line: &'a str, prefix: &str) -> Result<&'a str> { - match line.starts_with(prefix) { - true => Ok(&line[prefix.len()..]), - false => Err(Error::UnexpectedVersionFormat), + if line.starts_with(prefix) { + Ok(&line[prefix.len()..]) + } else { + Err(Error::UnexpectedVersionFormat) } } - let commit_hash = match try!(expect_prefix(out[2], "commit-hash: ")) { + let commit_hash = match expect_prefix(out[2], "commit-hash: ")? { "unknown" => None, hash => Some(hash.to_owned()), }; - let commit_date = match try!(expect_prefix(out[3], "commit-date: ")) { + let commit_date = match expect_prefix(out[3], "commit-date: ")? { "unknown" => None, hash => Some(hash.to_owned()), }; @@ -165,29 +162,26 @@ pub fn version_meta_for(verbose_version_string: &str) -> Result { let mut idx = 4; let mut build_date = None; if out[idx].starts_with("build-date") { - build_date = match try!(expect_prefix(out[idx], "build-date: ")) { + build_date = match expect_prefix(out[idx], "build-date: ")? { "unknown" => None, s => Some(s.to_owned()), }; - idx = idx + 1; + idx += 1; } - let host = try!(expect_prefix(out[idx], "host: ")); - idx = idx + 1; - let release = try!(expect_prefix(out[idx], "release: ")); + let host = expect_prefix(out[idx], "host: ")?; + idx += 1; + let release = expect_prefix(out[idx], "release: ")?; - let semver: Version = try!(release.parse()); + let semver: Version = release.parse()?; let channel = if semver.pre.is_empty() { Channel::Stable } else { match semver.pre[0] { - Identifier::AlphaNumeric(ref s) - if s == "dev" => Channel::Dev, - Identifier::AlphaNumeric(ref s) - if s == "beta" => Channel::Beta, - Identifier::AlphaNumeric(ref s) - if s == "nightly" => Channel::Nightly, + Identifier::AlphaNumeric(ref s) if s == "dev" => Channel::Dev, + Identifier::AlphaNumeric(ref s) if s == "beta" => Channel::Beta, + Identifier::AlphaNumeric(ref s) if s == "nightly" => Channel::Nightly, ref x => return Err(Error::UnknownPreReleaseTag(x.clone())), } }; diff --git a/third_party/rust/semver-0.6.0/.cargo-checksum.json b/third_party/rust/semver-0.6.0/.cargo-checksum.json new file mode 100644 index 000000000000..94297ea4d8f7 --- /dev/null +++ b/third_party/rust/semver-0.6.0/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.toml":"d02f51526644dbe6c82add37202f246a6b95e185a5519ef0c3ca4d55a245f22c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"bb80bfbd16bf7dc34de45891c21333c42590d5c5c10e8ba0ed59549fce5af1dd","src/lib.rs":"b33fcb9a79d46a581a4628f7c2bb00f7ba3451b1acfeeae0b38ff22532ed5b68","src/version.rs":"fc36d1e58c9a73f46fdec63283fd50ea78c89a0f816b8abaaa89438fb0c47c70","src/version_req.rs":"093f2ac08f2bc8fcf6a93ae0fc333eccc1ea04932e0c0b26835a952bb220eca1","tests/deprecation.rs":"b5ec79e19d61968d05b96b876c449e54d43cbd1762c6e63c23c3470f9db56292","tests/regression.rs":"180b699ad029b81e6135d42f0a8e6d782177bc29a41132f875ee6f8607a46b56"},"package":"7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"} \ No newline at end of file diff --git a/third_party/rust/semver-0.6.0/Cargo.toml b/third_party/rust/semver-0.6.0/Cargo.toml new file mode 100644 index 000000000000..d21ea9db8f08 --- /dev/null +++ b/third_party/rust/semver-0.6.0/Cargo.toml @@ -0,0 +1,25 @@ +[package] + +name = "semver" +version = "0.6.0" +authors = ["Steve Klabnik ", "The Rust Project Developers"] +license = "MIT/Apache-2.0" +repository = "https://github.com/steveklabnik/semver" +homepage = "https://docs.rs/crate/semver/" +documentation = "https://docs.rs/crate/semver/" +description = """ +Semantic version parsing and comparison. +""" + +[dependencies] +semver-parser = "0.7.0" + +[features] +default = [] + +# are we testing on CI? +ci = [] + +[dev-dependencies] +crates-index = "0.5.0" +tempdir = "0.3.4" diff --git a/third_party/rust/semver-0.6.0/LICENSE-APACHE b/third_party/rust/semver-0.6.0/LICENSE-APACHE new file mode 100644 index 000000000000..16fe87b06e80 --- /dev/null +++ b/third_party/rust/semver-0.6.0/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/third_party/rust/semver-0.6.0/LICENSE-MIT b/third_party/rust/semver-0.6.0/LICENSE-MIT new file mode 100644 index 000000000000..39d4bdb5acd3 --- /dev/null +++ b/third_party/rust/semver-0.6.0/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2014 The Rust Project Developers + +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/third_party/rust/semver-0.6.0/README.md b/third_party/rust/semver-0.6.0/README.md new file mode 100644 index 000000000000..a3fe02c3d961 --- /dev/null +++ b/third_party/rust/semver-0.6.0/README.md @@ -0,0 +1,103 @@ +semver +====== + +Semantic version parsing and comparison. + +[![Build Status](https://api.travis-ci.org/steveklabnik/semver.svg?branch=master)](https://travis-ci.org/steveklabnik/semver) + +[Documentation](https://steveklabnik.github.io/semver) + +Semantic versioning (see http://semver.org/) is a set of rules for +assigning version numbers. + +## SemVer and the Rust ecosystem + +Rust itself follows the SemVer specification, as does its standard libraries. The two are +not tied together. + +[Cargo](https://crates.io), Rust's package manager, uses SemVer to determine which versions of +packages you need installed. + +## Installation + +To use `semver`, add this to your `[dependencies]` section: + +```toml +semver = "0.6.0" +``` + +And this to your crate root: + +```rust +extern crate semver; +``` + +## Versions + +At its simplest, the `semver` crate allows you to construct `Version` objects using the `parse` +method: + +```rust +use semver::Version; + +assert!(Version::parse("1.2.3") == Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec!(), + build: vec!(), +})); +``` + +If you have multiple `Version`s, you can use the usual comparison operators to compare them: + +```rust +use semver::Version; + +assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); +assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); +``` + +## Requirements + +The `semver` crate also provides the ability to compare requirements, which are more complex +comparisons. + +For example, creating a requirement that only matches versions greater than or +equal to 1.0.0: + +```rust +use semver::Version; +use semver::VersionReq; + +let r = VersionReq::parse(">= 1.0.0").unwrap(); +let v = Version::parse("1.0.0").unwrap(); + +assert!(r.to_string() == ">= 1.0.0".to_string()); +assert!(r.matches(&v)) +``` + +It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at +https://www.npmjs.org/doc/misc/semver.html + +**Tilde requirements** specify a minimal version with some updates: + +```notrust +~1.2.3 := >=1.2.3 <1.3.0 +~1.2 := >=1.2.0 <1.3.0 +~1 := >=1.0.0 <2.0.0 +``` + +**Caret requirements** allow SemVer compatible updates to a specified version, +`0.x` and `0.x+1` are not considered compatible, but `1.x` and `1.x+1` are. + +`0.0.x` is not considered compatible with any other version. +Missing minor and patch versions are desugared to `0` but allow flexibility for that value. + +```notrust +^1.2.3 := >=1.2.3 <2.0.0 +^0.2.3 := >=0.2.3 <0.3.0 +^0.0.3 := >=0.0.3 <0.0.4 +^0.0 := >=0.0.0 <0.1.0 +^0 := >=0.0.0 <1.0.0 +``` diff --git a/third_party/rust/semver-0.6.0/src/lib.rs b/third_party/rust/semver-0.6.0/src/lib.rs new file mode 100644 index 000000000000..1e74b01eaf1a --- /dev/null +++ b/third_party/rust/semver-0.6.0/src/lib.rs @@ -0,0 +1,178 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Semantic version parsing and comparison. +//! +//! Semantic versioning (see http://semver.org/) is a set of rules for +//! assigning version numbers. +//! +//! ## SemVer overview +//! +//! Given a version number MAJOR.MINOR.PATCH, increment the: +//! +//! 1. MAJOR version when you make incompatible API changes, +//! 2. MINOR version when you add functionality in a backwards-compatible +//! manner, and +//! 3. PATCH version when you make backwards-compatible bug fixes. +//! +//! Additional labels for pre-release and build metadata are available as +//! extensions to the MAJOR.MINOR.PATCH format. +//! +//! Any references to 'the spec' in this documentation refer to [version 2.0 of +//! the SemVer spec](http://semver.org/spec/v2.0.0.html). +//! +//! ## SemVer and the Rust ecosystem +//! +//! Rust itself follows the SemVer specification, as does its standard +//! libraries. The two are not tied together. +//! +//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine +//! which versions of packages you need installed. +//! +//! ## Versions +//! +//! At its simplest, the `semver` crate allows you to construct `Version` +//! objects using the `parse` method: +//! +//! ```{rust} +//! use semver::Version; +//! +//! assert!(Version::parse("1.2.3") == Ok(Version { +//! major: 1, +//! minor: 2, +//! patch: 3, +//! pre: vec!(), +//! build: vec!(), +//! })); +//! ``` +//! +//! If you have multiple `Version`s, you can use the usual comparison operators +//! to compare them: +//! +//! ```{rust} +//! use semver::Version; +//! +//! assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); +//! assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); +//! ``` +//! +//! If you explicitly need to modify a Version, SemVer also allows you to +//! increment the major, minor, and patch numbers in accordance with the spec. +//! +//! Please note that in order to do this, you must use a mutable Version: +//! +//! ```{rust} +//! use semver::Version; +//! +//! let mut bugfix_release = Version::parse("1.0.0").unwrap(); +//! bugfix_release.increment_patch(); +//! +//! assert_eq!(Ok(bugfix_release), Version::parse("1.0.1")); +//! ``` +//! +//! When incrementing the minor version number, the patch number resets to zero +//! (in accordance with section 7 of the spec) +//! +//! ```{rust} +//! use semver::Version; +//! +//! let mut feature_release = Version::parse("1.4.6").unwrap(); +//! feature_release.increment_minor(); +//! +//! assert_eq!(Ok(feature_release), Version::parse("1.5.0")); +//! ``` +//! +//! Similarly, when incrementing the major version number, the patch and minor +//! numbers reset to zero (in accordance with section 8 of the spec) +//! +//! ```{rust} +//! use semver::Version; +//! +//! let mut chrome_release = Version::parse("41.5.5377").unwrap(); +//! chrome_release.increment_major(); +//! +//! assert_eq!(Ok(chrome_release), Version::parse("42.0.0")); +//! ``` +//! +//! ## Requirements +//! +//! The `semver` crate also provides the ability to compare requirements, which +//! are more complex comparisons. +//! +//! For example, creating a requirement that only matches versions greater than +//! or equal to 1.0.0: +//! +//! ```{rust} +//! # #![allow(unstable)] +//! use semver::Version; +//! use semver::VersionReq; +//! +//! let r = VersionReq::parse(">= 1.0.0").unwrap(); +//! let v = Version::parse("1.0.0").unwrap(); +//! +//! assert!(r.to_string() == ">= 1.0.0".to_string()); +//! assert!(r.matches(&v)) +//! ``` +//! +//! It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at +//! https://www.npmjs.org/doc/misc/semver.html +//! +//! **Tilde requirements** specify a minimal version with some updates: +//! +//! ```notrust +//! ~1.2.3 := >=1.2.3 <1.3.0 +//! ~1.2 := >=1.2.0 <1.3.0 +//! ~1 := >=1.0.0 <2.0.0 +//! ``` +//! +//! **Caret requirements** allow SemVer compatible updates to a specified +//! verion, `0.x` and `0.x+1` are not considered compatible, but `1.x` and +//! `1.x+1` are. +//! +//! `0.0.x` is not considered compatible with any other version. +//! Missing minor and patch versions are desugared to `0` but allow flexibility +//! for that value. +//! +//! ```notrust +//! ^1.2.3 := >=1.2.3 <2.0.0 +//! ^0.2.3 := >=0.2.3 <0.3.0 +//! ^0.0.3 := >=0.0.3 <0.0.4 +//! ^0.0 := >=0.0.0 <0.1.0 +//! ^0 := >=0.0.0 <1.0.0 +//! ``` +//! +//! **Wildcard requirements** allows parsing of version requirements of the +//! formats `*`, `x.*` and `x.y.*`. +//! +//! ```notrust +//! * := >=0.0.0 +//! 1.* := >=1.0.0 <2.0.0 +//! 1.2.* := >=1.2.0 <1.3.0 +//! ``` + +#![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", + html_favicon_url = "https://www.rust-lang.org/favicon.ico")] +#![deny(missing_docs)] +#![cfg_attr(test, deny(warnings))] + +extern crate semver_parser; + +// We take the common approach of keeping our own module system private, and +// just re-exporting the interface that we want. + +pub use version::{Version, Identifier, SemVerError}; +pub use version::Identifier::{Numeric, AlphaNumeric}; +pub use version_req::{VersionReq, ReqParseError}; + +// SemVer-compliant versions. +mod version; + +// advanced version comparisons +mod version_req; diff --git a/third_party/rust/semver-0.6.0/src/version.rs b/third_party/rust/semver-0.6.0/src/version.rs new file mode 100644 index 000000000000..004971ffc466 --- /dev/null +++ b/third_party/rust/semver-0.6.0/src/version.rs @@ -0,0 +1,650 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! The `version` module gives you tools to create and compare SemVer-compliant +//! versions. + +use std::cmp::{self, Ordering}; +use std::fmt; +use std::hash; +use std::error::Error; + +use std::result; +use std::str; + +use semver_parser; + +/// An identifier in the pre-release or build metadata. +/// +/// See sections 9 and 10 of the spec for more about pre-release identifers and +/// build metadata. +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +pub enum Identifier { + /// An identifier that's solely numbers. + Numeric(u64), + /// An identifier with letters and numbers. + AlphaNumeric(String), +} + +impl From for Identifier { + fn from(other: semver_parser::version::Identifier) -> Identifier { + match other { + semver_parser::version::Identifier::Numeric(n) => Identifier::Numeric(n), + semver_parser::version::Identifier::AlphaNumeric(s) => Identifier::AlphaNumeric(s), + } + } +} + +impl fmt::Display for Identifier { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Identifier::Numeric(ref n) => fmt::Display::fmt(n, f), + Identifier::AlphaNumeric(ref s) => fmt::Display::fmt(s, f), + } + } +} + +/// Represents a version number conforming to the semantic versioning scheme. +#[derive(Clone, Eq, Debug)] +pub struct Version { + /// The major version, to be incremented on incompatible changes. + pub major: u64, + /// The minor version, to be incremented when functionality is added in a + /// backwards-compatible manner. + pub minor: u64, + /// The patch version, to be incremented when backwards-compatible bug + /// fixes are made. + pub patch: u64, + /// The pre-release version identifier, if one exists. + pub pre: Vec, + /// The build metadata, ignored when determining version precedence. + pub build: Vec, +} + +impl From for Version { + fn from(other: semver_parser::version::Version) -> Version { + Version { + major: other.major, + minor: other.minor, + patch: other.patch, + pre: other.pre.into_iter().map(From::from).collect(), + build: other.build.into_iter().map(From::from).collect(), + } + } +} + +/// An error type for this crate +/// +/// Currently, just a generic error. Will make this nicer later. +#[derive(Clone,PartialEq,Debug,PartialOrd)] +pub enum SemVerError { + /// An error ocurred while parsing. + ParseError(String), +} + +impl fmt::Display for SemVerError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &SemVerError::ParseError(ref m) => write!(f, "{}", m), + } + } +} + +impl Error for SemVerError { + fn description(&self) -> &str { + match self { + &SemVerError::ParseError(ref m) => m, + } + } +} + +/// A Result type for errors +pub type Result = result::Result; + +impl Version { + /// Parse a string into a semver object. + pub fn parse(version: &str) -> Result { + let res = semver_parser::version::parse(version); + + match res { + // Convert plain String error into proper ParseError + Err(e) => Err(SemVerError::ParseError(e)), + Ok(v) => Ok(From::from(v)), + } + } + + /// Clears the build metadata + fn clear_metadata(&mut self) { + self.build = Vec::new(); + self.pre = Vec::new(); + } + + /// Increments the patch number for this Version (Must be mutable) + pub fn increment_patch(&mut self) { + self.patch += 1; + self.clear_metadata(); + } + + /// Increments the minor version number for this Version (Must be mutable) + /// + /// As instructed by section 7 of the spec, the patch number is reset to 0. + pub fn increment_minor(&mut self) { + self.minor += 1; + self.patch = 0; + self.clear_metadata(); + } + + /// Increments the major version number for this Version (Must be mutable) + /// + /// As instructed by section 8 of the spec, the minor and patch numbers are + /// reset to 0 + pub fn increment_major(&mut self) { + self.major += 1; + self.minor = 0; + self.patch = 0; + self.clear_metadata(); + } + + /// Checks to see if the current Version is in pre-release status + pub fn is_prerelease(&self) -> bool { + !self.pre.is_empty() + } +} + +impl str::FromStr for Version { + type Err = SemVerError; + + fn from_str(s: &str) -> Result { + Version::parse(s) + } +} + +impl fmt::Display for Version { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch)); + if !self.pre.is_empty() { + try!(write!(f, "-")); + for (i, x) in self.pre.iter().enumerate() { + if i != 0 { + try!(write!(f, ".")) + } + try!(write!(f, "{}", x)); + } + } + if !self.build.is_empty() { + try!(write!(f, "+")); + for (i, x) in self.build.iter().enumerate() { + if i != 0 { + try!(write!(f, ".")) + } + try!(write!(f, "{}", x)); + } + } + Ok(()) + } +} + +impl cmp::PartialEq for Version { + #[inline] + fn eq(&self, other: &Version) -> bool { + // We should ignore build metadata here, otherwise versions v1 and v2 + // can exist such that !(v1 < v2) && !(v1 > v2) && v1 != v2, which + // violate strict total ordering rules. + self.major == other.major && self.minor == other.minor && self.patch == other.patch && + self.pre == other.pre + } +} + +impl cmp::PartialOrd for Version { + fn partial_cmp(&self, other: &Version) -> Option { + Some(self.cmp(other)) + } +} + +impl cmp::Ord for Version { + fn cmp(&self, other: &Version) -> Ordering { + match self.major.cmp(&other.major) { + Ordering::Equal => {} + r => return r, + } + + match self.minor.cmp(&other.minor) { + Ordering::Equal => {} + r => return r, + } + + match self.patch.cmp(&other.patch) { + Ordering::Equal => {} + r => return r, + } + + // NB: semver spec says 0.0.0-pre < 0.0.0 + // but the version of ord defined for vec + // says that [] < [pre] so we alter it here + match (self.pre.len(), other.pre.len()) { + (0, 0) => Ordering::Equal, + (0, _) => Ordering::Greater, + (_, 0) => Ordering::Less, + (_, _) => self.pre.cmp(&other.pre), + } + } +} + +impl hash::Hash for Version { + fn hash(&self, into: &mut H) { + self.major.hash(into); + self.minor.hash(into); + self.patch.hash(into); + self.pre.hash(into); + } +} + +#[cfg(test)] +mod tests { + use std::result; + use super::Version; + use super::Identifier; + use super::SemVerError; + + #[test] + fn test_parse() { + fn parse_error(e: &str) -> result::Result { + return Err(SemVerError::ParseError(e.to_string())); + } + + assert_eq!(Version::parse(""), + parse_error("Error parsing major identifier")); + assert_eq!(Version::parse(" "), + parse_error("Error parsing major identifier")); + assert_eq!(Version::parse("1"), + parse_error("Expected dot")); + assert_eq!(Version::parse("1.2"), + parse_error("Expected dot")); + assert_eq!(Version::parse("1.2.3-"), + parse_error("Error parsing prerelease")); + assert_eq!(Version::parse("a.b.c"), + parse_error("Error parsing major identifier")); + assert_eq!(Version::parse("1.2.3 abc"), + parse_error("Extra junk after valid version: abc")); + + assert_eq!(Version::parse("1.2.3"), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: Vec::new(), + })); + assert_eq!(Version::parse(" 1.2.3 "), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: Vec::new(), + })); + assert_eq!(Version::parse("1.2.3-alpha1"), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: Vec::new(), + })); + assert_eq!(Version::parse(" 1.2.3-alpha1 "), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: Vec::new(), + })); + assert_eq!(Version::parse("1.2.3+build5"), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(Version::parse(" 1.2.3+build5 "), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(Version::parse("1.2.3-alpha1+build5"), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(Version::parse(" 1.2.3-alpha1+build5 "), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(Version::parse("1.2.3-1.alpha1.9+build5.7.3aedf "), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::Numeric(1), + Identifier::AlphaNumeric(String::from("alpha1")), + Identifier::Numeric(9), + ], + build: vec![Identifier::AlphaNumeric(String::from("build5")), + Identifier::Numeric(7), + Identifier::AlphaNumeric(String::from("3aedf")), + ], + })); + assert_eq!(Version::parse("0.4.0-beta.1+0851523"), + Ok(Version { + major: 0, + minor: 4, + patch: 0, + pre: vec![Identifier::AlphaNumeric(String::from("beta")), + Identifier::Numeric(1), + ], + build: vec![Identifier::AlphaNumeric(String::from("0851523"))], + })); + + } + + #[test] + fn test_increment_patch() { + let mut buggy_release = Version::parse("0.1.0").unwrap(); + buggy_release.increment_patch(); + assert_eq!(buggy_release, Version::parse("0.1.1").unwrap()); + } + + #[test] + fn test_increment_minor() { + let mut feature_release = Version::parse("1.4.6").unwrap(); + feature_release.increment_minor(); + assert_eq!(feature_release, Version::parse("1.5.0").unwrap()); + } + + #[test] + fn test_increment_major() { + let mut chrome_release = Version::parse("46.1.246773").unwrap(); + chrome_release.increment_major(); + assert_eq!(chrome_release, Version::parse("47.0.0").unwrap()); + } + + #[test] + fn test_increment_keep_prerelease() { + let mut release = Version::parse("1.0.0-alpha").unwrap(); + release.increment_patch(); + + assert_eq!(release, Version::parse("1.0.1").unwrap()); + + release.increment_minor(); + + assert_eq!(release, Version::parse("1.1.0").unwrap()); + + release.increment_major(); + + assert_eq!(release, Version::parse("2.0.0").unwrap()); + } + + + #[test] + fn test_increment_clear_metadata() { + let mut release = Version::parse("1.0.0+4442").unwrap(); + release.increment_patch(); + + assert_eq!(release, Version::parse("1.0.1").unwrap()); + release = Version::parse("1.0.1+hello").unwrap(); + + release.increment_minor(); + + assert_eq!(release, Version::parse("1.1.0").unwrap()); + release = Version::parse("1.1.3747+hello").unwrap(); + + release.increment_major(); + + assert_eq!(release, Version::parse("2.0.0").unwrap()); + } + + #[test] + fn test_eq() { + assert_eq!(Version::parse("1.2.3"), Version::parse("1.2.3")); + assert_eq!(Version::parse("1.2.3-alpha1"), + Version::parse("1.2.3-alpha1")); + assert_eq!(Version::parse("1.2.3+build.42"), + Version::parse("1.2.3+build.42")); + assert_eq!(Version::parse("1.2.3-alpha1+42"), + Version::parse("1.2.3-alpha1+42")); + assert_eq!(Version::parse("1.2.3+23"), Version::parse("1.2.3+42")); + } + + #[test] + fn test_ne() { + assert!(Version::parse("0.0.0") != Version::parse("0.0.1")); + assert!(Version::parse("0.0.0") != Version::parse("0.1.0")); + assert!(Version::parse("0.0.0") != Version::parse("1.0.0")); + assert!(Version::parse("1.2.3-alpha") != Version::parse("1.2.3-beta")); + } + + #[test] + fn test_show() { + assert_eq!(format!("{}", Version::parse("1.2.3").unwrap()), + "1.2.3".to_string()); + assert_eq!(format!("{}", Version::parse("1.2.3-alpha1").unwrap()), + "1.2.3-alpha1".to_string()); + assert_eq!(format!("{}", Version::parse("1.2.3+build.42").unwrap()), + "1.2.3+build.42".to_string()); + assert_eq!(format!("{}", Version::parse("1.2.3-alpha1+42").unwrap()), + "1.2.3-alpha1+42".to_string()); + } + + #[test] + fn test_to_string() { + assert_eq!(Version::parse("1.2.3").unwrap().to_string(), + "1.2.3".to_string()); + assert_eq!(Version::parse("1.2.3-alpha1").unwrap().to_string(), + "1.2.3-alpha1".to_string()); + assert_eq!(Version::parse("1.2.3+build.42").unwrap().to_string(), + "1.2.3+build.42".to_string()); + assert_eq!(Version::parse("1.2.3-alpha1+42").unwrap().to_string(), + "1.2.3-alpha1+42".to_string()); + } + + #[test] + fn test_lt() { + assert!(Version::parse("0.0.0") < Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.0.0") < Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.0") < Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3")); + assert!(Version::parse("1.2.3-alpha1") < Version::parse("1.2.3-alpha2")); + assert!(!(Version::parse("1.2.3-alpha2") < Version::parse("1.2.3-alpha2"))); + assert!(!(Version::parse("1.2.3+23") < Version::parse("1.2.3+42"))); + } + + #[test] + fn test_le() { + assert!(Version::parse("0.0.0") <= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.0.0") <= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.0") <= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.3-alpha1") <= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.3-alpha2") <= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.3+23") <= Version::parse("1.2.3+42")); + } + + #[test] + fn test_gt() { + assert!(Version::parse("1.2.3-alpha2") > Version::parse("0.0.0")); + assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.0.0")); + assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.0")); + assert!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha1")); + assert!(Version::parse("1.2.3") > Version::parse("1.2.3-alpha2")); + assert!(!(Version::parse("1.2.3-alpha2") > Version::parse("1.2.3-alpha2"))); + assert!(!(Version::parse("1.2.3+23") > Version::parse("1.2.3+42"))); + } + + #[test] + fn test_ge() { + assert!(Version::parse("1.2.3-alpha2") >= Version::parse("0.0.0")); + assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.0.0")); + assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.0")); + assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha1")); + assert!(Version::parse("1.2.3-alpha2") >= Version::parse("1.2.3-alpha2")); + assert!(Version::parse("1.2.3+23") >= Version::parse("1.2.3+42")); + } + + #[test] + fn test_prerelease_check() { + assert!(Version::parse("1.0.0").unwrap().is_prerelease() == false); + assert!(Version::parse("0.0.1").unwrap().is_prerelease() == false); + assert!(Version::parse("4.1.4-alpha").unwrap().is_prerelease()); + assert!(Version::parse("1.0.0-beta294296").unwrap().is_prerelease()); + } + + #[test] + fn test_spec_order() { + let vs = ["1.0.0-alpha", + "1.0.0-alpha.1", + "1.0.0-alpha.beta", + "1.0.0-beta", + "1.0.0-beta.2", + "1.0.0-beta.11", + "1.0.0-rc.1", + "1.0.0"]; + let mut i = 1; + while i < vs.len() { + let a = Version::parse(vs[i - 1]); + let b = Version::parse(vs[i]); + assert!(a < b, "nope {:?} < {:?}", a, b); + i += 1; + } + } + + #[test] + fn test_from_str() { + assert_eq!("1.2.3".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: Vec::new(), + })); + assert_eq!(" 1.2.3 ".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: Vec::new(), + })); + assert_eq!("1.2.3-alpha1".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: Vec::new(), + })); + assert_eq!(" 1.2.3-alpha1 ".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: Vec::new(), + })); + assert_eq!("1.2.3+build5".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(" 1.2.3+build5 ".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: Vec::new(), + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!("1.2.3-alpha1+build5".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!(" 1.2.3-alpha1+build5 ".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::AlphaNumeric(String::from("alpha1"))], + build: vec![Identifier::AlphaNumeric(String::from("build5"))], + })); + assert_eq!("1.2.3-1.alpha1.9+build5.7.3aedf ".parse(), + Ok(Version { + major: 1, + minor: 2, + patch: 3, + pre: vec![Identifier::Numeric(1), + Identifier::AlphaNumeric(String::from("alpha1")), + Identifier::Numeric(9), + ], + build: vec![Identifier::AlphaNumeric(String::from("build5")), + Identifier::Numeric(7), + Identifier::AlphaNumeric(String::from("3aedf")), + ], + })); + assert_eq!("0.4.0-beta.1+0851523".parse(), + Ok(Version { + major: 0, + minor: 4, + patch: 0, + pre: vec![Identifier::AlphaNumeric(String::from("beta")), + Identifier::Numeric(1), + ], + build: vec![Identifier::AlphaNumeric(String::from("0851523"))], + })); + + } + + #[test] + fn test_from_str_errors() { + fn parse_error(e: &str) -> result::Result { + return Err(SemVerError::ParseError(e.to_string())); + } + + assert_eq!("".parse(), parse_error("Error parsing major identifier")); + assert_eq!(" ".parse(), parse_error("Error parsing major identifier")); + assert_eq!("1".parse(), parse_error("Expected dot")); + assert_eq!("1.2".parse(), + parse_error("Expected dot")); + assert_eq!("1.2.3-".parse(), + parse_error("Error parsing prerelease")); + assert_eq!("a.b.c".parse(), + parse_error("Error parsing major identifier")); + assert_eq!("1.2.3 abc".parse(), + parse_error("Extra junk after valid version: abc")); + } +} diff --git a/third_party/rust/semver-0.6.0/src/version_req.rs b/third_party/rust/semver-0.6.0/src/version_req.rs new file mode 100644 index 000000000000..343793352e48 --- /dev/null +++ b/third_party/rust/semver-0.6.0/src/version_req.rs @@ -0,0 +1,824 @@ +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::error::Error; +use std::fmt; +use std::str; + +use Version; +use version::Identifier; +use semver_parser; + +use self::Op::{Ex, Gt, GtEq, Lt, LtEq, Tilde, Compatible, Wildcard}; +use self::WildcardVersion::{Major, Minor, Patch}; +use self::ReqParseError::*; + +/// A `VersionReq` is a struct containing a list of predicates that can apply to ranges of version +/// numbers. Matching operations can then be done with the `VersionReq` against a particular +/// version to see if it satisfies some or all of the constraints. +#[derive(PartialEq,Clone,Debug)] +pub struct VersionReq { + predicates: Vec, +} + +impl From for VersionReq { + fn from(other: semver_parser::range::VersionReq) -> VersionReq { + VersionReq { predicates: other.predicates.into_iter().map(From::from).collect() } + } +} + +#[derive(Clone, PartialEq, Debug)] +enum WildcardVersion { + Major, + Minor, + Patch, +} + +#[derive(PartialEq,Clone,Debug)] +enum Op { + Ex, // Exact + Gt, // Greater than + GtEq, // Greater than or equal to + Lt, // Less than + LtEq, // Less than or equal to + Tilde, // e.g. ~1.0.0 + Compatible, // compatible by definition of semver, indicated by ^ + Wildcard(WildcardVersion), // x.y.*, x.*, * +} + +impl From for Op { + fn from(other: semver_parser::range::Op) -> Op { + use semver_parser::range; + match other { + range::Op::Ex => Op::Ex, + range::Op::Gt => Op::Gt, + range::Op::GtEq => Op::GtEq, + range::Op::Lt => Op::Lt, + range::Op::LtEq => Op::LtEq, + range::Op::Tilde => Op::Tilde, + range::Op::Compatible => Op::Compatible, + range::Op::Wildcard(version) => { + match version { + range::WildcardVersion::Major => Op::Wildcard(WildcardVersion::Major), + range::WildcardVersion::Minor => Op::Wildcard(WildcardVersion::Minor), + range::WildcardVersion::Patch => Op::Wildcard(WildcardVersion::Patch), + } + } + } + } +} + +#[derive(PartialEq,Clone,Debug)] +struct Predicate { + op: Op, + major: u64, + minor: Option, + patch: Option, + pre: Vec, +} + +impl From for Predicate { + fn from(other: semver_parser::range::Predicate) -> Predicate { + Predicate { + op: From::from(other.op), + major: other.major, + minor: other.minor, + patch: other.patch, + pre: other.pre.into_iter().map(From::from).collect(), + } + } +} + +/// A `ReqParseError` is returned from methods which parse a string into a `VersionReq`. Each +/// enumeration is one of the possible errors that can occur. +#[derive(Clone, Debug, PartialEq)] +pub enum ReqParseError { + /// The given version requirement is invalid. + InvalidVersionRequirement, + /// You have already provided an operation, such as `=`, `~`, or `^`. Only use one. + OpAlreadySet, + /// The sigil you have written is not correct. + InvalidSigil, + /// All components of a version must be numeric. + VersionComponentsMustBeNumeric, + /// There was an error parsing an identifier. + InvalidIdentifier, + /// At least a major version is required. + MajorVersionRequired, + /// An unimplemented version requirement. + UnimplementedVersionRequirement, + /// This form of requirement is deprecated. + DeprecatedVersionRequirement(VersionReq), +} + +impl fmt::Display for ReqParseError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + self.description().fmt(f) + } +} + +impl Error for ReqParseError { + fn description(&self) -> &str { + match self { + &InvalidVersionRequirement => "the given version requirement is invalid", + &OpAlreadySet => { + "you have already provided an operation, such as =, ~, or ^; only use one" + }, + &InvalidSigil => "the sigil you have written is not correct", + &VersionComponentsMustBeNumeric => "version components must be numeric", + &InvalidIdentifier => "invalid identifier", + &MajorVersionRequired => "at least a major version number is required", + &UnimplementedVersionRequirement => { + "the given version requirement is not implemented, yet" + }, + &DeprecatedVersionRequirement(_) => "This requirement is deprecated", + } + } +} + +impl From for ReqParseError { + fn from(other: String) -> ReqParseError { + match &*other { + "Null is not a valid VersionReq" => ReqParseError::InvalidVersionRequirement, + "VersionReq did not parse properly." => ReqParseError::OpAlreadySet, + _ => ReqParseError::InvalidVersionRequirement, + } + } +} + +impl VersionReq { + /// `any()` is a factory method which creates a `VersionReq` with no constraints. In other + /// words, any version will match against it. + /// + /// # Examples + /// + /// ``` + /// use semver::VersionReq; + /// + /// let anything = VersionReq::any(); + /// ``` + pub fn any() -> VersionReq { + VersionReq { predicates: vec![] } + } + + /// `parse()` is the main constructor of a `VersionReq`. It turns a string like `"^1.2.3"` + /// and turns it into a `VersionReq` that matches that particular constraint. + /// + /// A `Result` is returned which contains a `ReqParseError` if there was a problem parsing the + /// `VersionReq`. + /// + /// # Examples + /// + /// ``` + /// use semver::VersionReq; + /// + /// let version = VersionReq::parse("=1.2.3"); + /// let version = VersionReq::parse(">1.2.3"); + /// let version = VersionReq::parse("<1.2.3"); + /// let version = VersionReq::parse("~1.2.3"); + /// let version = VersionReq::parse("^1.2.3"); + /// let version = VersionReq::parse("<=1.2.3"); + /// let version = VersionReq::parse(">=1.2.3"); + /// ``` + /// + /// This example demonstrates error handling, and will panic. + /// + /// ```should-panic + /// use semver::VersionReq; + /// + /// let version = match VersionReq::parse("not a version") { + /// Ok(version) => version, + /// Err(e) => panic!("There was a problem parsing: {}", e), + /// } + /// ``` + pub fn parse(input: &str) -> Result { + let res = semver_parser::range::parse(input); + + if let Ok(v) = res { + return Ok(From::from(v)); + } + + return match VersionReq::parse_deprecated(input) { + Some(v) => { + Err(ReqParseError::DeprecatedVersionRequirement(v)) + } + None => Err(From::from(res.err().unwrap())), + } + } + + fn parse_deprecated(version: &str) -> Option { + return match version { + ".*" => Some(VersionReq::any()), + "0.1.0." => Some(VersionReq::parse("0.1.0").unwrap()), + "0.3.1.3" => Some(VersionReq::parse("0.3.13").unwrap()), + "0.2*" => Some(VersionReq::parse("0.2.*").unwrap()), + "*.0" => Some(VersionReq::any()), + _ => None, + } + } + + /// `exact()` is a factory method which creates a `VersionReq` with one exact constraint. + /// + /// # Examples + /// + /// ``` + /// use semver::VersionReq; + /// use semver::Version; + /// + /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] }; + /// let exact = VersionReq::exact(&version); + /// ``` + pub fn exact(version: &Version) -> VersionReq { + VersionReq { predicates: vec![Predicate::exact(version)] } + } + + /// `matches()` matches a given `Version` against this `VersionReq`. + /// + /// # Examples + /// + /// ``` + /// use semver::VersionReq; + /// use semver::Version; + /// + /// let version = Version { major: 1, minor: 1, patch: 1, pre: vec![], build: vec![] }; + /// let exact = VersionReq::exact(&version); + /// + /// assert!(exact.matches(&version)); + /// ``` + pub fn matches(&self, version: &Version) -> bool { + // no predicates means anything matches + if self.predicates.is_empty() { + return true; + } + + self.predicates.iter().all(|p| p.matches(version)) && + self.predicates.iter().any(|p| p.pre_tag_is_compatible(version)) + } +} + +impl str::FromStr for VersionReq { + type Err = ReqParseError; + + fn from_str(s: &str) -> Result { + VersionReq::parse(s) + } +} + +impl Predicate { + fn exact(version: &Version) -> Predicate { + Predicate { + op: Ex, + major: version.major, + minor: Some(version.minor), + patch: Some(version.patch), + pre: version.pre.clone(), + } + } + + /// `matches()` takes a `Version` and determines if it matches this particular `Predicate`. + pub fn matches(&self, ver: &Version) -> bool { + match self.op { + Ex => self.is_exact(ver), + Gt => self.is_greater(ver), + GtEq => self.is_exact(ver) || self.is_greater(ver), + Lt => !self.is_exact(ver) && !self.is_greater(ver), + LtEq => !self.is_greater(ver), + Tilde => self.matches_tilde(ver), + Compatible => self.is_compatible(ver), + Wildcard(_) => self.matches_wildcard(ver), + } + } + + fn is_exact(&self, ver: &Version) -> bool { + if self.major != ver.major { + return false; + } + + match self.minor { + Some(minor) => { + if minor != ver.minor { + return false; + } + } + None => return true, + } + + match self.patch { + Some(patch) => { + if patch != ver.patch { + return false; + } + } + None => return true, + } + + if self.pre != ver.pre { + return false; + } + + true + } + + // https://docs.npmjs.com/misc/semver#prerelease-tags + fn pre_tag_is_compatible(&self, ver: &Version) -> bool { + // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it will + // only be + // allowed to satisfy comparator sets if at least one comparator with the same + // [major, + // minor, patch] tuple also has a prerelease tag. + !ver.is_prerelease() || + (self.major == ver.major && self.minor == Some(ver.minor) && + self.patch == Some(ver.patch) && !self.pre.is_empty()) + } + + fn is_greater(&self, ver: &Version) -> bool { + if self.major != ver.major { + return ver.major > self.major; + } + + match self.minor { + Some(minor) => { + if minor != ver.minor { + return ver.minor > minor; + } + } + None => return false, + } + + match self.patch { + Some(patch) => { + if patch != ver.patch { + return ver.patch > patch; + } + } + None => return false, + } + + if !self.pre.is_empty() { + return ver.pre.is_empty() || ver.pre > self.pre; + } + + false + } + + // see https://www.npmjs.org/doc/misc/semver.html for behavior + fn matches_tilde(&self, ver: &Version) -> bool { + let minor = match self.minor { + Some(n) => n, + None => return self.major == ver.major, + }; + + match self.patch { + Some(patch) => { + self.major == ver.major && minor == ver.minor && + (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver))) + } + None => self.major == ver.major && minor == ver.minor, + } + } + + // see https://www.npmjs.org/doc/misc/semver.html for behavior + fn is_compatible(&self, ver: &Version) -> bool { + if self.major != ver.major { + return false; + } + + let minor = match self.minor { + Some(n) => n, + None => return self.major == ver.major, + }; + + match self.patch { + Some(patch) => { + if self.major == 0 { + if minor == 0 { + ver.minor == minor && ver.patch == patch && self.pre_is_compatible(ver) + } else { + ver.minor == minor && + (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver))) + } + } else { + ver.minor > minor || + (ver.minor == minor && + (ver.patch > patch || (ver.patch == patch && self.pre_is_compatible(ver)))) + } + } + None => { + if self.major == 0 { + ver.minor == minor + } else { + ver.minor >= minor + } + } + } + } + + fn pre_is_compatible(&self, ver: &Version) -> bool { + ver.pre.is_empty() || ver.pre >= self.pre + } + + // see https://www.npmjs.org/doc/misc/semver.html for behavior + fn matches_wildcard(&self, ver: &Version) -> bool { + match self.op { + Wildcard(Major) => true, + Wildcard(Minor) => self.major == ver.major, + Wildcard(Patch) => { + match self.minor { + Some(minor) => self.major == ver.major && minor == ver.minor, + None => { + // minor and patch version astericks mean match on major + self.major == ver.major + } + } + } + _ => false, // unreachable + } + } +} + +impl fmt::Display for VersionReq { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + if self.predicates.is_empty() { + try!(write!(fmt, "*")); + } else { + for (i, ref pred) in self.predicates.iter().enumerate() { + if i == 0 { + try!(write!(fmt, "{}", pred)); + } else { + try!(write!(fmt, ", {}", pred)); + } + } + } + + Ok(()) + } +} + +impl fmt::Display for Predicate { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match self.op { + Wildcard(Major) => try!(write!(fmt, "*")), + Wildcard(Minor) => try!(write!(fmt, "{}.*", self.major)), + Wildcard(Patch) => { + if let Some(minor) = self.minor { + try!(write!(fmt, "{}.{}.*", self.major, minor)) + } else { + try!(write!(fmt, "{}.*.*", self.major)) + } + } + _ => { + try!(write!(fmt, "{}{}", self.op, self.major)); + + match self.minor { + Some(v) => try!(write!(fmt, ".{}", v)), + None => (), + } + + match self.patch { + Some(v) => try!(write!(fmt, ".{}", v)), + None => (), + } + + if !self.pre.is_empty() { + try!(write!(fmt, "-")); + for (i, x) in self.pre.iter().enumerate() { + if i != 0 { + try!(write!(fmt, ".")) + } + try!(write!(fmt, "{}", x)); + } + } + } + } + + Ok(()) + } +} + +impl fmt::Display for Op { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + match *self { + Ex => try!(write!(fmt, "= ")), + Gt => try!(write!(fmt, "> ")), + GtEq => try!(write!(fmt, ">= ")), + Lt => try!(write!(fmt, "< ")), + LtEq => try!(write!(fmt, "<= ")), + Tilde => try!(write!(fmt, "~")), + Compatible => try!(write!(fmt, "^")), + // gets handled specially in Predicate::fmt + Wildcard(_) => try!(write!(fmt, "")), + } + Ok(()) + } +} + +#[cfg(test)] +mod test { + use super::{VersionReq, Op}; + use super::super::version::Version; + + fn req(s: &str) -> VersionReq { + VersionReq::parse(s).unwrap() + } + + fn version(s: &str) -> Version { + match Version::parse(s) { + Ok(v) => v, + Err(e) => panic!("`{}` is not a valid version. Reason: {:?}", s, e), + } + } + + fn assert_match(req: &VersionReq, vers: &[&str]) { + for ver in vers.iter() { + assert!(req.matches(&version(*ver)), "did not match {}", ver); + } + } + + fn assert_not_match(req: &VersionReq, vers: &[&str]) { + for ver in vers.iter() { + assert!(!req.matches(&version(*ver)), "matched {}", ver); + } + } + + #[test] + fn test_parsing_default() { + let r = req("1.0.0"); + + assert_eq!(r.to_string(), "^1.0.0".to_string()); + + assert_match(&r, &["1.0.0", "1.0.1"]); + assert_not_match(&r, &["0.9.9", "0.10.0", "0.1.0"]); + } + + #[test] + fn test_parsing_exact() { + let r = req("=1.0.0"); + + assert!(r.to_string() == "= 1.0.0".to_string()); + assert_eq!(r.to_string(), "= 1.0.0".to_string()); + + assert_match(&r, &["1.0.0"]); + assert_not_match(&r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]); + + let r = req("=0.9.0"); + + assert_eq!(r.to_string(), "= 0.9.0".to_string()); + + assert_match(&r, &["0.9.0"]); + assert_not_match(&r, &["0.9.1", "1.9.0", "0.0.9"]); + + let r = req("=0.1.0-beta2.a"); + + assert_eq!(r.to_string(), "= 0.1.0-beta2.a".to_string()); + + assert_match(&r, &["0.1.0-beta2.a"]); + assert_not_match(&r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]); + } + + #[test] + fn test_parse_metadata_see_issue_88_see_issue_88() { + for op in &[Op::Compatible, Op::Ex, Op::Gt, Op::GtEq, Op::Lt, Op::LtEq, Op::Tilde] { + req(&format!("{} 1.2.3+meta", op)); + } + } + + #[test] + pub fn test_parsing_greater_than() { + let r = req(">= 1.0.0"); + + assert_eq!(r.to_string(), ">= 1.0.0".to_string()); + + assert_match(&r, &["1.0.0", "2.0.0"]); + assert_not_match(&r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]); + + let r = req(">= 2.1.0-alpha2"); + + assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]); + assert_not_match(&r, + &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"]); + } + + #[test] + pub fn test_parsing_less_than() { + let r = req("< 1.0.0"); + + assert_eq!(r.to_string(), "< 1.0.0".to_string()); + + assert_match(&r, &["0.1.0", "0.0.1"]); + assert_not_match(&r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]); + + let r = req("<= 2.1.0-alpha2"); + + assert_match(&r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]); + assert_not_match(&r, + &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"]); + } + + #[test] + pub fn test_multiple() { + let r = req("> 0.0.9, <= 2.5.3"); + assert_eq!(r.to_string(), "> 0.0.9, <= 2.5.3".to_string()); + assert_match(&r, &["0.0.10", "1.0.0", "2.5.3"]); + assert_not_match(&r, &["0.0.8", "2.5.4"]); + + let r = req("0.3.0, 0.4.0"); + assert_eq!(r.to_string(), "^0.3.0, ^0.4.0".to_string()); + assert_not_match(&r, &["0.0.8", "0.3.0", "0.4.0"]); + + let r = req("<= 0.2.0, >= 0.5.0"); + assert_eq!(r.to_string(), "<= 0.2.0, >= 0.5.0".to_string()); + assert_not_match(&r, &["0.0.8", "0.3.0", "0.5.1"]); + + let r = req("0.1.0, 0.1.4, 0.1.6"); + assert_eq!(r.to_string(), "^0.1.0, ^0.1.4, ^0.1.6".to_string()); + assert_match(&r, &["0.1.6", "0.1.9"]); + assert_not_match(&r, &["0.1.0", "0.1.4", "0.2.0"]); + + assert!(VersionReq::parse("> 0.1.0,").is_err()); + assert!(VersionReq::parse("> 0.3.0, ,").is_err()); + + let r = req(">=0.5.1-alpha3, <0.6"); + assert_eq!(r.to_string(), ">= 0.5.1-alpha3, < 0.6".to_string()); + assert_match(&r, + &["0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5"]); + assert_not_match(&r, + &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"]); + assert_not_match(&r, &["0.6.0", "0.6.0-pre"]); + } + + #[test] + pub fn test_parsing_tilde() { + let r = req("~1"); + assert_match(&r, &["1.0.0", "1.0.1", "1.1.1"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "0.0.9"]); + + let r = req("~1.2"); + assert_match(&r, &["1.2.0", "1.2.1"]); + assert_not_match(&r, &["1.1.1", "1.3.0", "0.0.9"]); + + let r = req("~1.2.2"); + assert_match(&r, &["1.2.2", "1.2.4"]); + assert_not_match(&r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]); + + let r = req("~1.2.3-beta.2"); + assert_match(&r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]); + assert_not_match(&r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]); + } + + #[test] + pub fn test_parsing_compatible() { + let r = req("^1"); + assert_match(&r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "0.1.4"]); + assert_not_match(&r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]); + + let r = req("^1.1"); + assert_match(&r, &["1.1.2", "1.1.0", "1.2.1"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]); + + let r = req("^1.1.2"); + assert_match(&r, &["1.1.2", "1.1.4", "1.2.1"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); + assert_not_match(&r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]); + + let r = req("^0.1.2"); + assert_match(&r, &["0.1.2", "0.1.4"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]); + assert_not_match(&r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]); + + let r = req("^0.5.1-alpha3"); + assert_match(&r, + &["0.5.1-alpha3", "0.5.1-alpha4", "0.5.1-beta", "0.5.1", "0.5.5"]); + assert_not_match(&r, + &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre", "0.6.0"]); + + let r = req("^0.0.2"); + assert_match(&r, &["0.0.2"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]); + + let r = req("^0.0"); + assert_match(&r, &["0.0.2", "0.0.0"]); + assert_not_match(&r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]); + + let r = req("^0"); + assert_match(&r, &["0.9.1", "0.0.2", "0.0.0"]); + assert_not_match(&r, &["2.9.0", "1.1.1"]); + + let r = req("^1.4.2-beta.5"); + assert_match(&r, + &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"]); + assert_not_match(&r, + &["0.9.9", "2.0.0", "1.4.2-alpha", "1.4.2-beta.4", "1.4.3-beta.5"]); + } + + #[test] + pub fn test_parsing_wildcard() { + let r = req(""); + assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); + assert_not_match(&r, &[]); + let r = req("*"); + assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); + assert_not_match(&r, &[]); + let r = req("x"); + assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); + assert_not_match(&r, &[]); + let r = req("X"); + assert_match(&r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]); + assert_not_match(&r, &[]); + + let r = req("1.*"); + assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); + assert_not_match(&r, &["0.0.9"]); + let r = req("1.x"); + assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); + assert_not_match(&r, &["0.0.9"]); + let r = req("1.X"); + assert_match(&r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]); + assert_not_match(&r, &["0.0.9"]); + + let r = req("1.2.*"); + assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); + assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); + let r = req("1.2.x"); + assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); + assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); + let r = req("1.2.X"); + assert_match(&r, &["1.2.0", "1.2.2", "1.2.4"]); + assert_not_match(&r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3"]); + } + + #[test] + pub fn test_any() { + let r = VersionReq::any(); + assert_match(&r, &["0.0.1", "0.1.0", "1.0.0"]); + } + + #[test] + pub fn test_pre() { + let r = req("=2.1.1-really.0"); + assert_match(&r, &["2.1.1-really.0"]); + } + + // #[test] + // pub fn test_parse_errors() { + // assert_eq!(Err(InvalidVersionRequirement), VersionReq::parse("\0")); + // assert_eq!(Err(OpAlreadySet), VersionReq::parse(">= >= 0.0.2")); + // assert_eq!(Err(InvalidSigil), VersionReq::parse(">== 0.0.2")); + // assert_eq!(Err(VersionComponentsMustBeNumeric), + // VersionReq::parse("a.0.0")); + // assert_eq!(Err(InvalidIdentifier), VersionReq::parse("1.0.0-")); + // assert_eq!(Err(MajorVersionRequired), VersionReq::parse(">=")); + // } + + #[test] + pub fn test_from_str() { + assert_eq!("1.0.0".parse::().unwrap().to_string(), + "^1.0.0".to_string()); + assert_eq!("=1.0.0".parse::().unwrap().to_string(), + "= 1.0.0".to_string()); + assert_eq!("~1".parse::().unwrap().to_string(), + "~1".to_string()); + assert_eq!("~1.2".parse::().unwrap().to_string(), + "~1.2".to_string()); + assert_eq!("^1".parse::().unwrap().to_string(), + "^1".to_string()); + assert_eq!("^1.1".parse::().unwrap().to_string(), + "^1.1".to_string()); + assert_eq!("*".parse::().unwrap().to_string(), + "*".to_string()); + assert_eq!("1.*".parse::().unwrap().to_string(), + "1.*".to_string()); + assert_eq!("< 1.0.0".parse::().unwrap().to_string(), + "< 1.0.0".to_string()); + } + + // #[test] + // pub fn test_from_str_errors() { + // assert_eq!(Err(InvalidVersionRequirement), "\0".parse::()); + // assert_eq!(Err(OpAlreadySet), ">= >= 0.0.2".parse::()); + // assert_eq!(Err(InvalidSigil), ">== 0.0.2".parse::()); + // assert_eq!(Err(VersionComponentsMustBeNumeric), + // "a.0.0".parse::()); + // assert_eq!(Err(InvalidIdentifier), "1.0.0-".parse::()); + // assert_eq!(Err(MajorVersionRequired), ">=".parse::()); + // } + + #[test] + fn test_cargo3202() { + let v = "0.*.*".parse::().unwrap(); + assert_eq!("0.*.*", format!("{}", v.predicates[0])); + + let v = "0.0.*".parse::().unwrap(); + assert_eq!("0.0.*", format!("{}", v.predicates[0])); + + let r = req("0.*.*"); + assert_match(&r, &["0.5.0"]); + } +} diff --git a/third_party/rust/semver-0.6.0/tests/deprecation.rs b/third_party/rust/semver-0.6.0/tests/deprecation.rs new file mode 100644 index 000000000000..a5f533a3495b --- /dev/null +++ b/third_party/rust/semver-0.6.0/tests/deprecation.rs @@ -0,0 +1,22 @@ +extern crate semver; + +#[test] +fn test_regressions() { + use semver::VersionReq; + use semver::ReqParseError; + + let versions = vec![ + (".*", VersionReq::any()), + ("0.1.0.", VersionReq::parse("0.1.0").unwrap()), + ("0.3.1.3", VersionReq::parse("0.3.13").unwrap()), + ("0.2*", VersionReq::parse("0.2.*").unwrap()), + ("*.0", VersionReq::any()), + ]; + + for (version, requirement) in versions.into_iter() { + let parsed = VersionReq::parse(version); + let error = parsed.err().unwrap(); + + assert_eq!(ReqParseError::DeprecatedVersionRequirement(requirement), error); + } +} diff --git a/third_party/rust/semver-0.6.0/tests/regression.rs b/third_party/rust/semver-0.6.0/tests/regression.rs new file mode 100644 index 000000000000..ef568a7d3e2f --- /dev/null +++ b/third_party/rust/semver-0.6.0/tests/regression.rs @@ -0,0 +1,25 @@ +extern crate semver; +extern crate crates_index; +extern crate tempdir; + +// This test checks to see if every existing crate parses successfully. Important to not break the +// Rust universe! + +#[cfg(feature = "ci")] +#[test] +fn test_regressions() { + use tempdir::TempDir; + use crates_index::Index; + use semver::Version; + + let dir = TempDir::new("semver").unwrap(); + let index = Index::new(dir.into_path()); + index.clone().unwrap(); + + for krate in index.crates() { + for version in krate.versions() { + let v = version.version(); + assert!(Version::parse(v).is_ok(), "failed: {} ({})", version.name(), v); + } + } +} diff --git a/third_party/rust/semver/.cargo-checksum.json b/third_party/rust/semver/.cargo-checksum.json index 94297ea4d8f7..2f9af6eca870 100644 --- a/third_party/rust/semver/.cargo-checksum.json +++ b/third_party/rust/semver/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"d02f51526644dbe6c82add37202f246a6b95e185a5519ef0c3ca4d55a245f22c","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"bb80bfbd16bf7dc34de45891c21333c42590d5c5c10e8ba0ed59549fce5af1dd","src/lib.rs":"b33fcb9a79d46a581a4628f7c2bb00f7ba3451b1acfeeae0b38ff22532ed5b68","src/version.rs":"fc36d1e58c9a73f46fdec63283fd50ea78c89a0f816b8abaaa89438fb0c47c70","src/version_req.rs":"093f2ac08f2bc8fcf6a93ae0fc333eccc1ea04932e0c0b26835a952bb220eca1","tests/deprecation.rs":"b5ec79e19d61968d05b96b876c449e54d43cbd1762c6e63c23c3470f9db56292","tests/regression.rs":"180b699ad029b81e6135d42f0a8e6d782177bc29a41132f875ee6f8607a46b56"},"package":"7a3186ec9e65071a2095434b1f5bb24838d4e8e130f584c790f6033c79943537"} \ No newline at end of file +{"files":{"Cargo.toml":"a5b995796b5559de8975a6fee7166c9fda6c21b449ec90bef5f9baaeddd479a5","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"c780d8c3c802c5fe2c316127900385010c3e57f71c851eea9e8ed8495e2030dd","src/lib.rs":"cb1725a8bb90c1043f187c6ba504d0a9d07793e2f39f5205f926c58849311770","src/version.rs":"ffdf9c628597b889f149f3b2b1245b97c774eae1ce7030bd19235eabecaaede0","src/version_req.rs":"40d20720f5fdc0b3d9e398e64eb448a65987229bd322cab0fedf0cf1843f3bd8","tests/deprecation.rs":"b5ec79e19d61968d05b96b876c449e54d43cbd1762c6e63c23c3470f9db56292","tests/regression.rs":"180b699ad029b81e6135d42f0a8e6d782177bc29a41132f875ee6f8607a46b56","tests/serde.rs":"cdbbefc576ffcc814c30dad9598ab87a7fd9d14c5f42f1349e1db6afc72f8fed"},"package":"1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"} \ No newline at end of file diff --git a/third_party/rust/semver/Cargo.toml b/third_party/rust/semver/Cargo.toml index d21ea9db8f08..7749f76c3778 100644 --- a/third_party/rust/semver/Cargo.toml +++ b/third_party/rust/semver/Cargo.toml @@ -1,25 +1,45 @@ -[package] +# 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 believe there's an error in this file please file an +# issue against the rust-lang/cargo repository. If you're +# editing this file be aware that the upstream Cargo.toml +# will likely look very different (and much more reasonable) +[package] name = "semver" -version = "0.6.0" +version = "0.9.0" authors = ["Steve Klabnik ", "The Rust Project Developers"] -license = "MIT/Apache-2.0" -repository = "https://github.com/steveklabnik/semver" +description = "Semantic version parsing and comparison.\n" homepage = "https://docs.rs/crate/semver/" documentation = "https://docs.rs/crate/semver/" -description = """ -Semantic version parsing and comparison. -""" +readme = "README.md" +license = "MIT/Apache-2.0" +repository = "https://github.com/steveklabnik/semver" +[dependencies.semver-parser] +version = "0.7.0" -[dependencies] -semver-parser = "0.7.0" +[dependencies.serde] +version = "1.0" +optional = true +[dev-dependencies.crates-index] +version = "0.5.0" + +[dev-dependencies.serde_json] +version = "1.0" + +[dev-dependencies.serde_derive] +version = "1.0" + +[dev-dependencies.tempdir] +version = "0.3.4" [features] default = [] - -# are we testing on CI? -ci = [] - -[dev-dependencies] -crates-index = "0.5.0" -tempdir = "0.3.4" +ci = ["serde"] +[badges.travis-ci] +repository = "steveklabnik/semver" diff --git a/third_party/rust/semver/README.md b/third_party/rust/semver/README.md index a3fe02c3d961..2a5306d4ccd2 100644 --- a/third_party/rust/semver/README.md +++ b/third_party/rust/semver/README.md @@ -23,7 +23,7 @@ packages you need installed. To use `semver`, add this to your `[dependencies]` section: ```toml -semver = "0.6.0" +semver = "0.7.0" ``` And this to your crate root: diff --git a/third_party/rust/semver/src/lib.rs b/third_party/rust/semver/src/lib.rs index 1e74b01eaf1a..a38aae0e163d 100644 --- a/third_party/rust/semver/src/lib.rs +++ b/third_party/rust/semver/src/lib.rs @@ -164,6 +164,10 @@ extern crate semver_parser; +// Serialization and deserialization support for version numbers +#[cfg(feature = "serde")] +extern crate serde; + // We take the common approach of keeping our own module system private, and // just re-exporting the interface that we want. diff --git a/third_party/rust/semver/src/version.rs b/third_party/rust/semver/src/version.rs index 004971ffc466..38de133191ad 100644 --- a/third_party/rust/semver/src/version.rs +++ b/third_party/rust/semver/src/version.rs @@ -21,6 +21,11 @@ use std::str; use semver_parser; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, Serializer}; +#[cfg(feature = "serde")] +use serde::de::{self, Deserialize, Deserializer, Visitor}; + /// An identifier in the pre-release or build metadata. /// /// See sections 9 and 10 of the spec for more about pre-release identifers and @@ -52,6 +57,51 @@ impl fmt::Display for Identifier { } } +#[cfg(feature = "serde")] +impl Serialize for Identifier { + fn serialize(&self, serializer: S) -> result::Result + where S: Serializer + { + // Serialize Identifier as a number or string. + match *self { + Identifier::Numeric(n) => serializer.serialize_u64(n), + Identifier::AlphaNumeric(ref s) => serializer.serialize_str(s), + } + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Identifier { + fn deserialize(deserializer: D) -> result::Result + where D: Deserializer<'de> + { + struct IdentifierVisitor; + + // Deserialize Identifier from a number or string. + impl<'de> Visitor<'de> for IdentifierVisitor { + type Value = Identifier; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a SemVer pre-release or build identifier") + } + + fn visit_u64(self, numeric: u64) -> result::Result + where E: de::Error + { + Ok(Identifier::Numeric(numeric)) + } + + fn visit_str(self, alphanumeric: &str) -> result::Result + where E: de::Error + { + Ok(Identifier::AlphaNumeric(alphanumeric.to_owned())) + } + } + + deserializer.deserialize_any(IdentifierVisitor) + } +} + /// Represents a version number conforming to the semantic versioning scheme. #[derive(Clone, Eq, Debug)] pub struct Version { @@ -81,6 +131,42 @@ impl From for Version { } } +#[cfg(feature = "serde")] +impl Serialize for Version { + fn serialize(&self, serializer: S) -> result::Result + where S: Serializer + { + // Serialize Version as a string. + serializer.collect_str(self) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for Version { + fn deserialize(deserializer: D) -> result::Result + where D: Deserializer<'de> + { + struct VersionVisitor; + + // Deserialize Version from a string. + impl<'de> Visitor<'de> for VersionVisitor { + type Value = Version; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a SemVer version as a string") + } + + fn visit_str(self, v: &str) -> result::Result + where E: de::Error + { + Version::parse(v).map_err(de::Error::custom) + } + } + + deserializer.deserialize_str(VersionVisitor) + } +} + /// An error type for this crate /// /// Currently, just a generic error. Will make this nicer later. @@ -110,6 +196,18 @@ impl Error for SemVerError { pub type Result = result::Result; impl Version { + + /// Contructs the simple case without pre or build. + pub fn new(major: u64, minor: u64, patch: u64) -> Version { + Version { + major: major, + minor: minor, + patch: patch, + pre: Vec::new(), + build: Vec::new() + } + } + /// Parse a string into a semver object. pub fn parse(version: &str) -> Result { let res = semver_parser::version::parse(version); @@ -248,6 +346,13 @@ impl hash::Hash for Version { } } +impl From<(u64,u64,u64)> for Version { + fn from(tuple: (u64,u64,u64)) -> Version { + let (major, minor, patch) = tuple; + Version::new(major, minor, patch) + } +} + #[cfg(test)] mod tests { use std::result; @@ -284,6 +389,10 @@ mod tests { pre: Vec::new(), build: Vec::new(), })); + + assert_eq!(Version::parse("1.2.3"), + Ok(Version::new(1,2,3))); + assert_eq!(Version::parse(" 1.2.3 "), Ok(Version { major: 1, diff --git a/third_party/rust/semver/src/version_req.rs b/third_party/rust/semver/src/version_req.rs index 343793352e48..6e6a542b8a52 100644 --- a/third_party/rust/semver/src/version_req.rs +++ b/third_party/rust/semver/src/version_req.rs @@ -10,12 +10,18 @@ use std::error::Error; use std::fmt; +use std::result; use std::str; use Version; use version::Identifier; use semver_parser; +#[cfg(feature = "serde")] +use serde::ser::{Serialize, Serializer}; +#[cfg(feature = "serde")] +use serde::de::{self, Deserialize, Deserializer, Visitor}; + use self::Op::{Ex, Gt, GtEq, Lt, LtEq, Tilde, Compatible, Wildcard}; use self::WildcardVersion::{Major, Minor, Patch}; use self::ReqParseError::*; @@ -23,7 +29,7 @@ use self::ReqParseError::*; /// A `VersionReq` is a struct containing a list of predicates that can apply to ranges of version /// numbers. Matching operations can then be done with the `VersionReq` against a particular /// version to see if it satisfies some or all of the constraints. -#[derive(PartialEq,Clone,Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] pub struct VersionReq { predicates: Vec, } @@ -34,14 +40,50 @@ impl From for VersionReq { } } -#[derive(Clone, PartialEq, Debug)] +#[cfg(feature = "serde")] +impl Serialize for VersionReq { + fn serialize(&self, serializer: S) -> result::Result + where S: Serializer + { + // Serialize VersionReq as a string. + serializer.collect_str(self) + } +} + +#[cfg(feature = "serde")] +impl<'de> Deserialize<'de> for VersionReq { + fn deserialize(deserializer: D) -> result::Result + where D: Deserializer<'de> + { + struct VersionReqVisitor; + + /// Deserialize `VersionReq` from a string. + impl<'de> Visitor<'de> for VersionReqVisitor { + type Value = VersionReq; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("a SemVer version requirement as a string") + } + + fn visit_str(self, v: &str) -> result::Result + where E: de::Error + { + VersionReq::parse(v).map_err(de::Error::custom) + } + } + + deserializer.deserialize_str(VersionReqVisitor) + } +} + +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] enum WildcardVersion { Major, Minor, Patch, } -#[derive(PartialEq,Clone,Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] enum Op { Ex, // Exact Gt, // Greater than @@ -75,7 +117,7 @@ impl From for Op { } } -#[derive(PartialEq,Clone,Debug)] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] struct Predicate { op: Op, major: u64, @@ -168,7 +210,7 @@ impl VersionReq { VersionReq { predicates: vec![] } } - /// `parse()` is the main constructor of a `VersionReq`. It turns a string like `"^1.2.3"` + /// `parse()` is the main constructor of a `VersionReq`. It takes a string like `"^1.2.3"` /// and turns it into a `VersionReq` that matches that particular constraint. /// /// A `Result` is returned which contains a `ReqParseError` if there was a problem parsing the @@ -184,6 +226,7 @@ impl VersionReq { /// let version = VersionReq::parse("<1.2.3"); /// let version = VersionReq::parse("~1.2.3"); /// let version = VersionReq::parse("^1.2.3"); + /// let version = VersionReq::parse("1.2.3"); // synonym for ^1.2.3 /// let version = VersionReq::parse("<=1.2.3"); /// let version = VersionReq::parse(">=1.2.3"); /// ``` @@ -523,6 +566,7 @@ impl fmt::Display for Op { mod test { use super::{VersionReq, Op}; use super::super::version::Version; + use std::hash::{Hash, Hasher}; fn req(s: &str) -> VersionReq { VersionReq::parse(s).unwrap() @@ -547,6 +591,14 @@ mod test { } } + fn calculate_hash(t: T) -> u64 { + use std::collections::hash_map::DefaultHasher; + + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() + } + #[test] fn test_parsing_default() { let r = req("1.0.0"); @@ -821,4 +873,23 @@ mod test { let r = req("0.*.*"); assert_match(&r, &["0.5.0"]); } + + #[test] + fn test_eq_hash() { + assert!(req("^1") == req("^1")); + assert!(calculate_hash(req("^1")) == calculate_hash(req("^1"))); + assert!(req("^1") != req("^2")); + } + + #[test] + fn test_ordering() { + assert!(req("=1") < req("*")); + assert!(req(">1") < req("*")); + assert!(req(">=1") < req("*")); + assert!(req("<1") < req("*")); + assert!(req("<=1") < req("*")); + assert!(req("~1") < req("*")); + assert!(req("^1") < req("*")); + assert!(req("*") == req("*")); + } } diff --git a/third_party/rust/semver/tests/serde.rs b/third_party/rust/semver/tests/serde.rs new file mode 100644 index 000000000000..bcb92643cb6f --- /dev/null +++ b/third_party/rust/semver/tests/serde.rs @@ -0,0 +1,90 @@ +#![cfg(feature = "serde")] + +#[macro_use] +extern crate serde_derive; + +extern crate semver; +extern crate serde_json; + +use semver::{Identifier, Version, VersionReq}; + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +struct Identified { + name: String, + identifier: Identifier, +} + +#[derive(Serialize, Deserialize, PartialEq, Debug)] +struct Versioned { + name: String, + vers: Version, +} + +#[test] +fn serialize_identifier() { + let id = Identified { + name: "serde".to_owned(), + identifier: Identifier::Numeric(100), + }; + let j = serde_json::to_string(&id).unwrap(); + assert_eq!(j, r#"{"name":"serde","identifier":100}"#); + + let id = Identified { + name: "serde".to_owned(), + identifier: Identifier::AlphaNumeric("b100".to_owned()), + }; + let j = serde_json::to_string(&id).unwrap(); + assert_eq!(j, r#"{"name":"serde","identifier":"b100"}"#); +} + +#[test] +fn deserialize_identifier() { + let j = r#"{"name":"serde","identifier":100}"#; + let id = serde_json::from_str::(j).unwrap(); + let expected = Identified { + name: "serde".to_owned(), + identifier: Identifier::Numeric(100), + }; + assert_eq!(id, expected); + + let j = r#"{"name":"serde","identifier":"b100"}"#; + let id = serde_json::from_str::(j).unwrap(); + let expected = Identified { + name: "serde".to_owned(), + identifier: Identifier::AlphaNumeric("b100".to_owned()), + }; + assert_eq!(id, expected); +} + +#[test] +fn serialize_version() { + let v = Versioned { + name: "serde".to_owned(), + vers: Version::parse("1.0.0").unwrap(), + }; + let j = serde_json::to_string(&v).unwrap(); + assert_eq!(j, r#"{"name":"serde","vers":"1.0.0"}"#); +} + +#[test] +fn deserialize_version() { + let j = r#"{"name":"serde","vers":"1.0.0"}"#; + let v = serde_json::from_str::(j).unwrap(); + let expected = Versioned { + name: "serde".to_owned(), + vers: Version::parse("1.0.0").unwrap(), + }; + assert_eq!(v, expected); +} + +#[test] +fn serialize_versionreq() { + let v = VersionReq::exact(&Version::parse("1.0.0").unwrap()); + + assert_eq!(serde_json::to_string(&v).unwrap(), r#""= 1.0.0""#); +} + +#[test] +fn deserialize_versionreq() { + assert_eq!("1.0.0".parse::().unwrap(), serde_json::from_str(r#""1.0.0""#).unwrap()); +} diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml index fd4aa845cbae..8b28fef58d00 100644 --- a/toolkit/library/rust/shared/Cargo.toml +++ b/toolkit/library/rust/shared/Cargo.toml @@ -33,9 +33,7 @@ jsrust_shared = { path = "../../../../js/src/rust/shared", optional = true } arrayvec = "0.4" [build-dependencies] -# Use exactly version 0.2.1, which uses semver 0.6, which other crates -# require (0.2.2 requires 0.9) -rustc_version = "=0.2.1" +rustc_version = "0.2" [features] default = []