2022-08-29 19:01:18 +00:00
# HG changeset patch
# User Mike Hommey <mh+mozilla@glandium.org>
# Date 1654596092 0
# Node ID f52e2ad948e88e2c4ce83599d379aa4a1e57334e
# Parent 969171da8cc09d4eb7c070b0ecf33bc5cc504537
Bug 1772048 - Update rustc_version and semver crates. r=emilio,webdriver-reviewers,kinetik,whimboo
semver 1.0 doesn't and won't support Clone on semver::Error[1], so we
convert the mozversion error type to store the string version of the
error, which is an incompatible change requiring a version bump on the
crate.
1. https://github.com/dtolnay/semver/pull/280
Differential Revision: https://phabricator.services.mozilla.com/D147825
diff --git a/.cargo/config.in b/.cargo/config.in
--- a/.cargo/config.in
+++ b/.cargo/config.in
@@ -25,17 +25,17 @@ rev = "3bfc47d9a571d0842676043ba60716318
[source."https://github.com/mozilla/midir.git"]
git = "https://github.com/mozilla/midir.git"
replace-with = "vendored-sources"
rev = "4c11f0ffb5d6a10de4aff40a7b81218b33b94e6f"
[source."https://github.com/mozilla/cubeb-pulse-rs"]
git = "https://github.com/mozilla/cubeb-pulse-rs"
replace-with = "vendored-sources"
-rev = "df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
+rev = "1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
[source."https://github.com/mozilla/cubeb-coreaudio-rs"]
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
replace-with = "vendored-sources"
rev = "44eca95823bb57e964cf7b6d9791ed2ccb4b2108"
[source."https://github.com/mozilla/audioipc"]
git = "https://github.com/mozilla/audioipc"
diff --git a/Cargo.lock b/Cargo.lock
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1157,17 +1157,17 @@ dependencies = [
"mach",
"ringbuf",
"triple_buffer",
]
[[package]]
name = "cubeb-pulse"
version = "0.4.0"
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
dependencies = [
"cubeb-backend",
"pulse",
"pulse-ffi",
"ringbuf",
"semver",
]
@@ -3399,17 +3399,17 @@ dependencies = [
"nsstring",
"url",
"uuid",
"xpcom",
]
[[package]]
name = "mozversion"
-version = "0.4.3"
+version = "0.5.0-alpha"
dependencies = [
"regex",
"rust-ini",
"semver",
]
[[package]]
name = "mozwer_s"
@@ -4122,26 +4122,26 @@ dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "pulse"
version = "0.3.0"
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
dependencies = [
"bitflags",
"pulse-ffi",
]
[[package]]
name = "pulse-ffi"
version = "0.1.0"
-source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=df4dc0288b07b865440f4c7e41ca49ca9ccffc63#df4dc0288b07b865440f4c7e41ca49ca9ccffc63"
+source = "git+https://github.com/mozilla/cubeb-pulse-rs?rev=1f1fe1e08e01a9a534ec7f079702a583a0899ce7#1f1fe1e08e01a9a534ec7f079702a583a0899ce7"
dependencies = [
"libc",
]
[[package]]
name = "qcms"
version = "0.2.0"
dependencies = [
@@ -4456,19 +4456,19 @@ checksum = "7ef03e0a2b150c7a90d01faf6254
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "rustc_version"
-version = "0.2.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
]
[[package]]
name = "ryu"
version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4544,28 +4544,19 @@ dependencies = [
[[package]]
name = "self_cell"
version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af"
[[package]]
name = "semver"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
-dependencies = [
- "semver-parser",
-]
-
-[[package]]
-name = "semver-parser"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
[[package]]
name = "serde"
version = "1.0.136"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789"
dependencies = [
"serde_derive",
diff --git a/gfx/qcms/Cargo.toml b/gfx/qcms/Cargo.toml
--- a/gfx/qcms/Cargo.toml
+++ b/gfx/qcms/Cargo.toml
@@ -17,9 +17,9 @@ c_bindings = ["libc"]
neon = []
iccv4-enabled = []
cmyk = []
[dependencies]
libc = {version = "0.2", optional = true }
[build-dependencies]
-rustc_version = "0.2"
+rustc_version = "0.4"
diff --git a/mozglue/static/rust/Cargo.toml b/mozglue/static/rust/Cargo.toml
--- a/mozglue/static/rust/Cargo.toml
+++ b/mozglue/static/rust/Cargo.toml
@@ -8,12 +8,12 @@ license = "MPL"
path = "lib.rs"
[dependencies]
arrayvec = "0.5"
[build-dependencies]
mozbuild = "0.1"
cc = "1"
-rustc_version = "0.2"
+rustc_version = "0.4"
[features]
moz_memory = []
diff --git a/testing/geckodriver/Cargo.toml b/testing/geckodriver/Cargo.toml
--- a/testing/geckodriver/Cargo.toml
+++ b/testing/geckodriver/Cargo.toml
@@ -15,17 +15,17 @@ chrono = "0.4.6"
clap = { version = "3.1", default-features = false, features = ["cargo", "std", "suggestions", "wrap_help"] }
hyper = "0.14"
lazy_static = "1.0"
log = { version = "0.4", features = ["std"] }
marionette = { path = "./marionette", version="0.2.0" }
mozdevice = { path = "../mozbase/rust/mozdevice", version="0.5.0" }
mozprofile = { path = "../mozbase/rust/mozprofile", version="0.8.0" }
mozrunner = { path = "../mozbase/rust/mozrunner", version="0.14.0" }
-mozversion = { path = "../mozbase/rust/mozversion", version="0.4.3" }
+mozversion = { path = "../mozbase/rust/mozversion", version="0.5.0-alpha" }
regex = { version="1.0", default-features = false, features = ["perf", "std"] }
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
serde_yaml = "0.8"
tempfile = "3"
url = "2.0"
uuid = { version = "0.8", features = ["v4"] }
diff --git a/testing/mozbase/rust/mozversion/Cargo.toml b/testing/mozbase/rust/mozversion/Cargo.toml
--- a/testing/mozbase/rust/mozversion/Cargo.toml
+++ b/testing/mozbase/rust/mozversion/Cargo.toml
@@ -1,14 +1,14 @@
[package]
name = "mozversion"
-version = "0.4.3"
+version = "0.5.0-alpha"
authors = ["Mozilla"]
description = "Utility for accessing Firefox version metadata"
keywords = ["mozilla", "firefox"]
repository = "https://hg.mozilla.org/mozilla-central/file/tip/testing/mozbase/rust/mozversion"
license = "MPL-2.0"
edition = "2018"
[dependencies]
regex = { version = "1", default-features = false, features = ["perf", "std"] }
rust-ini = "0.10"
-semver = "0.9"
+semver = "1.0"
diff --git a/testing/mozbase/rust/mozversion/src/lib.rs b/testing/mozbase/rust/mozversion/src/lib.rs
--- a/testing/mozbase/rust/mozversion/src/lib.rs
+++ b/testing/mozbase/rust/mozversion/src/lib.rs
@@ -101,18 +101,18 @@ impl Version {
// The way the semver crate handles prereleases isn't what we want here
// This should be fixed in the long term by implementing our own comparison
// operators, but for now just act as if prerelease metadata was missing,
// otherwise it is almost impossible to use this with nightly
semver::Version {
major: self.major,
minor: self.minor,
patch: self.patch,
- pre: vec![],
- build: vec![],
+ pre: semver::Prerelease::EMPTY,
+ build: semver::BuildMetadata::EMPTY,
}
}
pub fn matches(&self, version_req: &str) -> VersionResult<bool> {
let req = semver::VersionReq::parse(version_req)?;
Ok(req.matches(&self.to_semver()))
}
}
@@ -269,17 +269,17 @@ fn parse_binary_version(version_str: &st
#[derive(Clone, Debug)]
pub enum Error {
/// Error parsing a version string
VersionError(String),
/// Error reading application metadata
MetadataError(String),
/// Error processing a string as a semver comparator
- SemVerError(semver::ReqParseError),
+ SemVerError(String),
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::VersionError(ref x) => {
"VersionError: ".fmt(f)?;
x.fmt(f)
@@ -291,28 +291,25 @@ impl Display for Error {
Error::SemVerError(ref e) => {
"SemVerError: ".fmt(f)?;
e.fmt(f)
}
}
}
}
-impl From<semver::ReqParseError> for Error {
- fn from(err: semver::ReqParseError) -> Error {
- Error::SemVerError(err)
+impl From<semver::Error> for Error {
+ fn from(err: semver::Error) -> Error {
+ Error::SemVerError(err.to_string())
}
}
impl error::Error for Error {
fn cause(&self) -> Option<&dyn error::Error> {
- match *self {
- Error::SemVerError(ref e) => Some(e),
- Error::VersionError(_) | Error::MetadataError(_) => None,
- }
+ None
}
}
pub type VersionResult<T> = Result<T, Error>;
#[cfg(target_os = "macos")]
mod platform {
use std::path::{Path, PathBuf};
diff --git a/third_party/rust/cubeb-pulse/.cargo-checksum.json b/third_party/rust/cubeb-pulse/.cargo-checksum.json
--- a/third_party/rust/cubeb-pulse/.cargo-checksum.json
+++ b/third_party/rust/cubeb-pulse/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"95d0d2542c04f0c932f58591b92c3051db5c95657bf5f24b6a6110f7b667568d","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"d8f84d114794b79a02c8d93724951a0b924f4815e446d666e66877c7a90d0446","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"839fbbd90e501c9e455e6b46729f8c3cc03b368b6b45d02c82399660b7cf8289","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"525e1f6be1990deef3c42d34fc4e25947be642ce242514f8e3428737146cc755","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
\ No newline at end of file
+{"files":{".editorconfig":"bf047bd1da10cabb99eea666d1e57c321eba4716dccb3e4ed0e2c5fe3ca53858",".github/workflows/build.yml":"95d0d2542c04f0c932f58591b92c3051db5c95657bf5f24b6a6110f7b667568d","AUTHORS":"0e0ac930a68ce2f6b876126b195add177f0d3886facb9260f4d9b69f1988f0cc","Cargo.toml":"13fe95ad27f37b8423958d78093ecff3ade9fffb28c5980604b624c2b617e5a7","LICENSE":"44c6b5ae5ec3fe2fbc608b00e6f4896f4d2d5c7e525fcbaa3eaa3cf2f3d5a983","README.md":"0079450bb4b013bac065ed1750851e461a3710ebad1f323817da1cb82db0bc4f","src/backend/context.rs":"839fbbd90e501c9e455e6b46729f8c3cc03b368b6b45d02c82399660b7cf8289","src/backend/cork_state.rs":"4a0f1afc7d9f333dac89218cc56d7d32fbffb487cd48c1c9a4e03d79cb3b5e28","src/backend/intern.rs":"11ca424e4eb77f8eb9fd5a6717d1e791facf9743156a8534f0016fcf64d57b0f","src/backend/mod.rs":"d5da05348bf1a7f65c85b14372964a49dc4849f0aee96c75e2c18b51fb03fcaf","src/backend/stream.rs":"e88a04ab7094b9df1bcdd07628369ec70ecb2062b91b0bd86f2642962814405c","src/capi.rs":"fa0fa020f0d0efe55aa0fc3596405e8407bbe2cbe6c7a558345304e6da87994e","src/lib.rs":"b41bbdc562cbfb130ed7c1e53fe69944774f515705341d8ce48a2f82c8c0c2c5"},"package":null}
\ No newline at end of file
diff --git a/third_party/rust/cubeb-pulse/Cargo.toml b/third_party/rust/cubeb-pulse/Cargo.toml
--- a/third_party/rust/cubeb-pulse/Cargo.toml
+++ b/third_party/rust/cubeb-pulse/Cargo.toml
@@ -10,10 +10,10 @@ pulse-dlopen = ["pulse-ffi/dlopen"]
[lib]
crate-type = ["staticlib", "rlib"]
[dependencies]
cubeb-backend = "0.10"
pulse-ffi = { path = "pulse-ffi" }
pulse = { path = "pulse-rs" }
-semver = "^0.9"
+semver = "1.0"
ringbuf = "0.2"
diff --git a/third_party/rust/cubeb-pulse/src/backend/stream.rs b/third_party/rust/cubeb-pulse/src/backend/stream.rs
--- a/third_party/rust/cubeb-pulse/src/backend/stream.rs
+++ b/third_party/rust/cubeb-pulse/src/backend/stream.rs
@@ -350,16 +350,25 @@ impl<'ctx> PulseStream<'ctx> {
ptr::null_mut(),
read_frames as c_long,
)
};
if got < 0 || got as usize != read_frames {
let _ = s.cancel_write();
stm.shutdown = true;
+ if got < 0 {
+ unsafe {
+ stm.state_callback.unwrap()(
+ stm as *mut _ as *mut _,
+ stm.user_ptr,
+ ffi::CUBEB_STATE_ERROR,
+ );
+ }
+ }
break;
}
}
}
if read_size > 0 {
let _ = s.drop();
}
@@ -1064,16 +1073,23 @@ impl<'ctx> PulseStream<'ctx> {
read_ptr as *const _ as *mut _,
buffer,
(size / frame_size) as c_long,
) as i64
};
if got < 0 {
let _ = stm.cancel_write();
self.shutdown = true;
+ unsafe {
+ self.state_callback.unwrap()(
+ self as *const _ as *mut _,
+ self.user_ptr,
+ ffi::CUBEB_STATE_ERROR,
+ );
+ }
return;
}
// If more iterations move offset of read buffer
if !input_data.is_null() {
let in_frame_size = self.input_sample_spec.frame_size();
read_offset += (size / frame_size) * in_frame_size;
}
diff --git a/third_party/rust/rustc_version/.cargo-checksum.json b/third_party/rust/rustc_version/.cargo-checksum.json
--- a/third_party/rust/rustc_version/.cargo-checksum.json
+++ b/third_party/rust/rustc_version/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"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
+{"files":{"Cargo.toml":"6a2e927f37b4897e75470e62face13eff0fe846c57f8fcfb98bcd5e0fe8ed0a2","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"c9a75f18b9ab2927829a208fc6aa2cf4e63b8420887ba29cdb265d6619ae82d5","README.md":"40f1138d4ddcfcfd0534429cea8dcbdcaf4a175aca1c26662f011f6e83d2fd7a","deny.toml":"22979f2da49546b27a5c892d5216bf74215987810a2d011b58870471883b9437","src/lib.rs":"bc18589948e3c04c3ffb491ffc3d4eccd8037c8e377d0bbae8aca2b21978b1de","tests/all.rs":"7b2969022feab85a948fafd331d9bb30d80357d01afaf7e0f723908e75f39e89"},"package":"bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"}
\ No newline at end of file
diff --git a/third_party/rust/rustc_version/Cargo.toml b/third_party/rust/rustc_version/Cargo.toml
--- a/third_party/rust/rustc_version/Cargo.toml
+++ b/third_party/rust/rustc_version/Cargo.toml
@@ -1,26 +1,27 @@
# 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
+# 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]
+edition = "2018"
name = "rustc_version"
-version = "0.2.3"
-authors = ["Marvin Löbel <loebel.marvin@gmail.com>"]
+version = "0.4.0"
+authors = ["Dirkjan Ochtman <dirkjan@ochtman.nl>", "Marvin Löbel <loebel.marvin@gmail.com>"]
description = "A library for querying the version of a installed rustc compiler"
documentation = "https://docs.rs/rustc_version/"
readme = "README.md"
keywords = ["version", "rustc"]
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"
+version = "1.0"
+[dev-dependencies.doc-comment]
+version = "0.3"
diff --git a/third_party/rust/rustc_version/README.md b/third_party/rust/rustc_version/README.md
--- a/third_party/rust/rustc_version/README.md
+++ b/third_party/rust/rustc_version/README.md
@@ -1,40 +1,46 @@
rustc-version-rs
-==============
+================
+
+[![Documentation](https://docs.rs/rustc_version/badge.svg)](https://docs.rs/rustc_version/)
+[![Crates.io](https://img.shields.io/crates/v/rustc_version.svg)](https://crates.io/crates/rustc_version)
+[![Build status](https://github.com/Kimundi/rustc-version-rs/workflows/CI/badge.svg)](https://github.com/Kimundi/rustc-version-rs/actions?query=workflow%3ACI)
A library for querying the version of a `rustc` compiler.
This can be used by build scripts or other tools dealing with Rust sources
-to make decisions based on the version of the compiler.
+to make decisions based on the version of the compiler. Current MSRV is 1.32.0.
-[![Travis-CI Status](https://travis-ci.org/Kimundi/rustc-version-rs.png?branch=master)](https://travis-ci.org/Kimundi/rustc-version-rs)
+If this is of interest, also consider looking at these other crates:
+
+* [autocfg](https://crates.io/crates/autocfg/), which helps with feature detection instead of depending on compiler versions
+* [rustversion](https://github.com/dtolnay/rustversion) provides a procedural macro with no other dependencies
# Getting Started
[rustc-version-rs is available on crates.io](https://crates.io/crates/rustc_version).
It is recommended to look there for the newest released version, as well as links to the newest builds of the docs.
At the point of the last update of this README, the latest published version could be used like this:
Add the following dependency to your Cargo manifest...
```toml
[build-dependencies]
rustc_version = "0.2"
```
-...and see the [docs](http://kimundi.github.io/rustc-version-rs/rustc_version/index.html) for how to use it.
+... and see the [docs](https://docs.rs/rustc_version) for how to use it.
# Example
```rust
// This could be a cargo build script
-extern crate rustc_version;
use rustc_version::{version, version_meta, Channel, Version};
fn main() {
// Assert we haven't travelled back in time
assert!(version().unwrap().major >= 1);
// Set cfg flags depending on release channel
match version_meta().unwrap().channel {
diff --git a/third_party/rust/rustc_version/deny.toml b/third_party/rust/rustc_version/deny.toml
new file mode 100644
--- /dev/null
+++ b/third_party/rust/rustc_version/deny.toml
@@ -0,0 +1,3 @@
+[licenses]
+allow-osi-fsf-free = "either"
+copyleft = "deny"
diff --git a/third_party/rust/rustc_version/src/errors.rs b/third_party/rust/rustc_version/src/errors.rs
deleted file mode 100644
--- a/third_party/rust/rustc_version/src/errors.rs
+++ /dev/null
@@ -1,79 +0,0 @@
-use std::{self, error, fmt, io, str};
-use semver::{self, Identifier};
-
-/// The error type for this crate.
-#[derive(Debug)]
-pub enum Error {
- /// An error ocurrend when executing the `rustc` command.
- CouldNotExecuteCommand(io::Error),
- /// The output of `rustc -vV` was not valid utf-8.
- Utf8Error(str::Utf8Error),
- /// The output of `rustc -vV` was not in the expected format.
- UnexpectedVersionFormat,
- /// An error ocurred in parsing a `VersionReq`.
- ReqParseError(semver::ReqParseError),
- /// An error ocurred in parsing the semver.
- SemVerError(semver::SemVerError),
- /// The pre-release tag is unknown.
- UnknownPreReleaseTag(Identifier),
-}
-use Error::*;
-
-impl fmt::Display for Error {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- use std::error::Error;
- match *self {
- CouldNotExecuteCommand(ref e) => write!(f, "{}: {}", self.description(), e),
- Utf8Error(_) => write!(f, "{}", self.description()),
- UnexpectedVersionFormat => write!(f, "{}", self.description()),
- ReqParseError(ref e) => write!(f, "{}: {}", self.description(), e),
- SemVerError(ref e) => write!(f, "{}: {}", self.description(), e),
- UnknownPreReleaseTag(ref i) => write!(f, "{}: {}", self.description(), i),
- }
- }
-}
-
-impl error::Error for Error {
- fn cause(&self) -> Option<&error::Error> {
- match *self {
- CouldNotExecuteCommand(ref e) => Some(e),
- Utf8Error(ref e) => Some(e),
- UnexpectedVersionFormat => None,
- ReqParseError(ref e) => Some(e),
- SemVerError(ref e) => Some(e),
- UnknownPreReleaseTag(_) => None,
- }
- }
-
- fn description(&self) -> &str {
- match *self {
- CouldNotExecuteCommand(_) => "could not execute command",
- Utf8Error(_) => "invalid UTF-8 output from `rustc -vV`",
- UnexpectedVersionFormat => "unexpected `rustc -vV` format",
- ReqParseError(_) => "error parsing version requirement",
- SemVerError(_) => "error parsing version",
- UnknownPreReleaseTag(_) => "unknown pre-release tag",
- }
- }
-}
-
-macro_rules! impl_from {
- ($($err_ty:ty => $variant:ident),* $(,)*) => {
- $(
- impl From<$err_ty> for Error {
- fn from(e: $err_ty) -> Error {
- Error::$variant(e)
- }
- }
- )*
- }
-}
-
-impl_from! {
- str::Utf8Error => Utf8Error,
- semver::SemVerError => SemVerError,
- semver::ReqParseError => ReqParseError,
-}
-
-/// The result type for this crate.
-pub type Result<T> = std::result::Result<T, Error>;
diff --git a/third_party/rust/rustc_version/src/lib.rs b/third_party/rust/rustc_version/src/lib.rs
--- a/third_party/rust/rustc_version/src/lib.rs
+++ b/third_party/rust/rustc_version/src/lib.rs
@@ -17,73 +17,138 @@
//! It calls `$RUSTC --version -v` and parses the output, falling
//! back to `rustc` if `$RUSTC` is not set.
//!
//! # Example
//!
//! ```rust
//! // This could be a cargo build script
//!
-//! extern crate rustc_version;
//! use rustc_version::{version, version_meta, Channel, Version};
//!
-//! fn main() {
-//! // Assert we haven't travelled back in time
-//! assert!(version().unwrap().major >= 1);
+//! // Assert we haven't travelled back in time
+//! assert!(version().unwrap().major >= 1);
//!
-//! // Set cfg flags depending on release channel
-//! match version_meta().unwrap().channel {
-//! Channel::Stable => {
-//! println!("cargo:rustc-cfg=RUSTC_IS_STABLE");
-//! }
-//! Channel::Beta => {
-//! println!("cargo:rustc-cfg=RUSTC_IS_BETA");
-//! }
-//! Channel::Nightly => {
-//! println!("cargo:rustc-cfg=RUSTC_IS_NIGHTLY");
-//! }
-//! Channel::Dev => {
-//! println!("cargo:rustc-cfg=RUSTC_IS_DEV");
-//! }
+//! // Set cfg flags depending on release channel
+//! match version_meta().unwrap().channel {
+//! Channel::Stable => {
+//! println!("cargo:rustc-cfg=RUSTC_IS_STABLE");
+//! }
+//! Channel::Beta => {
+//! println!("cargo:rustc-cfg=RUSTC_IS_BETA");
//! }
+//! Channel::Nightly => {
+//! println!("cargo:rustc-cfg=RUSTC_IS_NIGHTLY");
+//! }
+//! Channel::Dev => {
+//! println!("cargo:rustc-cfg=RUSTC_IS_DEV");
+//! }
+//! }
//!
-//! // Check for a minimum version
-//! if version().unwrap() >= Version::parse("1.4.0").unwrap() {
-//! println!("cargo:rustc-cfg=compiler_has_important_bugfix");
-//! }
+//! // Check for a minimum version
+//! if version().unwrap() >= Version::parse("1.4.0").unwrap() {
+//! println!("cargo:rustc-cfg=compiler_has_important_bugfix");
//! }
//! ```
-extern crate semver;
-use semver::Identifier;
+#[cfg(test)]
+#[macro_use]
+extern crate doc_comment;
+
+#[cfg(test)]
+doctest!("../README.md");
+
+use std::collections::HashMap;
use std::process::Command;
-use std::{env, str};
-use std::ffi::OsString;
+use std::{env, error, fmt, io, num, str};
+use std::{ffi::OsString, str::FromStr};
// Convenience re-export to allow version comparison without needing to add
// semver crate.
pub use semver::Version;
-mod errors;
-pub use errors::{Error, Result};
+use Error::*;
/// Release channel of the compiler.
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum Channel {
/// Development release channel
Dev,
/// Nightly release channel
Nightly,
/// Beta release channel
Beta,
/// Stable release channel
Stable,
}
-/// Rustc version plus metada like git short hash and build date.
+/// LLVM version
+///
+/// LLVM's version numbering scheme is not semver compatible until version 4.0
+///
+/// rustc [just prints the major and minor versions], so other parts of the version are not included.
+///
+/// [just prints the major and minor versions]: https://github.com/rust-lang/rust/blob/b5c9e2448c9ace53ad5c11585803894651b18b0a/compiler/rustc_codegen_llvm/src/llvm_util.rs#L173-L178
+#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct LlvmVersion {
+ // fields must be ordered major, minor for comparison to be correct
+ /// Major version
+ pub major: u64,
+ /// Minor version
+ pub minor: u64,
+ // TODO: expose micro version here
+}
+
+impl fmt::Display for LlvmVersion {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}.{}", self.major, self.minor)
+ }
+}
+
+impl FromStr for LlvmVersion {
+ type Err = LlvmVersionParseError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ let mut parts = s
+ .split('.')
+ .map(|part| -> Result<u64, LlvmVersionParseError> {
+ if part == "0" {
+ Ok(0)
+ } else if part.starts_with('0') {
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros)
+ } else if part.starts_with('-') || part.starts_with('+') {
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign)
+ } else {
+ Ok(part.parse()?)
+ }
+ });
+
+ let major = parts.next().unwrap()?;
+ let mut minor = 0;
+
+ if let Some(part) = parts.next() {
+ minor = part?;
+ } else if major < 4 {
+ // LLVM versions earlier than 4.0 have significant minor versions, so require the minor version in this case.
+ return Err(LlvmVersionParseError::MinorVersionRequiredBefore4);
+ }
+
+ if let Some(Err(e)) = parts.next() {
+ return Err(e);
+ }
+
+ if parts.next().is_some() {
+ return Err(LlvmVersionParseError::TooManyComponents);
+ }
+
+ Ok(Self { major, minor })
+ }
+}
+
+/// Rustc version plus metadata like git short hash and build date.
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct VersionMeta {
/// Version of the compiler
pub semver: Version,
/// Git short hash of the build of the compiler
pub commit_hash: Option<String>,
@@ -96,27 +161,37 @@ pub struct VersionMeta {
/// Release channel of the compiler
pub channel: Channel,
/// Host target triple of the compiler
pub host: String,
/// Short version string of the compiler
pub short_version_string: String,
+
+ /// Version of LLVM used by the compiler
+ pub llvm_version: Option<LlvmVersion>,
}
impl VersionMeta {
/// Returns the version metadata for `cmd`, which should be a `rustc` command.
- pub fn for_command(cmd: Command) -> Result<VersionMeta> {
- let mut cmd = cmd;
+ pub fn for_command(mut cmd: Command) -> Result<VersionMeta> {
+ let out = cmd
+ .arg("-vV")
+ .output()
+ .map_err(Error::CouldNotExecuteCommand)?;
- let out = cmd.arg("-vV").output().map_err(Error::CouldNotExecuteCommand)?;
- let out = str::from_utf8(&out.stdout)?;
+ if !out.status.success() {
+ return Err(Error::CommandError {
+ stdout: String::from_utf8_lossy(&out.stdout).into(),
+ stderr: String::from_utf8_lossy(&out.stderr).into(),
+ });
+ }
- version_meta_for(out)
+ version_meta_for(str::from_utf8(&out.stdout)?)
}
}
/// Returns the `rustc` SemVer version.
pub fn version() -> Result<Version> {
Ok(version_meta()?.semver)
}
@@ -127,221 +202,216 @@ pub fn version_meta() -> Result<VersionM
VersionMeta::for_command(Command::new(cmd))
}
/// Parses a "rustc -vV" output string and returns
/// the SemVer version and additional metadata
/// like the git short hash and build date.
pub fn version_meta_for(verbose_version_string: &str) -> Result<VersionMeta> {
- let out: Vec<_> = verbose_version_string.lines().collect();
-
- if !(out.len() >= 6 && out.len() <= 8) {
- return Err(Error::UnexpectedVersionFormat);
- }
+ let mut map = HashMap::new();
+ for (i, line) in verbose_version_string.lines().enumerate() {
+ if i == 0 {
+ map.insert("short", line);
+ continue;
+ }
- let short_version_string = out[0];
+ let mut parts = line.splitn(2, ": ");
+ let key = match parts.next() {
+ Some(key) => key,
+ None => continue,
+ };
- fn expect_prefix<'a>(line: &'a str, prefix: &str) -> Result<&'a str> {
- if line.starts_with(prefix) {
- Ok(&line[prefix.len()..])
- } else {
- Err(Error::UnexpectedVersionFormat)
+ if let Some(value) = parts.next() {
+ map.insert(key, value);
}
}
- let commit_hash = match expect_prefix(out[2], "commit-hash: ")? {
- "unknown" => None,
- hash => Some(hash.to_owned()),
- };
+ let short_version_string = expect_key("short", &map)?;
+ let host = expect_key("host", &map)?;
+ let release = expect_key("release", &map)?;
+ let semver: Version = release.parse()?;
- let commit_date = match expect_prefix(out[3], "commit-date: ")? {
- "unknown" => None,
- hash => Some(hash.to_owned()),
+ let channel = match semver.pre.split('.').next().unwrap() {
+ "" => Channel::Stable,
+ "dev" => Channel::Dev,
+ "beta" => Channel::Beta,
+ "nightly" => Channel::Nightly,
+ x => return Err(Error::UnknownPreReleaseTag(x.to_owned())),
};
- // Handle that the build date may or may not be present.
- let mut idx = 4;
- let mut build_date = None;
- if out[idx].starts_with("build-date") {
- build_date = match expect_prefix(out[idx], "build-date: ")? {
- "unknown" => None,
- s => Some(s.to_owned()),
- };
- idx += 1;
- }
-
- let host = expect_prefix(out[idx], "host: ")?;
- idx += 1;
- let release = expect_prefix(out[idx], "release: ")?;
-
- 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,
- ref x => return Err(Error::UnknownPreReleaseTag(x.clone())),
- }
+ let commit_hash = expect_key_or_unknown("commit-hash", &map)?;
+ let commit_date = expect_key_or_unknown("commit-date", &map)?;
+ let build_date = map
+ .get("build-date")
+ .filter(|&v| *v != "unknown")
+ .map(|&v| String::from(v));
+ let llvm_version = match map.get("LLVM version") {
+ Some(&v) => Some(v.parse()?),
+ None => None,
};
Ok(VersionMeta {
- semver: semver,
- commit_hash: commit_hash,
- commit_date: commit_date,
- build_date: build_date,
- channel: channel,
- host: host.into(),
- short_version_string: short_version_string.into(),
+ semver,
+ commit_hash,
+ commit_date,
+ build_date,
+ channel,
+ host,
+ short_version_string,
+ llvm_version,
})
}
-#[test]
-fn smoketest() {
- let v = version().unwrap();
- assert!(v.major >= 1);
+fn expect_key_or_unknown(key: &str, map: &HashMap<&str, &str>) -> Result<Option<String>, Error> {
+ match map.get(key) {
+ Some(&v) if v == "unknown" => Ok(None),
+ Some(&v) => Ok(Some(String::from(v))),
+ None => Err(Error::UnexpectedVersionFormat),
+ }
+}
- let v = version_meta().unwrap();
- assert!(v.semver.major >= 1);
-
- assert!(version().unwrap() >= Version::parse("1.0.0").unwrap());
+fn expect_key(key: &str, map: &HashMap<&str, &str>) -> Result<String, Error> {
+ map.get(key)
+ .map(|&v| String::from(v))
+ .ok_or(Error::UnexpectedVersionFormat)
}
-#[test]
-fn parse_unexpected() {
- let res = version_meta_for(
-"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
-binary: rustc
-commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e
-commit-date: 2015-05-13
-rust-birthday: 2015-05-14
-host: x86_64-unknown-linux-gnu
-release: 1.0.0");
+/// LLVM Version Parse Error
+#[derive(Debug)]
+pub enum LlvmVersionParseError {
+ /// An error occurred in parsing a version component as an integer
+ ParseIntError(num::ParseIntError),
+ /// A version component must not have leading zeros
+ ComponentMustNotHaveLeadingZeros,
+ /// A version component has a sign
+ ComponentMustNotHaveSign,
+ /// Minor version component must be zero on LLVM versions later than 4.0
+ MinorVersionMustBeZeroAfter4,
+ /// Minor version component is required on LLVM versions earlier than 4.0
+ MinorVersionRequiredBefore4,
+ /// Too many components
+ TooManyComponents,
+}
- assert!(match res {
- Err(Error::UnexpectedVersionFormat) => true,
- _ => false,
- });
-
+impl From<num::ParseIntError> for LlvmVersionParseError {
+ fn from(e: num::ParseIntError) -> Self {
+ LlvmVersionParseError::ParseIntError(e)
+ }
}
-#[test]
-fn parse_1_0_0() {
- let version = version_meta_for(
-"rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
-binary: rustc
-commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e
-commit-date: 2015-05-13
-build-date: 2015-05-14
-host: x86_64-unknown-linux-gnu
-release: 1.0.0").unwrap();
-
- assert_eq!(version.semver, Version::parse("1.0.0").unwrap());
- assert_eq!(version.commit_hash, Some("a59de37e99060162a2674e3ff45409ac73595c0e".into()));
- assert_eq!(version.commit_date, Some("2015-05-13".into()));
- assert_eq!(version.build_date, Some("2015-05-14".into()));
- assert_eq!(version.channel, Channel::Stable);
- assert_eq!(version.host, "x86_64-unknown-linux-gnu");
- assert_eq!(version.short_version_string, "rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)");
+impl fmt::Display for LlvmVersionParseError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ LlvmVersionParseError::ParseIntError(e) => {
+ write!(f, "error parsing LLVM version component: {}", e)
+ }
+ LlvmVersionParseError::ComponentMustNotHaveLeadingZeros => {
+ write!(f, "a version component must not have leading zeros")
+ }
+ LlvmVersionParseError::ComponentMustNotHaveSign => {
+ write!(f, "a version component must not have a sign")
+ }
+ LlvmVersionParseError::MinorVersionMustBeZeroAfter4 => write!(
+ f,
+ "LLVM's minor version component must be 0 for versions greater than 4.0"
+ ),
+ LlvmVersionParseError::MinorVersionRequiredBefore4 => write!(
+ f,
+ "LLVM's minor version component is required for versions less than 4.0"
+ ),
+ LlvmVersionParseError::TooManyComponents => write!(f, "too many version components"),
+ }
+ }
}
-
-#[test]
-fn parse_unknown() {
- let version = version_meta_for(
-"rustc 1.3.0
-binary: rustc
-commit-hash: unknown
-commit-date: unknown
-host: x86_64-unknown-linux-gnu
-release: 1.3.0").unwrap();
-
- assert_eq!(version.semver, Version::parse("1.3.0").unwrap());
- assert_eq!(version.commit_hash, None);
- assert_eq!(version.commit_date, None);
- assert_eq!(version.channel, Channel::Stable);
- assert_eq!(version.host, "x86_64-unknown-linux-gnu");
- assert_eq!(version.short_version_string, "rustc 1.3.0");
+impl error::Error for LlvmVersionParseError {
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ match self {
+ LlvmVersionParseError::ParseIntError(e) => Some(e),
+ LlvmVersionParseError::ComponentMustNotHaveLeadingZeros
+ | LlvmVersionParseError::ComponentMustNotHaveSign
+ | LlvmVersionParseError::MinorVersionMustBeZeroAfter4
+ | LlvmVersionParseError::MinorVersionRequiredBefore4
+ | LlvmVersionParseError::TooManyComponents => None,
+ }
+ }
}
-#[test]
-fn parse_nightly() {
- let version = version_meta_for(
-"rustc 1.5.0-nightly (65d5c0833 2015-09-29)
-binary: rustc
-commit-hash: 65d5c083377645a115c4ac23a620d3581b9562b6
-commit-date: 2015-09-29
-host: x86_64-unknown-linux-gnu
-release: 1.5.0-nightly").unwrap();
-
- assert_eq!(version.semver, Version::parse("1.5.0-nightly").unwrap());
- assert_eq!(version.commit_hash, Some("65d5c083377645a115c4ac23a620d3581b9562b6".into()));
- assert_eq!(version.commit_date, Some("2015-09-29".into()));
- assert_eq!(version.channel, Channel::Nightly);
- assert_eq!(version.host, "x86_64-unknown-linux-gnu");
- assert_eq!(version.short_version_string, "rustc 1.5.0-nightly (65d5c0833 2015-09-29)");
-}
-
-#[test]
-fn parse_stable() {
- let version = version_meta_for(
-"rustc 1.3.0 (9a92aaf19 2015-09-15)
-binary: rustc
-commit-hash: 9a92aaf19a64603b02b4130fe52958cc12488900
-commit-date: 2015-09-15
-host: x86_64-unknown-linux-gnu
-release: 1.3.0").unwrap();
-
- assert_eq!(version.semver, Version::parse("1.3.0").unwrap());
- assert_eq!(version.commit_hash, Some("9a92aaf19a64603b02b4130fe52958cc12488900".into()));
- assert_eq!(version.commit_date, Some("2015-09-15".into()));
- assert_eq!(version.channel, Channel::Stable);
- assert_eq!(version.host, "x86_64-unknown-linux-gnu");
- assert_eq!(version.short_version_string, "rustc 1.3.0 (9a92aaf19 2015-09-15)");
+/// The error type for this crate.
+#[derive(Debug)]
+pub enum Error {
+ /// An error occurred while trying to find the `rustc` to run.
+ CouldNotExecuteCommand(io::Error),
+ /// Error output from the command that was run.
+ CommandError {
+ /// stdout output from the command
+ stdout: String,
+ /// stderr output from the command
+ stderr: String,
+ },
+ /// The output of `rustc -vV` was not valid utf-8.
+ Utf8Error(str::Utf8Error),
+ /// The output of `rustc -vV` was not in the expected format.
+ UnexpectedVersionFormat,
+ /// An error occurred in parsing the semver.
+ SemVerError(semver::Error),
+ /// The pre-release tag is unknown.
+ UnknownPreReleaseTag(String),
+ /// An error occurred in parsing a `LlvmVersion`.
+ LlvmVersionError(LlvmVersionParseError),
}
-#[test]
-fn parse_1_16_0_nightly() {
- let version = version_meta_for(
-"rustc 1.16.0-nightly (5d994d8b7 2017-01-05)
-binary: rustc
-commit-hash: 5d994d8b7e482e87467d4a521911477bd8284ce3
-commit-date: 2017-01-05
-host: x86_64-unknown-linux-gnu
-release: 1.16.0-nightly
-LLVM version: 3.9").unwrap();
-
- assert_eq!(version.semver, Version::parse("1.16.0-nightly").unwrap());
- assert_eq!(version.commit_hash, Some("5d994d8b7e482e87467d4a521911477bd8284ce3".into()));
- assert_eq!(version.commit_date, Some("2017-01-05".into()));
- assert_eq!(version.channel, Channel::Nightly);
- assert_eq!(version.host, "x86_64-unknown-linux-gnu");
- assert_eq!(version.short_version_string, "rustc 1.16.0-nightly (5d994d8b7 2017-01-05)");
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match *self {
+ CouldNotExecuteCommand(ref e) => write!(f, "could not execute command: {}", e),
+ CommandError {
+ ref stdout,
+ ref stderr,
+ } => write!(
+ f,
+ "error from command -- stderr:\n\n{}\n\nstderr:\n\n{}",
+ stderr, stdout,
+ ),
+ Utf8Error(_) => write!(f, "invalid UTF-8 output from `rustc -vV`"),
+ UnexpectedVersionFormat => write!(f, "unexpected `rustc -vV` format"),
+ SemVerError(ref e) => write!(f, "error parsing version: {}", e),
+ UnknownPreReleaseTag(ref i) => write!(f, "unknown pre-release tag: {}", i),
+ LlvmVersionError(ref e) => write!(f, "error parsing LLVM's version: {}", e),
+ }
+ }
}
-/*
-#[test]
-fn version_matches_replacement() {
- let f = |s1: &str, s2: &str| {
- let a = Version::parse(s1).unwrap();
- let b = Version::parse(s2).unwrap();
- println!("{} <= {} : {}", s1, s2, a <= b);
- };
-
- println!();
+impl error::Error for Error {
+ fn source(&self) -> Option<&(dyn error::Error + 'static)> {
+ match *self {
+ CouldNotExecuteCommand(ref e) => Some(e),
+ CommandError { .. } => None,
+ Utf8Error(ref e) => Some(e),
+ UnexpectedVersionFormat => None,
+ SemVerError(ref e) => Some(e),
+ UnknownPreReleaseTag(_) => None,
+ LlvmVersionError(ref e) => Some(e),
+ }
+ }
+}
- f("1.5.0", "1.5.0");
- f("1.5.0-nightly", "1.5.0");
- f("1.5.0", "1.5.0-nightly");
- f("1.5.0-nightly", "1.5.0-nightly");
+macro_rules! impl_from {
+ ($($err_ty:ty => $variant:ident),* $(,)*) => {
+ $(
+ impl From<$err_ty> for Error {
+ fn from(e: $err_ty) -> Error {
+ Error::$variant(e)
+ }
+ }
+ )*
+ }
+}
- f("1.5.0", "1.6.0");
- f("1.5.0-nightly", "1.6.0");
- f("1.5.0", "1.6.0-nightly");
- f("1.5.0-nightly", "1.6.0-nightly");
+impl_from! {
+ str::Utf8Error => Utf8Error,
+ semver::Error => SemVerError,
+ LlvmVersionParseError => LlvmVersionError,
+}
- panic!();
-
-}
-*/
+/// The result type for this crate.
+pub type Result<T, E = Error> = std::result::Result<T, E>;
diff --git a/third_party/rust/rustc_version/tests/all.rs b/third_party/rust/rustc_version/tests/all.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/rustc_version/tests/all.rs
@@ -0,0 +1,456 @@
+#![allow(clippy::match_like_matches_macro)]
+
+use std::process::Command;
+
+use rustc_version::{
+ version, version_meta, version_meta_for, Channel, Error, LlvmVersion, LlvmVersionParseError,
+ Version, VersionMeta,
+};
+
+#[test]
+fn rustc_error() {
+ let mut cmd = Command::new("rustc");
+ cmd.arg("--FOO");
+ let stderr = match VersionMeta::for_command(cmd) {
+ Err(Error::CommandError { stdout: _, stderr }) => stderr,
+ _ => panic!("command error expected"),
+ };
+ assert_eq!(stderr, "error: Unrecognized option: \'FOO\'\n\n");
+}
+
+#[test]
+fn smoketest() {
+ let v = version().unwrap();
+ assert!(v.major >= 1);
+
+ let v = version_meta().unwrap();
+ assert!(v.semver.major >= 1);
+
+ assert!(version().unwrap() >= Version::parse("1.0.0").unwrap());
+}
+
+#[test]
+fn parse_1_0_0() {
+ let version = version_meta_for(
+ "rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)
+binary: rustc
+commit-hash: a59de37e99060162a2674e3ff45409ac73595c0e
+commit-date: 2015-05-13
+build-date: 2015-05-14
+host: x86_64-unknown-linux-gnu
+release: 1.0.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.0.0").unwrap());
+ assert_eq!(
+ version.commit_hash,
+ Some("a59de37e99060162a2674e3ff45409ac73595c0e".into())
+ );
+ assert_eq!(version.commit_date, Some("2015-05-13".into()));
+ assert_eq!(version.build_date, Some("2015-05-14".into()));
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "x86_64-unknown-linux-gnu");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14)"
+ );
+ assert_eq!(version.llvm_version, None);
+}
+
+#[test]
+fn parse_unknown() {
+ let version = version_meta_for(
+ "rustc 1.3.0
+binary: rustc
+commit-hash: unknown
+commit-date: unknown
+host: x86_64-unknown-linux-gnu
+release: 1.3.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.3.0").unwrap());
+ assert_eq!(version.commit_hash, None);
+ assert_eq!(version.commit_date, None);
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "x86_64-unknown-linux-gnu");
+ assert_eq!(version.short_version_string, "rustc 1.3.0");
+ assert_eq!(version.llvm_version, None);
+}
+
+#[test]
+fn parse_nightly() {
+ let version = version_meta_for(
+ "rustc 1.5.0-nightly (65d5c0833 2015-09-29)
+binary: rustc
+commit-hash: 65d5c083377645a115c4ac23a620d3581b9562b6
+commit-date: 2015-09-29
+host: x86_64-unknown-linux-gnu
+release: 1.5.0-nightly",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.5.0-nightly").unwrap());
+ assert_eq!(
+ version.commit_hash,
+ Some("65d5c083377645a115c4ac23a620d3581b9562b6".into())
+ );
+ assert_eq!(version.commit_date, Some("2015-09-29".into()));
+ assert_eq!(version.channel, Channel::Nightly);
+ assert_eq!(version.host, "x86_64-unknown-linux-gnu");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.5.0-nightly (65d5c0833 2015-09-29)"
+ );
+ assert_eq!(version.llvm_version, None);
+}
+
+#[test]
+fn parse_stable() {
+ let version = version_meta_for(
+ "rustc 1.3.0 (9a92aaf19 2015-09-15)
+binary: rustc
+commit-hash: 9a92aaf19a64603b02b4130fe52958cc12488900
+commit-date: 2015-09-15
+host: x86_64-unknown-linux-gnu
+release: 1.3.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.3.0").unwrap());
+ assert_eq!(
+ version.commit_hash,
+ Some("9a92aaf19a64603b02b4130fe52958cc12488900".into())
+ );
+ assert_eq!(version.commit_date, Some("2015-09-15".into()));
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "x86_64-unknown-linux-gnu");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.3.0 (9a92aaf19 2015-09-15)"
+ );
+ assert_eq!(version.llvm_version, None);
+}
+
+#[test]
+fn parse_1_16_0_nightly() {
+ let version = version_meta_for(
+ "rustc 1.16.0-nightly (5d994d8b7 2017-01-05)
+binary: rustc
+commit-hash: 5d994d8b7e482e87467d4a521911477bd8284ce3
+commit-date: 2017-01-05
+host: x86_64-unknown-linux-gnu
+release: 1.16.0-nightly
+LLVM version: 3.9",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.16.0-nightly").unwrap());
+ assert_eq!(
+ version.commit_hash,
+ Some("5d994d8b7e482e87467d4a521911477bd8284ce3".into())
+ );
+ assert_eq!(version.commit_date, Some("2017-01-05".into()));
+ assert_eq!(version.channel, Channel::Nightly);
+ assert_eq!(version.host, "x86_64-unknown-linux-gnu");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.16.0-nightly (5d994d8b7 2017-01-05)"
+ );
+ assert_eq!(
+ version.llvm_version,
+ Some(LlvmVersion { major: 3, minor: 9 })
+ );
+}
+
+#[test]
+fn parse_1_47_0_stable() {
+ let version = version_meta_for(
+ "rustc 1.47.0 (18bf6b4f0 2020-10-07)
+binary: rustc
+commit-hash: 18bf6b4f01a6feaf7259ba7cdae58031af1b7b39
+commit-date: 2020-10-07
+host: powerpc64le-unknown-linux-gnu
+release: 1.47.0
+LLVM version: 11.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.47.0").unwrap());
+ assert_eq!(
+ version.commit_hash,
+ Some("18bf6b4f01a6feaf7259ba7cdae58031af1b7b39".into())
+ );
+ assert_eq!(version.commit_date, Some("2020-10-07".into()));
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "powerpc64le-unknown-linux-gnu");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.47.0 (18bf6b4f0 2020-10-07)"
+ );
+ assert_eq!(
+ version.llvm_version,
+ Some(LlvmVersion {
+ major: 11,
+ minor: 0,
+ })
+ );
+}
+
+#[test]
+fn parse_llvm_micro() {
+ let version = version_meta_for(
+ "rustc 1.51.0-nightly (4253153db 2021-01-17)
+binary: rustc
+commit-hash: 4253153db205251f72ea4493687a31e04a2a8ca0
+commit-date: 2021-01-17
+host: x86_64-pc-windows-msvc
+release: 1.51.0-nightly
+LLVM version: 11.0.1",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.51.0-nightly").unwrap());
+ assert_eq!(
+ version.commit_hash.unwrap(),
+ "4253153db205251f72ea4493687a31e04a2a8ca0"
+ );
+ assert_eq!(version.commit_date.unwrap(), "2021-01-17");
+ assert_eq!(version.host, "x86_64-pc-windows-msvc");
+ assert_eq!(
+ version.short_version_string,
+ "rustc 1.51.0-nightly (4253153db 2021-01-17)"
+ );
+ assert_eq!(
+ version.llvm_version,
+ Some(LlvmVersion {
+ major: 11,
+ minor: 0
+ })
+ );
+}
+
+#[test]
+fn parse_debian_buster() {
+ let version = version_meta_for(
+ "rustc 1.41.1
+binary: rustc
+commit-hash: unknown
+commit-date: unknown
+host: powerpc64le-unknown-linux-gnu
+release: 1.41.1
+LLVM version: 7.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.41.1").unwrap());
+ assert_eq!(version.commit_hash, None);
+ assert_eq!(version.commit_date, None);
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "powerpc64le-unknown-linux-gnu");
+ assert_eq!(version.short_version_string, "rustc 1.41.1");
+ assert_eq!(
+ version.llvm_version,
+ Some(LlvmVersion { major: 7, minor: 0 })
+ );
+}
+
+#[test]
+fn parse_termux() {
+ let version = version_meta_for(
+ "rustc 1.46.0
+binary: rustc
+commit-hash: unknown
+commit-date: unknown
+host: aarch64-linux-android
+release: 1.46.0
+LLVM version: 10.0",
+ )
+ .unwrap();
+
+ assert_eq!(version.semver, Version::parse("1.46.0").unwrap());
+ assert_eq!(version.commit_hash, None);
+ assert_eq!(version.commit_date, None);
+ assert_eq!(version.channel, Channel::Stable);
+ assert_eq!(version.host, "aarch64-linux-android");
+ assert_eq!(version.short_version_string, "rustc 1.46.0");
+ assert_eq!(
+ version.llvm_version,
+ Some(LlvmVersion {
+ major: 10,
+ minor: 0,
+ })
+ );
+}
+
+#[test]
+fn parse_llvm_version_empty() {
+ let res: Result<LlvmVersion, _> = "".parse();
+ assert!(match res {
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_invalid_char() {
+ let res: Result<LlvmVersion, _> = "A".parse();
+ assert!(match res {
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_overflow() {
+ let res: Result<LlvmVersion, _> = "9999999999999999999999999999999".parse();
+ assert!(match res {
+ Err(LlvmVersionParseError::ParseIntError(_)) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_leading_zero_on_zero() {
+ let res: Result<LlvmVersion, _> = "00".parse();
+ assert!(match res {
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_leading_zero_on_nonzero() {
+ let res: Result<LlvmVersion, _> = "01".parse();
+ assert!(match res {
+ Err(LlvmVersionParseError::ComponentMustNotHaveLeadingZeros) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_4_components() {
+ let res: Result<LlvmVersion, _> = "4.0.0.0".parse();
+
+ assert!(match res {
+ Err(LlvmVersionParseError::TooManyComponents) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_component_sign_plus() {
+ let res: Result<LlvmVersion, _> = "1.+3".parse();
+
+ assert!(match res {
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_component_sign_minus() {
+ let res: Result<LlvmVersion, _> = "1.-3".parse();
+
+ assert!(match res {
+ Err(LlvmVersionParseError::ComponentMustNotHaveSign) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_3() {
+ let res: Result<LlvmVersion, _> = "3".parse();
+
+ assert!(match res {
+ Err(LlvmVersionParseError::MinorVersionRequiredBefore4) => true,
+ _ => false,
+ });
+}
+
+#[test]
+fn parse_llvm_version_5() {
+ let v: LlvmVersion = "5".parse().unwrap();
+ assert_eq!(v, LlvmVersion { major: 5, minor: 0 });
+}
+
+#[test]
+fn parse_llvm_version_5_0() {
+ let v: LlvmVersion = "5.0".parse().unwrap();
+ assert_eq!(v, LlvmVersion { major: 5, minor: 0 });
+}
+
+#[test]
+fn parse_llvm_version_4_0() {
+ let v: LlvmVersion = "4.0".parse().unwrap();
+ assert_eq!(v, LlvmVersion { major: 4, minor: 0 });
+}
+
+#[test]
+fn parse_llvm_version_3_0() {
+ let v: LlvmVersion = "3.0".parse().unwrap();
+ assert_eq!(v, LlvmVersion { major: 3, minor: 0 });
+}
+
+#[test]
+fn parse_llvm_version_3_9() {
+ let v: LlvmVersion = "3.9".parse().unwrap();
+ assert_eq!(v, LlvmVersion { major: 3, minor: 9 });
+}
+
+#[test]
+fn parse_llvm_version_11_0() {
+ let v: LlvmVersion = "11.0".parse().unwrap();
+ assert_eq!(
+ v,
+ LlvmVersion {
+ major: 11,
+ minor: 0
+ }
+ );
+}
+
+#[test]
+fn parse_llvm_version_11() {
+ let v: LlvmVersion = "11".parse().unwrap();
+ assert_eq!(
+ v,
+ LlvmVersion {
+ major: 11,
+ minor: 0
+ }
+ );
+}
+
+#[test]
+fn test_llvm_version_comparison() {
+ // check that field order is correct
+ assert!(LlvmVersion { major: 3, minor: 9 } < LlvmVersion { major: 4, minor: 0 });
+}
+
+/*
+#[test]
+fn version_matches_replacement() {
+ let f = |s1: &str, s2: &str| {
+ let a = Version::parse(s1).unwrap();
+ let b = Version::parse(s2).unwrap();
+ println!("{} <= {} : {}", s1, s2, a <= b);
+ };
+
+ println!();
+
+ f("1.5.0", "1.5.0");
+ f("1.5.0-nightly", "1.5.0");
+ f("1.5.0", "1.5.0-nightly");
+ f("1.5.0-nightly", "1.5.0-nightly");
+
+ f("1.5.0", "1.6.0");
+ f("1.5.0-nightly", "1.6.0");
+ f("1.5.0", "1.6.0-nightly");
+ f("1.5.0-nightly", "1.6.0-nightly");
+
+ panic!();
+
+}
+*/
diff --git a/third_party/rust/semver-parser/.cargo-checksum.json b/third_party/rust/semver-parser/.cargo-checksum.json
deleted file mode 100644
--- a/third_party/rust/semver-parser/.cargo-checksum.json
+++ /dev/null
@@ -1,1 +0,0 @@
-{"files":{"Cargo.toml":"67597114802114d2a7fdb457c1cf5f7e0c951b21e287c6a47b9a86b9028cf64d","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"d38feaa4f9468cd1e0ece22e0ad2eadfe6195a9a0a3843b7c722d5c7d81804fb","src/common.rs":"dc42336abd34e19ca9f732f33657e106f98dcc8c10d4c2564bc4f160cb31926e","src/lib.rs":"3ac8ef5a280344a25cb18ac386034c0fee8d64060fa14af5e25ed49f0cb2fd9e","src/range.rs":"3596f048d466d43887aff1e8c8c834476672a4627631ed35379c35466b5f02ec","src/recognize.rs":"9f16eda9fcd7d8af7eee4c3b89c611bd648040273fde6b35778f8a50b004c8b1","src/version.rs":"dbd91a4e4fd92a0aa9eb4f858ecbc1ecd680aa60572cc2ad2085e5c5c30e5b77"},"package":"388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"}
\ No newline at end of file
diff --git a/third_party/rust/semver-parser/Cargo.toml b/third_party/rust/semver-parser/Cargo.toml
deleted file mode 100644
--- a/third_party/rust/semver-parser/Cargo.toml
+++ /dev/null
@@ -1,11 +0,0 @@
-[package]
-name = "semver-parser"
-version = "0.7.0"
-authors = ["Steve Klabnik <steve@steveklabnik.com>"]
-license = "MIT/Apache-2.0"
-repository = "https://github.com/steveklabnik/semver-parser"
-homepage = "https://github.com/steveklabnik/semver-parser"
-documentation = "https://docs.rs/semver-parser"
-description = """
-Parsing of the semver spec.
-"""
diff --git a/third_party/rust/semver-parser/LICENSE-APACHE b/third_party/rust/semver-parser/LICENSE-APACHE
deleted file mode 100644
--- a/third_party/rust/semver-parser/LICENSE-APACHE
+++ /dev/null
@@ -1,201 +0,0 @@
- 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-parser/LICENSE-MIT b/third_party/rust/semver-parser/LICENSE-MIT
deleted file mode 100644
--- a/third_party/rust/semver-parser/LICENSE-MIT
+++ /dev/null
@@ -1,25 +0,0 @@
-Copyright (c) 2016 Steve Klabnik
-
-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-parser/src/common.rs b/third_party/rust/semver-parser/src/common.rs
deleted file mode 100644
--- a/third_party/rust/semver-parser/src/common.rs
+++ /dev/null
@@ -1,66 +0,0 @@
-use version::Identifier;
-use recognize::{Recognize, Alt, OneOrMore, Inclusive, OneByte};
-use std::str::from_utf8;
-
-// by the time we get here, we know that it's all valid characters, so this doesn't need to return
-// a result or anything
-fn parse_meta(s: &str) -> Vec<Identifier> {
- // Originally, I wanted to implement this method via calling parse, but parse is tolerant of
- // leading zeroes, and we want anything with leading zeroes to be considered alphanumeric, not
- // numeric. So the strategy is to check with a recognizer first, and then call parse once
- // we've determined that it's a number without a leading zero.
- s.split(".")
- .map(|part| {
- // another wrinkle: we made sure that any number starts with a
- // non-zero. But there's a problem: an actual zero is a number, yet
- // gets left out by this heuristic. So let's also check for the
- // single, lone zero.
- if is_alpha_numeric(part) {
- Identifier::AlphaNumeric(part.to_string())
- } else {
- // we can unwrap here because we know it is only digits due to the regex
- Identifier::Numeric(part.parse().unwrap())
- }
- }).collect()
-}
-
-// parse optional metadata (preceded by the prefix character)
-pub fn parse_optional_meta(s: &[u8], prefix_char: u8)-> Result<(Vec<Identifier>, usize), String> {
- if let Some(len) = prefix_char.p(s) {
- let start = len;
- if let Some(len) = letters_numbers_dash_dot(&s[start..]) {
- let end = start + len;
- Ok((parse_meta(from_utf8(&s[start..end]).unwrap()), end))
- } else {
- Err("Error parsing prerelease".to_string())
- }
- } else {
- Ok((Vec::new(), 0))
- }
-}
-
-pub fn is_alpha_numeric(s: &str) -> bool {
- if let Some((_val, len)) = numeric_identifier(s.as_bytes()) {
- // Return true for number with leading zero
- // Note: doing it this way also handily makes overflow fail over.
- len != s.len()
- } else {
- true
- }
-}
-
-// Note: could plumb overflow error up to return value as Result
-pub fn numeric_identifier(s: &[u8]) -> Option<(u64, usize)> {
- if let Some(len) = Alt(b'0', OneOrMore(Inclusive(b'0'..b'9'))).p(s) {
- from_utf8(&s[0..len]).unwrap().parse().ok().map(|val| (val, len))
- } else {
- None
- }
-}
-
-pub fn letters_numbers_dash_dot(s: &[u8]) -> Option<usize> {
- OneOrMore(OneByte(|c| c == b'-' || c == b'.' ||
- (b'0' <= c && c <= b'9') ||
- (b'a' <= c && c <= b'z') ||
- (b'A' <= c && c <= b'Z'))).p(s)
-}
diff --git a/third_party/rust/semver-parser/src/lib.rs b/third_party/rust/semver-parser/src/lib.rs
deleted file mode 100644
--- a/third_party/rust/semver-parser/src/lib.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-pub mod version;
-pub mod range;
-
-// for private stuff the two share
-mod common;
-
-// for recognizer combinators
-mod recognize;
diff --git a/third_party/rust/semver-parser/src/range.rs b/third_party/rust/semver-parser/src/range.rs
deleted file mode 100644
--- a/third_party/rust/semver-parser/src/range.rs
+++ /dev/null
@@ -1,696 +0,0 @@
-use common::{self, numeric_identifier, letters_numbers_dash_dot};
-use version::Identifier;
-use std::str::{FromStr, from_utf8};
-use recognize::*;
-
-#[derive(Debug)]
-pub struct VersionReq {
- pub predicates: Vec<Predicate>,
-}
-
-#[derive(PartialEq,Debug)]
-pub enum WildcardVersion {
- Major,
- Minor,
- Patch,
-}
-
-#[derive(PartialEq,Debug)]
-pub 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 FromStr for Op {
- type Err = String;
-
- fn from_str(s: &str) -> Result<Op, String> {
- match s {
- "=" => Ok(Op::Ex),
- ">" => Ok(Op::Gt),
- ">=" => Ok(Op::GtEq),
- "<" => Ok(Op::Lt),
- "<=" => Ok(Op::LtEq),
- "~" => Ok(Op::Tilde),
- "^" => Ok(Op::Compatible),
- _ => Err(String::from("Could not parse Op")),
- }
- }
-}
-
-#[derive(PartialEq,Debug)]
-pub struct Predicate {
- pub op: Op,
- pub major: u64,
- pub minor: Option<u64>,
- pub patch: Option<u64>,
- pub pre: Vec<Identifier>,
-}
-
-fn numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> {
- if let Some((val, len)) = numeric_identifier(s) {
- Some((Some(val), len))
- } else if let Some(len) = OneOf(b"*xX").p(s) {
- Some((None, len))
- } else {
- None
- }
-}
-
-fn dot_numeric_or_wild(s: &[u8]) -> Option<(Option<u64>, usize)> {
- b'.'.p(s).and_then(|len|
- numeric_or_wild(&s[len..]).map(|(val, len2)| (val, len + len2))
- )
-}
-
-fn operation(s: &[u8]) -> Option<(Op, usize)> {
- if let Some(len) = "=".p(s) {
- Some((Op::Ex, len))
- } else if let Some(len) = ">=".p(s) {
- Some((Op::GtEq, len))
- } else if let Some(len) = ">".p(s) {
- Some((Op::Gt, len))
- } else if let Some(len) = "<=".p(s) {
- Some((Op::LtEq, len))
- } else if let Some(len) = "<".p(s) {
- Some((Op::Lt, len))
- } else if let Some(len) = "~".p(s) {
- Some((Op::Tilde, len))
- } else if let Some(len) = "^".p(s) {
- Some((Op::Compatible, len))
- } else {
- None
- }
-}
-
-fn whitespace(s: &[u8]) -> Option<usize> {
- ZeroOrMore(OneOf(b"\t\r\n ")).p(s)
-}
-
-pub fn parse_predicate(range: &str) -> Result<Predicate, String> {
- let s = range.trim().as_bytes();
- let mut i = 0;
- let mut operation = if let Some((op, len)) = operation(&s[i..]) {
- i += len;
- op
- } else {
- // operations default to Compatible
- Op::Compatible
- };
- if let Some(len) = whitespace.p(&s[i..]) {
- i += len;
- }
- let major = if let Some((major, len)) = numeric_identifier(&s[i..]) {
- i += len;
- major
- } else {
- return Err("Error parsing major version number: ".to_string());
- };
- let minor = if let Some((minor, len)) = dot_numeric_or_wild(&s[i..]) {
- i += len;
- if minor.is_none() {
- operation = Op::Wildcard(WildcardVersion::Minor);
- }
- minor
- } else {
- None
- };
- let patch = if let Some((patch, len)) = dot_numeric_or_wild(&s[i..]) {
- i += len;
- if patch.is_none() {
- operation = Op::Wildcard(WildcardVersion::Patch);
- }
- patch
- } else {
- None
- };
- let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?;
- i += pre_len;
- if let Some(len) = (b'+', letters_numbers_dash_dot).p(&s[i..]) {
- i += len;
- }
- if i != s.len() {
- return Err("Extra junk after valid predicate: ".to_string() +
- from_utf8(&s[i..]).unwrap());
- }
- Ok(Predicate {
- op: operation,
- major: major,
- minor: minor,
- patch: patch,
- pre: pre,
- })
-}
-
-pub fn parse(ranges: &str) -> Result<VersionReq, String> {
- // null is an error
- if ranges == "\0" {
- return Err(String::from("Null is not a valid VersionReq"));
- }
-
- // an empty range is a major version wildcard
- // so is a lone * or x of either capitalization
- if (ranges == "")
- || (ranges == "*")
- || (ranges == "x")
- || (ranges == "X") {
- return Ok(VersionReq {
- predicates: vec![Predicate {
- op: Op::Wildcard(WildcardVersion::Major),
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- }],
- });
- }
-
-
- let ranges = ranges.trim();
-
- let predicates: Result<Vec<_>, String> = ranges
- .split(",")
- .map(|range| {
- parse_predicate(range)
- })
- .collect();
-
- let predicates = try!(predicates);
-
- if predicates.len() == 0 {
- return Err(String::from("VersionReq did not parse properly"));
- }
-
- Ok(VersionReq {
- predicates: predicates,
- })
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use range;
- use version::Identifier;
-
- #[test]
- fn test_parsing_default() {
- let r = range::parse("1.0.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 1,
- minor: Some(0),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_exact_01() {
- let r = range::parse("=1.0.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Ex,
- major: 1,
- minor: Some(0),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_exact_02() {
- let r = range::parse("=0.9.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Ex,
- major: 0,
- minor: Some(9),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_exact_03() {
- let r = range::parse("=0.1.0-beta2.a").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Ex,
- major: 0,
- minor: Some(1),
- patch: Some(0),
- pre: vec![Identifier::AlphaNumeric(String::from("beta2")),
- Identifier::AlphaNumeric(String::from("a"))],
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_greater_than() {
- let r = range::parse("> 1.0.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Gt,
- major: 1,
- minor: Some(0),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_greater_than_01() {
- let r = range::parse(">= 1.0.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::GtEq,
- major: 1,
- minor: Some(0),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_greater_than_02() {
- let r = range::parse(">= 2.1.0-alpha2").unwrap();
-
- assert_eq!(Predicate {
- op: Op::GtEq,
- major: 2,
- minor: Some(1),
- patch: Some(0),
- pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))],
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_less_than() {
- let r = range::parse("< 1.0.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Lt,
- major: 1,
- minor: Some(0),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_less_than_eq() {
- let r = range::parse("<= 2.1.0-alpha2").unwrap();
-
- assert_eq!(Predicate {
- op: Op::LtEq,
- major: 2,
- minor: Some(1),
- patch: Some(0),
- pre: vec![Identifier::AlphaNumeric(String::from("alpha2"))],
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_tilde() {
- let r = range::parse("~1").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Tilde,
- major: 1,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_parsing_compatible() {
- let r = range::parse("^0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_blank() {
- let r = range::parse("").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Major),
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_wildcard() {
- let r = range::parse("*").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Major),
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_x() {
- let r = range::parse("x").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Major),
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_capital_x() {
- let r = range::parse("X").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Major),
- major: 0,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_minor_wildcard_star() {
- let r = range::parse("1.*").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Minor),
- major: 1,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_minor_wildcard_x() {
- let r = range::parse("1.x").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Minor),
- major: 1,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_minor_wildcard_capital_x() {
- let r = range::parse("1.X").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Minor),
- major: 1,
- minor: None,
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_patch_wildcard_star() {
- let r = range::parse("1.2.*").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Patch),
- major: 1,
- minor: Some(2),
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_patch_wildcard_x() {
- let r = range::parse("1.2.x").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Patch),
- major: 1,
- minor: Some(2),
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- fn test_parsing_patch_wildcard_capital_x() {
- let r = range::parse("1.2.X").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Wildcard(WildcardVersion::Patch),
- major: 1,
- minor: Some(2),
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[0]
- );
- }
-
- #[test]
- pub fn test_multiple_01() {
- let r = range::parse("> 0.0.9, <= 2.5.3").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Gt,
- major: 0,
- minor: Some(0),
- patch: Some(9),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
-
- assert_eq!(Predicate {
- op: Op::LtEq,
- major: 2,
- minor: Some(5),
- patch: Some(3),
- pre: Vec::new(),
- },
- r.predicates[1]
- );
- }
-
- #[test]
- pub fn test_multiple_02() {
- let r = range::parse("0.3.0, 0.4.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: Some(3),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: Some(4),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[1]
- );
- }
-
- #[test]
- pub fn test_multiple_03() {
- let r = range::parse("<= 0.2.0, >= 0.5.0").unwrap();
-
- assert_eq!(Predicate {
- op: Op::LtEq,
- major: 0,
- minor: Some(2),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
-
- assert_eq!(Predicate {
- op: Op::GtEq,
- major: 0,
- minor: Some(5),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[1]
- );
- }
-
- #[test]
- pub fn test_multiple_04() {
- let r = range::parse("0.1.0, 0.1.4, 0.1.6").unwrap();
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: Some(1),
- patch: Some(0),
- pre: Vec::new(),
- },
- r.predicates[0]
- );
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: Some(1),
- patch: Some(4),
- pre: Vec::new(),
- },
- r.predicates[1]
- );
-
- assert_eq!(Predicate {
- op: Op::Compatible,
- major: 0,
- minor: Some(1),
- patch: Some(6),
- pre: Vec::new(),
- },
- r.predicates[2]
- );
- }
-
- #[test]
- pub fn test_multiple_05() {
- let r = range::parse(">=0.5.1-alpha3, <0.6").unwrap();
-
- assert_eq!(Predicate {
- op: Op::GtEq,
- major: 0,
- minor: Some(5),
- patch: Some(1),
- pre: vec![Identifier::AlphaNumeric(String::from("alpha3"))],
- },
- r.predicates[0]
- );
-
- assert_eq!(Predicate {
- op: Op::Lt,
- major: 0,
- minor: Some(6),
- patch: None,
- pre: Vec::new(),
- },
- r.predicates[1]
- );
- }
-
- #[test]
- fn test_parse_build_metadata_with_predicate() {
- assert_eq!(range::parse("^1.2.3+meta").unwrap().predicates[0].op,
- Op::Compatible);
- assert_eq!(range::parse("~1.2.3+meta").unwrap().predicates[0].op,
- Op::Tilde);
- assert_eq!(range::parse("=1.2.3+meta").unwrap().predicates[0].op,
- Op::Ex);
- assert_eq!(range::parse("<=1.2.3+meta").unwrap().predicates[0].op,
- Op::LtEq);
- assert_eq!(range::parse(">=1.2.3+meta").unwrap().predicates[0].op,
- Op::GtEq);
- assert_eq!(range::parse("<1.2.3+meta").unwrap().predicates[0].op,
- Op::Lt);
- assert_eq!(range::parse(">1.2.3+meta").unwrap().predicates[0].op,
- Op::Gt);
- }
-
- #[test]
- pub fn test_parse_errors() {
- assert!(range::parse("\0").is_err());
- assert!(range::parse(">= >= 0.0.2").is_err());
- assert!(range::parse(">== 0.0.2").is_err());
- assert!(range::parse("a.0.0").is_err());
- assert!(range::parse("1.0.0-").is_err());
- assert!(range::parse(">=").is_err());
- assert!(range::parse("> 0.1.0,").is_err());
- assert!(range::parse("> 0.3.0, ,").is_err());
- }
-
- #[test]
- pub fn test_large_major_version() {
- assert!(range::parse("18446744073709551617.0.0").is_err());
- }
-
- #[test]
- pub fn test_large_minor_version() {
- assert!(range::parse("0.18446744073709551617.0").is_err());
- }
-
- #[test]
- pub fn test_large_patch_version() {
- assert!(range::parse("0.0.18446744073709551617").is_err());
- }
-}
diff --git a/third_party/rust/semver-parser/src/recognize.rs b/third_party/rust/semver-parser/src/recognize.rs
deleted file mode 100644
--- a/third_party/rust/semver-parser/src/recognize.rs
+++ /dev/null
@@ -1,154 +0,0 @@
-// Copyright 2017 Google Inc. All rights reserved.
-//
-// Licensed under either of MIT or Apache License, Version 2.0,
-// at your option.
-//
-// Use of this source code is governed by a MIT-style
-// license that can be found in the LICENSE file or at
-// https://opensource.org/licenses/MIT.
-//
-// 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.
-
-//! Simple recognizer combinators.
-
-// This version is similar to a similar one in the "lang" module of
-// xi-editor, but is stripped down to only the needed combinators.
-
-use std::ops;
-
-pub trait Recognize {
- fn p(&self, s: &[u8]) -> Option<usize>;
-}
-
-impl<F: Fn(&[u8]) -> Option<usize>> Recognize for F {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- self(s)
- }
-}
-
-pub struct OneByte<F>(pub F);
-
-impl<F: Fn(u8) -> bool> Recognize for OneByte<F> {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- if s.is_empty() || !self.0(s[0]) {
- None
- } else {
- Some(1)
- }
- }
-}
-
-impl Recognize for u8 {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- OneByte(|b| b == *self).p(s)
- }
-}
-
-/// Use Inclusive(a..b) to indicate an inclusive range. When a...b syntax becomes
-/// stable, we can get rid of this and switch to that.
-pub struct Inclusive<T>(pub T);
-
-impl Recognize for Inclusive<ops::Range<u8>> {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- OneByte(|x| x >= self.0.start && x <= self.0.end).p(s)
- }
-}
-
-impl<'a> Recognize for &'a [u8] {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- let len = self.len();
- if s.len() >= len && &s[..len] == *self {
- Some(len)
- } else {
- None
- }
- }
-}
-
-impl<'a> Recognize for &'a str {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- self.as_bytes().p(s)
- }
-}
-
-impl<P1: Recognize, P2: Recognize> Recognize for (P1, P2) {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- self.0.p(s).and_then(|len1|
- self.1.p(&s[len1..]).map(|len2|
- len1 + len2))
- }
-}
-
-/// Choice from two heterogeneous alternatives.
-pub struct Alt<P1, P2>(pub P1, pub P2);
-
-impl<P1: Recognize, P2: Recognize> Recognize for Alt<P1, P2> {
- #[inline(always)]
- fn p(&self, s: &[u8]) -> Option<usize> {
- self.0.p(s).or_else(|| self.1.p(s))
- }
-}
-
-/// Choice from a homogenous slice of parsers.
-pub struct OneOf<'a, P: 'a>(pub &'a [P]);
-
-impl<'a, P: Recognize> Recognize for OneOf<'a, P> {
- #[inline]
- fn p(&self, s: &[u8]) -> Option<usize> {
- for ref p in self.0 {
- if let Some(len) = p.p(s) {
- return Some(len);
- }
- }
- None
- }
-}
-
-pub struct OneOrMore<P>(pub P);
-
-impl<P: Recognize> Recognize for OneOrMore<P> {
- #[inline]
- fn p(&self, s: &[u8]) -> Option<usize> {
- let mut i = 0;
- let mut count = 0;
- while let Some(len) = self.0.p(&s[i..]) {
- i += len;
- count += 1;
- }
- if count >= 1 {
- Some(i)
- } else {
- None
- }
- }
-}
-
-pub struct ZeroOrMore<P>(pub P);
-
-impl<P: Recognize> Recognize for ZeroOrMore<P> {
- #[inline]
- fn p(&self, s: &[u8]) -> Option<usize> {
- let mut i = 0;
- while let Some(len) = self.0.p(&s[i..]) {
- i += len;
- }
- Some(i)
- }
-}
diff --git a/third_party/rust/semver-parser/src/version.rs b/third_party/rust/semver-parser/src/version.rs
deleted file mode 100644
--- a/third_party/rust/semver-parser/src/version.rs
+++ /dev/null
@@ -1,365 +0,0 @@
-use std::fmt;
-use std::str::from_utf8;
-
-use recognize::*;
-
-use common::{self, numeric_identifier};
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Version {
- pub major: u64,
- pub minor: u64,
- pub patch: u64,
- pub pre: Vec<Identifier>,
- pub build: Vec<Identifier>,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum Identifier {
- /// An identifier that's solely numbers.
- Numeric(u64),
- /// An identifier with letters and numbers.
- AlphaNumeric(String),
-}
-
-pub fn parse(version: &str) -> Result<Version, String> {
- let s = version.trim().as_bytes();
- let mut i = 0;
- let major = if let Some((major, len)) = numeric_identifier(&s[i..]) {
- i += len;
- major
- } else {
- return Err("Error parsing major identifier".to_string());
- };
- if let Some(len) = b'.'.p(&s[i..]) {
- i += len;
- } else {
- return Err("Expected dot".to_string());
- }
- let minor = if let Some((minor, len)) = numeric_identifier(&s[i..]) {
- i += len;
- minor
- } else {
- return Err("Error parsing minor identifier".to_string());
- };
- if let Some(len) = b'.'.p(&s[i..]) {
- i += len;
- } else {
- return Err("Expected dot".to_string());
- }
- let patch = if let Some((patch, len)) = numeric_identifier(&s[i..]) {
- i += len;
- patch
- } else {
- return Err("Error parsing patch identifier".to_string());
- };
- let (pre, pre_len) = common::parse_optional_meta(&s[i..], b'-')?;
- i += pre_len;
- let (build, build_len) = common::parse_optional_meta(&s[i..], b'+')?;
- i += build_len;
- if i != s.len() {
- return Err("Extra junk after valid version: ".to_string() +
- from_utf8(&s[i..]).unwrap());
- }
- Ok(Version {
- major: major,
- minor: minor,
- patch: patch,
- pre: pre,
- build: build,
- })
-}
-
-impl fmt::Display for Version {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, "{}.{}.{}", self.major, self.minor, self.patch));
- if !self.pre.is_empty() {
- let strs: Vec<_> =
- self.pre.iter().map(ToString::to_string).collect();
- try!(write!(f, "-{}", strs.join(".")));
- }
- if !self.build.is_empty() {
- let strs: Vec<_> =
- self.build.iter().map(ToString::to_string).collect();
- try!(write!(f, "+{}", strs.join(".")));
- }
- Ok(())
- }
-}
-
-impl fmt::Display for Identifier {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Identifier::Numeric(ref id) => id.fmt(f),
- Identifier::AlphaNumeric(ref id) => id.fmt(f),
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use version;
- use super::*;
-
- #[test]
- fn parse_empty() {
- let version = "";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "empty string incorrectly considered a valid parse");
- }
-
- #[test]
- fn parse_blank() {
- let version = " ";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "blank string incorrectly considered a valid parse");
- }
-
- #[test]
- fn parse_no_minor_patch() {
- let version = "1";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
- }
-
- #[test]
- fn parse_no_patch() {
- let version = "1.2";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
- }
-
- #[test]
- fn parse_empty_pre() {
- let version = "1.2.3-";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
- }
-
- #[test]
- fn parse_letters() {
- let version = "a.b.c";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
- }
-
- #[test]
- fn parse_with_letters() {
- let version = "1.2.3 a.b.c";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), format!("'{}' incorrectly considered a valid parse", version));
- }
-
- #[test]
- fn parse_basic_version() {
- let version = "1.2.3";
-
- let parsed = version::parse(version).unwrap();
-
- assert_eq!(1, parsed.major);
- assert_eq!(2, parsed.minor);
- assert_eq!(3, parsed.patch);
- }
-
- #[test]
- fn parse_trims_input() {
- let version = " 1.2.3 ";
-
- let parsed = version::parse(version).unwrap();
-
- assert_eq!(1, parsed.major);
- assert_eq!(2, parsed.minor);
- assert_eq!(3, parsed.patch);
- }
-
- #[test]
- fn parse_no_major_leading_zeroes() {
- let version = "01.0.0";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "01 incorrectly considered a valid major version");
- }
-
- #[test]
- fn parse_no_minor_leading_zeroes() {
- let version = "0.01.0";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "01 incorrectly considered a valid minor version");
- }
-
- #[test]
- fn parse_no_patch_leading_zeroes() {
- let version = "0.0.01";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "01 incorrectly considered a valid patch version");
- }
-
- #[test]
- fn parse_no_major_overflow() {
- let version = "98765432109876543210.0.0";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid major version");
- }
-
- #[test]
- fn parse_no_minor_overflow() {
- let version = "0.98765432109876543210.0";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid minor version");
- }
-
- #[test]
- fn parse_no_patch_overflow() {
- let version = "0.0.98765432109876543210";
-
- let parsed = version::parse(version);
-
- assert!(parsed.is_err(), "98765432109876543210 incorrectly considered a valid patch version");
- }
-
- #[test]
- fn parse_basic_prerelease() {
- let version = "1.2.3-pre";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre"))];
- assert_eq!(expected_pre, parsed.pre);
- }
-
- #[test]
- fn parse_prerelease_alphanumeric() {
- let version = "1.2.3-alpha1";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))];
- assert_eq!(expected_pre, parsed.pre);
- }
-
- #[test]
- fn parse_prerelease_zero() {
- let version = "1.2.3-pre.0";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("pre")),
- Identifier::Numeric(0)];
- assert_eq!(expected_pre, parsed.pre);
- }
-
- #[test]
- fn parse_basic_build() {
- let version = "1.2.3+build";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("build"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_build_alphanumeric() {
- let version = "1.2.3+build5";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_pre_and_build() {
- let version = "1.2.3-alpha1+build5";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("alpha1"))];
- assert_eq!(expected_pre, parsed.pre);
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("build5"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_complex_metadata_01() {
- let version = "1.2.3-1.alpha1.9+build5.7.3aedf ";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::Numeric(1),
- Identifier::AlphaNumeric(String::from("alpha1")),
- Identifier::Numeric(9)];
- assert_eq!(expected_pre, parsed.pre);
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("build5")),
- Identifier::Numeric(7),
- Identifier::AlphaNumeric(String::from("3aedf"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_complex_metadata_02() {
- let version = "0.4.0-beta.1+0851523";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")),
- Identifier::Numeric(1)];
- assert_eq!(expected_pre, parsed.pre);
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("0851523"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_metadata_overflow() {
- let version = "0.4.0-beta.1+98765432109876543210";
-
- let parsed = version::parse(version).unwrap();
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("beta")),
- Identifier::Numeric(1)];
- assert_eq!(expected_pre, parsed.pre);
-
- let expected_build = vec![Identifier::AlphaNumeric(String::from("98765432109876543210"))];
- assert_eq!(expected_build, parsed.build);
- }
-
- #[test]
- fn parse_regression_01() {
- let version = "0.0.0-WIP";
-
- let parsed = version::parse(version).unwrap();
-
- assert_eq!(0, parsed.major);
- assert_eq!(0, parsed.minor);
- assert_eq!(0, parsed.patch);
-
- let expected_pre = vec![Identifier::AlphaNumeric(String::from("WIP"))];
- assert_eq!(expected_pre, parsed.pre);
- }
-}
diff --git a/third_party/rust/semver/.cargo-checksum.json b/third_party/rust/semver/.cargo-checksum.json
--- a/third_party/rust/semver/.cargo-checksum.json
+++ b/third_party/rust/semver/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"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
+{"files":{"Cargo.toml":"2a2126f8fe5d20540ae6cfbf6649ed3af365ffb9a0a788a7552a6e7649a7a75f","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"23f18e03dc49df91622fe2a76176497404e46ced8a715d9d2b67a7446571cca3","README.md":"57659341319915482c0b83779fb7f3f0f3accb7a8b881965799116afb5e9f7e9","benches/parse.rs":"6531f66f80ce2fc83878f9bf84f94c42e96f1e709466f2b88be8d95a3cec1511","build.rs":"47b42941210d44567c8561107420d7825aa1d01332c2d2f8892d9e20646a1c77","src/backport.rs":"f8866548840434c8974f135528693f25aacc4ad03639c4e3aea3be351e13fdf8","src/display.rs":"9ba42f7a6579aa9c7dd72f2380036f5c9664592f3eacd09ea25cef291a3e64e5","src/error.rs":"3bb489f4a29f38d93370e64ae8d6e4e9b451a055cd7d392b6aeacab7eb3e1953","src/eval.rs":"b7e7ec976051b9f87ddf5cfdbaad64654d98d86ae0763f7d88b14eeaeac6013c","src/identifier.rs":"601231351ac58602b7d193cb0951b5146bd868b62aba938d5cbe52cf2b93414b","src/impls.rs":"79b5a2ac6ca3d4cb46adfb1494756079f53bef780dd81c3a8d3adf86f91395c8","src/lib.rs":"8e116a19e521909f3fa50206c078f1e23bf033dc8057ba6101f80d5bc5900fed","src/parse.rs":"93593f62cdae489feb4f2e8ae1fa93d90dca63db50669b6265346ffaaf687be5","src/serde.rs":"970d343a6bac21ddd965168d3cc2af9998796bf29bf545e8b37c6bcdd97d9710","tests/node/mod.rs":"2710d9b8daace2038b66db0f8f4cc522dee938e7cbc42d7739c31995343c32f4","tests/test_autotrait.rs":"070500c32ceee14a8a0110c04a01f98278b24614a0aec8c382dcea3da0343f58","tests/test_identifier.rs":"6c3da46c73df210527b60f1069131b15e2c65eb7b5d11793940d00cf66812f4d","tests/test_version.rs":"09e37c3df162205acf3683d1c760a6001e34e1c709fd4a1a265d82450e340003","tests/test_version_req.rs":"b6eea0258cc3b6d567a9f6c42693a97316345083495236c47e85374fd45f7cf0","tests/util/mod.rs":"db61c2cd86af864d8be4f2a3d5f25c86d7712201cc6ab47b715facf5f7f275b7"},"package":"8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"}
\ No newline at end of file
diff --git a/third_party/rust/semver/Cargo.toml b/third_party/rust/semver/Cargo.toml
--- a/third_party/rust/semver/Cargo.toml
+++ b/third_party/rust/semver/Cargo.toml
@@ -1,45 +1,38 @@
# 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
+# 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)
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
[package]
+edition = "2018"
+rust-version = "1.31"
name = "semver"
-version = "0.9.0"
-authors = ["Steve Klabnik <steve@steveklabnik.com>", "The Rust Project Developers"]
-description = "Semantic version parsing and comparison.\n"
-homepage = "https://docs.rs/crate/semver/"
-documentation = "https://docs.rs/crate/semver/"
+version = "1.0.9"
+authors = ["David Tolnay <dtolnay@gmail.com>"]
+description = "Parser and evaluator for Cargo's flavor of Semantic Versioning"
+documentation = "https://docs.rs/semver"
readme = "README.md"
-license = "MIT/Apache-2.0"
-repository = "https://github.com/steveklabnik/semver"
-[dependencies.semver-parser]
-version = "0.7.0"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/dtolnay/semver"
+
+[package.metadata.docs.rs]
+targets = ["x86_64-unknown-linux-gnu"]
+rustdoc-args = [
+ "--cfg",
+ "doc_cfg",
+]
[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"
+default-features = false
[features]
-default = []
-ci = ["serde"]
-[badges.travis-ci]
-repository = "steveklabnik/semver"
+default = ["std"]
+std = []
diff --git a/third_party/rust/semver/LICENSE-MIT b/third_party/rust/semver/LICENSE-MIT
--- a/third_party/rust/semver/LICENSE-MIT
+++ b/third_party/rust/semver/LICENSE-MIT
@@ -1,10 +1,8 @@
-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
diff --git a/third_party/rust/semver/README.md b/third_party/rust/semver/README.md
--- a/third_party/rust/semver/README.md
+++ b/third_party/rust/semver/README.md
@@ -1,103 +1,84 @@
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.
+[<img alt="github" src="https://img.shields.io/badge/github-dtolnay/semver-8da0cb?style=for-the-badge&labelColor=555555&logo=github" height="20">](https://github.com/dtolnay/semver)
+[<img alt="crates.io" src="https://img.shields.io/crates/v/semver.svg?style=for-the-badge&color=fc8d62&logo=rust" height="20">](https://crates.io/crates/semver)
+[<img alt="docs.rs" src="https://img.shields.io/badge/docs.rs-semver-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K" height="20">](https://docs.rs/semver)
+[<img alt="build status" src="https://img.shields.io/github/workflow/status/dtolnay/semver/CI/master?style=for-the-badge" height="20">](https://github.com/dtolnay/semver/actions?query=branch%3Amaster)
-## SemVer and the Rust ecosystem
-
-Rust itself follows the SemVer specification, as does its standard libraries. The two are
-not tied together.
+A parser and evaluator for Cargo's flavor of Semantic Versioning.
-[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:
+Semantic Versioning (see <https://semver.org>) is a guideline for how version
+numbers are assigned and incremented. It is widely followed within the
+Cargo/crates.io ecosystem for Rust.
```toml
-semver = "0.7.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!(),
-}));
+[dependencies]
+semver = "1.0"
```
-If you have multiple `Version`s, you can use the usual comparison operators to compare them:
-
-```rust
-use semver::Version;
+*Compiler support: requires rustc 1.31+*
-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
+<br>
-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:
+## Example
```rust
-use semver::Version;
-use semver::VersionReq;
+use semver::{BuildMetadata, Prerelease, Version, VersionReq};
+
+fn main() {
+ let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap();
-let r = VersionReq::parse(">= 1.0.0").unwrap();
-let v = Version::parse("1.0.0").unwrap();
+ // Check whether this requirement matches version 1.2.3-alpha.1 (no)
+ let version = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: Prerelease::new("alpha.1").unwrap(),
+ build: BuildMetadata::EMPTY,
+ };
+ assert!(!req.matches(&version));
-assert!(r.to_string() == ">= 1.0.0".to_string());
-assert!(r.matches(&v))
+ // Check whether it matches 1.3.0 (yes it does)
+ let version = Version::parse("1.3.0").unwrap();
+ assert!(req.matches(&version));
+}
```
-It also allows parsing of `~x.y.z` and `^x.y.z` requirements as defined at
-https://www.npmjs.org/doc/misc/semver.html
+<br>
+
+## Scope of this crate
-**Tilde requirements** specify a minimal version with some updates:
+Besides Cargo, several other package ecosystems and package managers for other
+languages also use SemVer: RubyGems/Bundler for Ruby, npm for JavaScript,
+Composer for PHP, CocoaPods for Objective-C...
-```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
-```
+The `semver` crate is specifically intended to implement Cargo's interpretation
+of Semantic Versioning.
+
+Where the various tools differ in their interpretation or implementation of the
+spec, this crate follows the implementation choices made by Cargo. If you are
+operating on version numbers from some other package ecosystem, you will want to
+use a different semver library which is appropriate to that ecosystem.
+
+The extent of Cargo's SemVer support is documented in the *[Specifying
+Dependencies]* chapter of the Cargo reference.
-**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.
+[Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
-`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.
+<br>
+
+#### License
-```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
-```
+<sup>
+Licensed under either of <a href="LICENSE-APACHE">Apache License, Version
+2.0</a> or <a href="LICENSE-MIT">MIT license</a> at your option.
+</sup>
+
+<br>
+
+<sub>
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in this crate by you, as defined in the Apache-2.0 license, shall
+be dual licensed as above, without any additional terms or conditions.
+</sub>
diff --git a/third_party/rust/semver/benches/parse.rs b/third_party/rust/semver/benches/parse.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/benches/parse.rs
@@ -0,0 +1,24 @@
+#![feature(test)]
+
+extern crate test;
+
+use semver::{Prerelease, Version, VersionReq};
+use test::{black_box, Bencher};
+
+#[bench]
+fn parse_prerelease(b: &mut Bencher) {
+ let text = "x.7.z.92";
+ b.iter(|| black_box(text).parse::<Prerelease>().unwrap());
+}
+
+#[bench]
+fn parse_version(b: &mut Bencher) {
+ let text = "1.0.2021-beta+exp.sha.5114f85";
+ b.iter(|| black_box(text).parse::<Version>().unwrap());
+}
+
+#[bench]
+fn parse_version_req(b: &mut Bencher) {
+ let text = ">=1.2.3, <2.0.0";
+ b.iter(|| black_box(text).parse::<VersionReq>().unwrap());
+}
diff --git a/third_party/rust/semver/build.rs b/third_party/rust/semver/build.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/build.rs
@@ -0,0 +1,73 @@
+use std::env;
+use std::process::Command;
+use std::str;
+
+fn main() {
+ let compiler = match rustc_minor_version() {
+ Some(compiler) => compiler,
+ None => return,
+ };
+
+ if compiler < 33 {
+ // Exhaustive integer patterns. On older compilers, a final `_` arm is
+ // required even if every possible integer value is otherwise covered.
+ // https://github.com/rust-lang/rust/issues/50907
+ println!("cargo:rustc-cfg=no_exhaustive_int_match");
+ }
+
+ if compiler < 36 {
+ // extern crate alloc.
+ // https://blog.rust-lang.org/2019/07/04/Rust-1.36.0.html#the-alloc-crate-is-stable
+ println!("cargo:rustc-cfg=no_alloc_crate");
+ }
+
+ if compiler < 39 {
+ // const Vec::new.
+ // https://doc.rust-lang.org/std/vec/struct.Vec.html#method.new
+ println!("cargo:rustc-cfg=no_const_vec_new");
+ }
+
+ if compiler < 40 {
+ // #[non_exhaustive].
+ // https://blog.rust-lang.org/2019/12/19/Rust-1.40.0.html#non_exhaustive-structs-enums-and-variants
+ println!("cargo:rustc-cfg=no_non_exhaustive");
+ }
+
+ if compiler < 45 {
+ // String::strip_prefix.
+ // https://doc.rust-lang.org/std/primitive.str.html#method.repeat
+ println!("cargo:rustc-cfg=no_str_strip_prefix");
+ }
+
+ if compiler < 46 {
+ // #[track_caller].
+ // https://blog.rust-lang.org/2020/08/27/Rust-1.46.0.html#track_caller
+ println!("cargo:rustc-cfg=no_track_caller");
+ }
+
+ if compiler < 52 {
+ // #![deny(unsafe_op_in_unsafe_fn)].
+ // https://github.com/rust-lang/rust/issues/71668
+ println!("cargo:rustc-cfg=no_unsafe_op_in_unsafe_fn_lint");
+ }
+
+ if compiler < 53 {
+ // Efficient intrinsics for count-leading-zeros and count-trailing-zeros
+ // on NonZero integers stabilized in 1.53.0. On many architectures these
+ // are more efficient than counting zeros on ordinary zeroable integers.
+ // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.leading_zeros
+ // https://doc.rust-lang.org/std/num/struct.NonZeroU64.html#method.trailing_zeros
+ println!("cargo:rustc-cfg=no_nonzero_bitscan");
+ }
+}
+
+fn rustc_minor_version() -> Option<u32> {
+ let rustc = env::var_os("RUSTC")?;
+ let output = Command::new(rustc).arg("--version").output().ok()?;
+ let version = str::from_utf8(&output.stdout).ok()?;
+ let mut pieces = version.split('.');
+ if pieces.next() != Some("rustc 1") {
+ return None;
+ }
+ pieces.next()?.parse().ok()
+}
diff --git a/third_party/rust/semver/src/backport.rs b/third_party/rust/semver/src/backport.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/backport.rs
@@ -0,0 +1,51 @@
+#[cfg(no_str_strip_prefix)] // rustc <1.45
+pub(crate) trait StripPrefixExt {
+ fn strip_prefix(&self, ch: char) -> Option<&str>;
+}
+
+#[cfg(no_str_strip_prefix)]
+impl StripPrefixExt for str {
+ fn strip_prefix(&self, ch: char) -> Option<&str> {
+ if self.starts_with(ch) {
+ Some(&self[ch.len_utf8()..])
+ } else {
+ None
+ }
+ }
+}
+
+pub(crate) use crate::alloc::vec::Vec;
+
+#[cfg(no_alloc_crate)] // rustc <1.36
+pub(crate) mod alloc {
+ pub use std::vec;
+
+ pub mod alloc {
+ use std::mem;
+
+ pub struct Layout {
+ size: usize,
+ }
+
+ impl Layout {
+ pub unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
+ assert_eq!(align, 2);
+ Layout { size }
+ }
+ }
+
+ pub unsafe fn alloc(layout: Layout) -> *mut u8 {
+ let len_u16 = (layout.size + 1) / 2;
+ let mut vec = Vec::new();
+ vec.reserve_exact(len_u16);
+ let ptr: *mut u16 = vec.as_mut_ptr();
+ mem::forget(vec);
+ ptr as *mut u8
+ }
+
+ pub unsafe fn dealloc(ptr: *mut u8, layout: Layout) {
+ let len_u16 = (layout.size + 1) / 2;
+ unsafe { Vec::from_raw_parts(ptr as *mut u16, 0, len_u16) };
+ }
+ }
+}
diff --git a/third_party/rust/semver/src/display.rs b/third_party/rust/semver/src/display.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/display.rs
@@ -0,0 +1,165 @@
+use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
+use core::fmt::{self, Alignment, Debug, Display, Write};
+
+impl Display for Version {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let do_display = |formatter: &mut fmt::Formatter| -> fmt::Result {
+ write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)?;
+ if !self.pre.is_empty() {
+ write!(formatter, "-{}", self.pre)?;
+ }
+ if !self.build.is_empty() {
+ write!(formatter, "+{}", self.build)?;
+ }
+ Ok(())
+ };
+
+ let do_len = || -> usize {
+ digits(self.major)
+ + 1
+ + digits(self.minor)
+ + 1
+ + digits(self.patch)
+ + !self.pre.is_empty() as usize
+ + self.pre.len()
+ + !self.build.is_empty() as usize
+ + self.build.len()
+ };
+
+ pad(formatter, do_display, do_len)
+ }
+}
+
+impl Display for VersionReq {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ if self.comparators.is_empty() {
+ return formatter.write_str("*");
+ }
+ for (i, comparator) in self.comparators.iter().enumerate() {
+ if i > 0 {
+ formatter.write_str(", ")?;
+ }
+ write!(formatter, "{}", comparator)?;
+ }
+ Ok(())
+ }
+}
+
+impl Display for Comparator {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let op = match self.op {
+ Op::Exact => "=",
+ Op::Greater => ">",
+ Op::GreaterEq => ">=",
+ Op::Less => "<",
+ Op::LessEq => "<=",
+ Op::Tilde => "~",
+ Op::Caret => "^",
+ Op::Wildcard => "",
+ #[cfg(no_non_exhaustive)]
+ Op::__NonExhaustive => unreachable!(),
+ };
+ formatter.write_str(op)?;
+ write!(formatter, "{}", self.major)?;
+ if let Some(minor) = &self.minor {
+ write!(formatter, ".{}", minor)?;
+ if let Some(patch) = &self.patch {
+ write!(formatter, ".{}", patch)?;
+ if !self.pre.is_empty() {
+ write!(formatter, "-{}", self.pre)?;
+ }
+ } else if self.op == Op::Wildcard {
+ formatter.write_str(".*")?;
+ }
+ } else if self.op == Op::Wildcard {
+ formatter.write_str(".*")?;
+ }
+ Ok(())
+ }
+}
+
+impl Display for Prerelease {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str(self.as_str())
+ }
+}
+
+impl Display for BuildMetadata {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str(self.as_str())
+ }
+}
+
+impl Debug for Version {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ let mut debug = formatter.debug_struct("Version");
+ debug
+ .field("major", &self.major)
+ .field("minor", &self.minor)
+ .field("patch", &self.patch);
+ if !self.pre.is_empty() {
+ debug.field("pre", &self.pre);
+ }
+ if !self.build.is_empty() {
+ debug.field("build", &self.build);
+ }
+ debug.finish()
+ }
+}
+
+impl Debug for Prerelease {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "Prerelease(\"{}\")", self)
+ }
+}
+
+impl Debug for BuildMetadata {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ write!(formatter, "BuildMetadata(\"{}\")", self)
+ }
+}
+
+fn pad(
+ formatter: &mut fmt::Formatter,
+ do_display: impl FnOnce(&mut fmt::Formatter) -> fmt::Result,
+ do_len: impl FnOnce() -> usize,
+) -> fmt::Result {
+ let min_width = match formatter.width() {
+ Some(min_width) => min_width,
+ None => return do_display(formatter),
+ };
+
+ let len = do_len();
+ if len >= min_width {
+ return do_display(formatter);
+ }
+
+ let default_align = Alignment::Left;
+ let align = formatter.align().unwrap_or(default_align);
+ let padding = min_width - len;
+ let (pre_pad, post_pad) = match align {
+ Alignment::Left => (0, padding),
+ Alignment::Right => (padding, 0),
+ Alignment::Center => (padding / 2, (padding + 1) / 2),
+ };
+
+ let fill = formatter.fill();
+ for _ in 0..pre_pad {
+ formatter.write_char(fill)?;
+ }
+
+ do_display(formatter)?;
+
+ for _ in 0..post_pad {
+ formatter.write_char(fill)?;
+ }
+ Ok(())
+}
+
+fn digits(val: u64) -> usize {
+ if val < 10 {
+ 1
+ } else {
+ 1 + digits(val / 10)
+ }
+}
diff --git a/third_party/rust/semver/src/error.rs b/third_party/rust/semver/src/error.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/error.rs
@@ -0,0 +1,124 @@
+use crate::parse::Error;
+use core::fmt::{self, Debug, Display};
+
+pub(crate) enum ErrorKind {
+ UnexpectedEnd(Position),
+ UnexpectedChar(Position, char),
+ UnexpectedCharAfter(Position, char),
+ ExpectedCommaFound(Position, char),
+ LeadingZero(Position),
+ Overflow(Position),
+ EmptySegment(Position),
+ IllegalCharacter(Position),
+ WildcardNotTheOnlyComparator(char),
+ UnexpectedAfterWildcard,
+ ExcessiveComparators,
+}
+
+#[derive(Copy, Clone, Eq, PartialEq)]
+pub(crate) enum Position {
+ Major,
+ Minor,
+ Patch,
+ Pre,
+ Build,
+}
+
+#[cfg(feature = "std")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
+impl std::error::Error for Error {}
+
+impl Display for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ match &self.kind {
+ ErrorKind::UnexpectedEnd(pos) => {
+ write!(formatter, "unexpected end of input while parsing {}", pos)
+ }
+ ErrorKind::UnexpectedChar(pos, ch) => {
+ write!(
+ formatter,
+ "unexpected character {} while parsing {}",
+ QuotedChar(*ch),
+ pos,
+ )
+ }
+ ErrorKind::UnexpectedCharAfter(pos, ch) => {
+ write!(
+ formatter,
+ "unexpected character {} after {}",
+ QuotedChar(*ch),
+ pos,
+ )
+ }
+ ErrorKind::ExpectedCommaFound(pos, ch) => {
+ write!(
+ formatter,
+ "expected comma after {}, found {}",
+ pos,
+ QuotedChar(*ch),
+ )
+ }
+ ErrorKind::LeadingZero(pos) => {
+ write!(formatter, "invalid leading zero in {}", pos)
+ }
+ ErrorKind::Overflow(pos) => {
+ write!(formatter, "value of {} exceeds u64::MAX", pos)
+ }
+ ErrorKind::EmptySegment(pos) => {
+ write!(formatter, "empty identifier segment in {}", pos)
+ }
+ ErrorKind::IllegalCharacter(pos) => {
+ write!(formatter, "unexpected character in {}", pos)
+ }
+ ErrorKind::WildcardNotTheOnlyComparator(ch) => {
+ write!(
+ formatter,
+ "wildcard req ({}) must be the only comparator in the version req",
+ ch,
+ )
+ }
+ ErrorKind::UnexpectedAfterWildcard => {
+ formatter.write_str("unexpected character after wildcard in version req")
+ }
+ ErrorKind::ExcessiveComparators => {
+ formatter.write_str("excessive number of version comparators")
+ }
+ }
+ }
+}
+
+impl Display for Position {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str(match self {
+ Position::Major => "major version number",
+ Position::Minor => "minor version number",
+ Position::Patch => "patch version number",
+ Position::Pre => "pre-release identifier",
+ Position::Build => "build metadata",
+ })
+ }
+}
+
+impl Debug for Error {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("Error(\"")?;
+ Display::fmt(self, formatter)?;
+ formatter.write_str("\")")?;
+ Ok(())
+ }
+}
+
+struct QuotedChar(char);
+
+impl Display for QuotedChar {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ // Standard library versions prior to https://github.com/rust-lang/rust/pull/95345
+ // print character 0 as '\u{0}'. We prefer '\0' to keep error messages
+ // the same across all supported Rust versions.
+ if self.0 == '\0' {
+ formatter.write_str("'\\0'")
+ } else {
+ write!(formatter, "{:?}", self.0)
+ }
+ }
+}
diff --git a/third_party/rust/semver/src/eval.rs b/third_party/rust/semver/src/eval.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/eval.rs
@@ -0,0 +1,181 @@
+use crate::{Comparator, Op, Version, VersionReq};
+
+pub(crate) fn matches_req(req: &VersionReq, ver: &Version) -> bool {
+ for cmp in &req.comparators {
+ if !matches_impl(cmp, ver) {
+ return false;
+ }
+ }
+
+ if ver.pre.is_empty() {
+ return true;
+ }
+
+ // If a version has a prerelease tag (for example, 1.2.3-alpha.3) then it
+ // will only be allowed to satisfy req if at least one comparator with the
+ // same major.minor.patch also has a prerelease tag.
+ for cmp in &req.comparators {
+ if pre_is_compatible(cmp, ver) {
+ return true;
+ }
+ }
+
+ false
+}
+
+pub(crate) fn matches_comparator(cmp: &Comparator, ver: &Version) -> bool {
+ matches_impl(cmp, ver) && (ver.pre.is_empty() || pre_is_compatible(cmp, ver))
+}
+
+fn matches_impl(cmp: &Comparator, ver: &Version) -> bool {
+ match cmp.op {
+ Op::Exact | Op::Wildcard => matches_exact(cmp, ver),
+ Op::Greater => matches_greater(cmp, ver),
+ Op::GreaterEq => matches_exact(cmp, ver) || matches_greater(cmp, ver),
+ Op::Less => matches_less(cmp, ver),
+ Op::LessEq => matches_exact(cmp, ver) || matches_less(cmp, ver),
+ Op::Tilde => matches_tilde(cmp, ver),
+ Op::Caret => matches_caret(cmp, ver),
+ #[cfg(no_non_exhaustive)]
+ Op::__NonExhaustive => unreachable!(),
+ }
+}
+
+fn matches_exact(cmp: &Comparator, ver: &Version) -> bool {
+ if ver.major != cmp.major {
+ return false;
+ }
+
+ if let Some(minor) = cmp.minor {
+ if ver.minor != minor {
+ return false;
+ }
+ }
+
+ if let Some(patch) = cmp.patch {
+ if ver.patch != patch {
+ return false;
+ }
+ }
+
+ ver.pre == cmp.pre
+}
+
+fn matches_greater(cmp: &Comparator, ver: &Version) -> bool {
+ if ver.major != cmp.major {
+ return ver.major > cmp.major;
+ }
+
+ match cmp.minor {
+ None => return false,
+ Some(minor) => {
+ if ver.minor != minor {
+ return ver.minor > minor;
+ }
+ }
+ }
+
+ match cmp.patch {
+ None => return false,
+ Some(patch) => {
+ if ver.patch != patch {
+ return ver.patch > patch;
+ }
+ }
+ }
+
+ ver.pre > cmp.pre
+}
+
+fn matches_less(cmp: &Comparator, ver: &Version) -> bool {
+ if ver.major != cmp.major {
+ return ver.major < cmp.major;
+ }
+
+ match cmp.minor {
+ None => return false,
+ Some(minor) => {
+ if ver.minor != minor {
+ return ver.minor < minor;
+ }
+ }
+ }
+
+ match cmp.patch {
+ None => return false,
+ Some(patch) => {
+ if ver.patch != patch {
+ return ver.patch < patch;
+ }
+ }
+ }
+
+ ver.pre < cmp.pre
+}
+
+fn matches_tilde(cmp: &Comparator, ver: &Version) -> bool {
+ if ver.major != cmp.major {
+ return false;
+ }
+
+ if let Some(minor) = cmp.minor {
+ if ver.minor != minor {
+ return false;
+ }
+ }
+
+ if let Some(patch) = cmp.patch {
+ if ver.patch != patch {
+ return ver.patch > patch;
+ }
+ }
+
+ ver.pre >= cmp.pre
+}
+
+fn matches_caret(cmp: &Comparator, ver: &Version) -> bool {
+ if ver.major != cmp.major {
+ return false;
+ }
+
+ let minor = match cmp.minor {
+ None => return true,
+ Some(minor) => minor,
+ };
+
+ let patch = match cmp.patch {
+ None => {
+ if cmp.major > 0 {
+ return ver.minor >= minor;
+ } else {
+ return ver.minor == minor;
+ }
+ }
+ Some(patch) => patch,
+ };
+
+ if cmp.major > 0 {
+ if ver.minor != minor {
+ return ver.minor > minor;
+ } else if ver.patch != patch {
+ return ver.patch > patch;
+ }
+ } else if minor > 0 {
+ if ver.minor != minor {
+ return false;
+ } else if ver.patch != patch {
+ return ver.patch > patch;
+ }
+ } else if ver.minor != minor || ver.patch != patch {
+ return false;
+ }
+
+ ver.pre >= cmp.pre
+}
+
+fn pre_is_compatible(cmp: &Comparator, ver: &Version) -> bool {
+ cmp.major == ver.major
+ && cmp.minor == Some(ver.minor)
+ && cmp.patch == Some(ver.patch)
+ && !cmp.pre.is_empty()
+}
diff --git a/third_party/rust/semver/src/identifier.rs b/third_party/rust/semver/src/identifier.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/identifier.rs
@@ -0,0 +1,400 @@
+// This module implements Identifier, a short-optimized string allowed to
+// contain only the ASCII characters hyphen, dot, 0-9, A-Z, a-z.
+//
+// As of mid-2021, the distribution of pre-release lengths on crates.io is:
+//
+// length count length count length count
+// 0 355929 11 81 24 2
+// 1 208 12 48 25 6
+// 2 236 13 55 26 10
+// 3 1909 14 25 27 4
+// 4 1284 15 15 28 1
+// 5 1742 16 35 30 1
+// 6 3440 17 9 31 5
+// 7 5624 18 6 32 1
+// 8 1321 19 12 36 2
+// 9 179 20 2 37 379
+// 10 65 23 11
+//
+// and the distribution of build metadata lengths is:
+//
+// length count length count length count
+// 0 364445 8 7725 18 1
+// 1 72 9 16 19 1
+// 2 7 10 85 20 1
+// 3 28 11 17 22 4
+// 4 9 12 10 26 1
+// 5 68 13 9 27 1
+// 6 73 14 10 40 5
+// 7 53 15 6
+//
+// Therefore it really behooves us to be able to use the entire 8 bytes of a
+// pointer for inline storage. For both pre-release and build metadata there are
+// vastly more strings with length exactly 8 bytes than the sum over all lengths
+// longer than 8 bytes.
+//
+// To differentiate the inline representation from the heap allocated long
+// representation, we'll allocate heap pointers with 2-byte alignment so that
+// they are guaranteed to have an unset least significant bit. Then in the repr
+// we store for pointers, we rotate a 1 into the most significant bit of the
+// most significant byte, which is never set for an ASCII byte.
+//
+// Inline repr:
+//
+// 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx
+//
+// Heap allocated repr:
+//
+// 1ppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp pppppppp 0
+// ^ most significant bit least significant bit of orig ptr, rotated out ^
+//
+// Since the most significant bit doubles as a sign bit for the similarly sized
+// signed integer type, the CPU has an efficient instruction for inspecting it,
+// meaning we can differentiate between an inline repr and a heap allocated repr
+// in one instruction. Effectively an inline repr always looks like a positive
+// i64 while a heap allocated repr always looks like a negative i64.
+//
+// For the inline repr, we store \0 padding on the end of the stored characters,
+// and thus the string length is readily determined efficiently by a cttz (count
+// trailing zeros) or bsf (bit scan forward) instruction.
+//
+// For the heap allocated repr, the length is encoded as a base-128 varint at
+// the head of the allocation.
+//
+// Empty strings are stored as an all-1 bit pattern, corresponding to -1i64.
+// Consequently the all-0 bit pattern is never a legal representation in any
+// repr, leaving it available as a niche for downstream code. For example this
+// allows size_of::<Version>() == size_of::<Option<Version>>().
+
+use crate::alloc::alloc::{alloc, dealloc, Layout};
+use core::mem;
+use core::num::{NonZeroU64, NonZeroUsize};
+use core::ptr::{self, NonNull};
+use core::slice;
+use core::str;
+
+const PTR_BYTES: usize = mem::size_of::<NonNull<u8>>();
+
+// If pointers are already 8 bytes or bigger, then 0. If pointers are smaller
+// than 8 bytes, then Identifier will contain a byte array to raise its size up
+// to 8 bytes total.
+const TAIL_BYTES: usize = 8 * (PTR_BYTES < 8) as usize - PTR_BYTES * (PTR_BYTES < 8) as usize;
+
+#[repr(C, align(8))]
+pub(crate) struct Identifier {
+ head: NonNull<u8>,
+ tail: [u8; TAIL_BYTES],
+}
+
+impl Identifier {
+ pub(crate) const fn empty() -> Self {
+ // This is a separate constant because unsafe function calls are not
+ // allowed in a const fn body, only in a const, until later rustc than
+ // what we support.
+ const HEAD: NonNull<u8> = unsafe { NonNull::new_unchecked(!0 as *mut u8) };
+
+ // `mov rax, -1`
+ Identifier {
+ head: HEAD,
+ tail: [!0; TAIL_BYTES],
+ }
+ }
+
+ // SAFETY: string must be ASCII and not contain \0 bytes.
+ pub(crate) unsafe fn new_unchecked(string: &str) -> Self {
+ let len = string.len();
+ match len as u64 {
+ 0 => Self::empty(),
+ 1..=8 => {
+ let mut bytes = [0u8; mem::size_of::<Identifier>()];
+ // SAFETY: string is big enough to read len bytes, bytes is big
+ // enough to write len bytes, and they do not overlap.
+ unsafe { ptr::copy_nonoverlapping(string.as_ptr(), bytes.as_mut_ptr(), len) };
+ // SAFETY: the head field is nonzero because the input string
+ // was at least 1 byte of ASCII and did not contain \0.
+ unsafe { mem::transmute::<[u8; mem::size_of::<Identifier>()], Identifier>(bytes) }
+ }
+ 9..=0xff_ffff_ffff_ffff => {
+ // SAFETY: len is in a range that does not contain 0.
+ let size = bytes_for_varint(unsafe { NonZeroUsize::new_unchecked(len) }) + len;
+ let align = 2;
+ // SAFETY: align is not zero, align is a power of two, and
+ // rounding size up to align does not overflow usize::MAX.
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
+ // SAFETY: layout's size is nonzero.
+ let ptr = unsafe { alloc(layout) };
+ let mut write = ptr;
+ let mut varint_remaining = len;
+ while varint_remaining > 0 {
+ // SAFETY: size is bytes_for_varint(len) bytes + len bytes.
+ // This is writing the first bytes_for_varint(len) bytes.
+ unsafe { ptr::write(write, varint_remaining as u8 | 0x80) };
+ varint_remaining >>= 7;
+ // SAFETY: still in bounds of the same allocation.
+ write = unsafe { write.add(1) };
+ }
+ // SAFETY: size is bytes_for_varint(len) bytes + len bytes. This
+ // is writing to the last len bytes.
+ unsafe { ptr::copy_nonoverlapping(string.as_ptr(), write, len) };
+ Identifier {
+ head: ptr_to_repr(ptr),
+ tail: [0; TAIL_BYTES],
+ }
+ }
+ 0x100_0000_0000_0000..=0xffff_ffff_ffff_ffff => {
+ unreachable!("please refrain from storing >64 petabytes of text in semver version");
+ }
+ #[cfg(no_exhaustive_int_match)] // rustc <1.33
+ _ => unreachable!(),
+ }
+ }
+
+ pub(crate) fn is_empty(&self) -> bool {
+ // `cmp rdi, -1` -- basically: `repr as i64 == -1`
+ let empty = Self::empty();
+ let is_empty = self.head == empty.head && self.tail == empty.tail;
+ // The empty representation does nothing on Drop. We can't let this one
+ // drop normally because `impl Drop for Identifier` calls is_empty; that
+ // would be an infinite recursion.
+ mem::forget(empty);
+ is_empty
+ }
+
+ fn is_inline(&self) -> bool {
+ // `test rdi, rdi` -- basically: `repr as i64 >= 0`
+ self.head.as_ptr() as usize >> (PTR_BYTES * 8 - 1) == 0
+ }
+
+ fn is_empty_or_inline(&self) -> bool {
+ // `cmp rdi, -2` -- basically: `repr as i64 > -2`
+ self.is_empty() || self.is_inline()
+ }
+
+ pub(crate) fn as_str(&self) -> &str {
+ if self.is_empty() {
+ ""
+ } else if self.is_inline() {
+ // SAFETY: repr is in the inline representation.
+ unsafe { inline_as_str(self) }
+ } else {
+ // SAFETY: repr is in the heap allocated representation.
+ unsafe { ptr_as_str(&self.head) }
+ }
+ }
+}
+
+impl Clone for Identifier {
+ fn clone(&self) -> Self {
+ if self.is_empty_or_inline() {
+ Identifier {
+ head: self.head,
+ tail: self.tail,
+ }
+ } else {
+ let ptr = repr_to_ptr(self.head);
+ // SAFETY: ptr is one of our own heap allocations.
+ let len = unsafe { decode_len(ptr) };
+ let size = bytes_for_varint(len) + len.get();
+ let align = 2;
+ // SAFETY: align is not zero, align is a power of two, and rounding
+ // size up to align does not overflow usize::MAX. This is just
+ // duplicating a previous allocation where all of these guarantees
+ // were already made.
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
+ // SAFETY: layout's size is nonzero.
+ let clone = unsafe { alloc(layout) };
+ // SAFETY: new allocation cannot overlap the previous one (this was
+ // not a realloc). The argument ptrs are readable/writeable
+ // respectively for size bytes.
+ unsafe { ptr::copy_nonoverlapping(ptr, clone, size) }
+ Identifier {
+ head: ptr_to_repr(clone),
+ tail: [0; TAIL_BYTES],
+ }
+ }
+ }
+}
+
+impl Drop for Identifier {
+ fn drop(&mut self) {
+ if self.is_empty_or_inline() {
+ return;
+ }
+ let ptr = repr_to_ptr_mut(self.head);
+ // SAFETY: ptr is one of our own heap allocations.
+ let len = unsafe { decode_len(ptr) };
+ let size = bytes_for_varint(len) + len.get();
+ let align = 2;
+ // SAFETY: align is not zero, align is a power of two, and rounding
+ // size up to align does not overflow usize::MAX. These guarantees were
+ // made when originally allocating this memory.
+ let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
+ // SAFETY: ptr was previously allocated by the same allocator with the
+ // same layout.
+ unsafe { dealloc(ptr, layout) }
+ }
+}
+
+impl PartialEq for Identifier {
+ fn eq(&self, rhs: &Self) -> bool {
+ if self.is_empty_or_inline() {
+ // Fast path (most common)
+ self.head == rhs.head && self.tail == rhs.tail
+ } else if rhs.is_empty_or_inline() {
+ false
+ } else {
+ // SAFETY: both reprs are in the heap allocated representation.
+ unsafe { ptr_as_str(&self.head) == ptr_as_str(&rhs.head) }
+ }
+ }
+}
+
+unsafe impl Send for Identifier {}
+unsafe impl Sync for Identifier {}
+
+// We use heap pointers that are 2-byte aligned, meaning they have an
+// insignificant 0 in the least significant bit. We take advantage of that
+// unneeded bit to rotate a 1 into the most significant bit to make the repr
+// distinguishable from ASCII bytes.
+fn ptr_to_repr(original: *mut u8) -> NonNull<u8> {
+ // `mov eax, 1`
+ // `shld rax, rdi, 63`
+ let modified = (original as usize | 1).rotate_right(1);
+
+ // `original + (modified - original)`, but being mindful of provenance.
+ let diff = modified.wrapping_sub(original as usize);
+ let modified = original.wrapping_add(diff);
+
+ // SAFETY: the most significant bit of repr is known to be set, so the value
+ // is not zero.
+ unsafe { NonNull::new_unchecked(modified) }
+}
+
+// Shift out the 1 previously placed into the most significant bit of the least
+// significant byte. Shift in a low 0 bit to reconstruct the original 2-byte
+// aligned pointer.
+fn repr_to_ptr(modified: NonNull<u8>) -> *const u8 {
+ // `lea rax, [rdi + rdi]`
+ let modified = modified.as_ptr();
+ let original = (modified as usize) << 1;
+
+ // `modified + (original - modified)`, but being mindful of provenance.
+ let diff = original.wrapping_sub(modified as usize);
+ modified.wrapping_add(diff)
+}
+
+fn repr_to_ptr_mut(repr: NonNull<u8>) -> *mut u8 {
+ repr_to_ptr(repr) as *mut u8
+}
+
+// Compute the length of the inline string, assuming the argument is in short
+// string representation. Short strings are stored as 1 to 8 nonzero ASCII
+// bytes, followed by \0 padding for the remaining bytes.
+//
+// SAFETY: the identifier must indeed be in the inline representation.
+unsafe fn inline_len(repr: &Identifier) -> NonZeroUsize {
+ // SAFETY: Identifier's layout is align(8) and at least size 8. We're doing
+ // an aligned read of the first 8 bytes from it. The bytes are not all zero
+ // because inline strings are at least 1 byte long and cannot contain \0.
+ let repr = unsafe { ptr::read(repr as *const Identifier as *const NonZeroU64) };
+
+ // Rustc >=1.53 has intrinsics for counting zeros on a non-zeroable integer.
+ // On many architectures these are more efficient than counting on ordinary
+ // zeroable integers (bsf vs cttz). On rustc <1.53 without those intrinsics,
+ // we count zeros in the u64 rather than the NonZeroU64.
+ #[cfg(no_nonzero_bitscan)]
+ let repr = repr.get();
+
+ #[cfg(target_endian = "little")]
+ let zero_bits_on_string_end = repr.leading_zeros();
+ #[cfg(target_endian = "big")]
+ let zero_bits_on_string_end = repr.trailing_zeros();
+
+ let nonzero_bytes = 8 - zero_bits_on_string_end as usize / 8;
+
+ // SAFETY: repr is nonzero, so it has at most 63 zero bits on either end,
+ // thus at least one nonzero byte.
+ unsafe { NonZeroUsize::new_unchecked(nonzero_bytes) }
+}
+
+// SAFETY: repr must be in the inline representation, i.e. at least 1 and at
+// most 8 nonzero ASCII bytes padded on the end with \0 bytes.
+unsafe fn inline_as_str(repr: &Identifier) -> &str {
+ let ptr = repr as *const Identifier as *const u8;
+ let len = unsafe { inline_len(repr) }.get();
+ // SAFETY: we are viewing the nonzero ASCII prefix of the inline repr's
+ // contents as a slice of bytes. Input/output lifetimes are correctly
+ // associated.
+ let slice = unsafe { slice::from_raw_parts(ptr, len) };
+ // SAFETY: the string contents are known to be only ASCII bytes, which are
+ // always valid UTF-8.
+ unsafe { str::from_utf8_unchecked(slice) }
+}
+
+// Decode varint. Varints consist of between one and eight base-128 digits, each
+// of which is stored in a byte with most significant bit set. Adjacent to the
+// varint in memory there is guaranteed to be at least 9 ASCII bytes, each of
+// which has an unset most significant bit.
+//
+// SAFETY: ptr must be one of our own heap allocations, with the varint header
+// already written.
+unsafe fn decode_len(ptr: *const u8) -> NonZeroUsize {
+ // SAFETY: There is at least one byte of varint followed by at least 9 bytes
+ // of string content, which is at least 10 bytes total for the allocation,
+ // so reading the first two is no problem.
+ let [first, second] = unsafe { ptr::read(ptr as *const [u8; 2]) };
+ if second < 0x80 {
+ // SAFETY: the length of this heap allocated string has been encoded as
+ // one base-128 digit, so the length is at least 9 and at most 127. It
+ // cannot be zero.
+ unsafe { NonZeroUsize::new_unchecked((first & 0x7f) as usize) }
+ } else {
+ return unsafe { decode_len_cold(ptr) };
+
+ // Identifiers 128 bytes or longer. This is not exercised by any crate
+ // version currently published to crates.io.
+ #[cold]
+ #[inline(never)]
+ unsafe fn decode_len_cold(mut ptr: *const u8) -> NonZeroUsize {
+ let mut len = 0;
+ let mut shift = 0;
+ loop {
+ // SAFETY: varint continues while there are bytes having the
+ // most significant bit set, i.e. until we start hitting the
+ // ASCII string content with msb unset.
+ let byte = unsafe { *ptr };
+ if byte < 0x80 {
+ // SAFETY: the string length is known to be 128 bytes or
+ // longer.
+ return unsafe { NonZeroUsize::new_unchecked(len) };
+ }
+ // SAFETY: still in bounds of the same allocation.
+ ptr = unsafe { ptr.add(1) };
+ len += ((byte & 0x7f) as usize) << shift;
+ shift += 7;
+ }
+ }
+ }
+}
+
+// SAFETY: repr must be in the heap allocated representation, with varint header
+// and string contents already written.
+unsafe fn ptr_as_str(repr: &NonNull<u8>) -> &str {
+ let ptr = repr_to_ptr(*repr);
+ let len = unsafe { decode_len(ptr) };
+ let header = bytes_for_varint(len);
+ let slice = unsafe { slice::from_raw_parts(ptr.add(header), len.get()) };
+ // SAFETY: all identifier contents are ASCII bytes, which are always valid
+ // UTF-8.
+ unsafe { str::from_utf8_unchecked(slice) }
+}
+
+// Number of base-128 digits required for the varint representation of a length.
+fn bytes_for_varint(len: NonZeroUsize) -> usize {
+ #[cfg(no_nonzero_bitscan)] // rustc <1.53
+ let len = len.get();
+
+ let usize_bits = mem::size_of::<usize>() * 8;
+ let len_bits = usize_bits - len.leading_zeros() as usize;
+ (len_bits + 6) / 7
+}
diff --git a/third_party/rust/semver/src/impls.rs b/third_party/rust/semver/src/impls.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/impls.rs
@@ -0,0 +1,156 @@
+use crate::backport::*;
+use crate::identifier::Identifier;
+use crate::{BuildMetadata, Comparator, Prerelease, VersionReq};
+use core::cmp::Ordering;
+use core::hash::{Hash, Hasher};
+use core::iter::FromIterator;
+use core::ops::Deref;
+
+impl Default for Identifier {
+ fn default() -> Self {
+ Identifier::empty()
+ }
+}
+
+impl Eq for Identifier {}
+
+impl Hash for Identifier {
+ fn hash<H: Hasher>(&self, hasher: &mut H) {
+ self.as_str().hash(hasher);
+ }
+}
+
+impl Deref for Prerelease {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ self.identifier.as_str()
+ }
+}
+
+impl Deref for BuildMetadata {
+ type Target = str;
+
+ fn deref(&self) -> &Self::Target {
+ self.identifier.as_str()
+ }
+}
+
+impl PartialOrd for Prerelease {
+ fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
+ Some(Ord::cmp(self, rhs))
+ }
+}
+
+impl PartialOrd for BuildMetadata {
+ fn partial_cmp(&self, rhs: &Self) -> Option<Ordering> {
+ Some(Ord::cmp(self, rhs))
+ }
+}
+
+impl Ord for Prerelease {
+ fn cmp(&self, rhs: &Self) -> Ordering {
+ match self.is_empty() {
+ true if rhs.is_empty() => return Ordering::Equal,
+ // A real release compares greater than prerelease.
+ true => return Ordering::Greater,
+ // Prerelease compares less than the real release.
+ false if rhs.is_empty() => return Ordering::Less,
+ false => {}
+ }
+
+ let lhs = self.as_str().split('.');
+ let mut rhs = rhs.as_str().split('.');
+
+ for lhs in lhs {
+ let rhs = match rhs.next() {
+ // Spec: "A larger set of pre-release fields has a higher
+ // precedence than a smaller set, if all of the preceding
+ // identifiers are equal."
+ None => return Ordering::Greater,
+ Some(rhs) => rhs,
+ };
+
+ let string_cmp = || Ord::cmp(lhs, rhs);
+ let is_ascii_digit = |b: u8| b.is_ascii_digit();
+ let ordering = match (
+ lhs.bytes().all(is_ascii_digit),
+ rhs.bytes().all(is_ascii_digit),
+ ) {
+ // Respect numeric ordering, for example 99 < 100. Spec says:
+ // "Identifiers consisting of only digits are compared
+ // numerically."
+ (true, true) => Ord::cmp(&lhs.len(), &rhs.len()).then_with(string_cmp),
+ // Spec: "Numeric identifiers always have lower precedence than
+ // non-numeric identifiers."
+ (true, false) => return Ordering::Less,
+ (false, true) => return Ordering::Greater,
+ // Spec: "Identifiers with letters or hyphens are compared
+ // lexically in ASCII sort order."
+ (false, false) => string_cmp(),
+ };
+
+ if ordering != Ordering::Equal {
+ return ordering;
+ }
+ }
+
+ if rhs.next().is_none() {
+ Ordering::Equal
+ } else {
+ Ordering::Less
+ }
+ }
+}
+
+impl Ord for BuildMetadata {
+ fn cmp(&self, rhs: &Self) -> Ordering {
+ let lhs = self.as_str().split('.');
+ let mut rhs = rhs.as_str().split('.');
+
+ for lhs in lhs {
+ let rhs = match rhs.next() {
+ None => return Ordering::Greater,
+ Some(rhs) => rhs,
+ };
+
+ let is_ascii_digit = |b: u8| b.is_ascii_digit();
+ let ordering = match (
+ lhs.bytes().all(is_ascii_digit),
+ rhs.bytes().all(is_ascii_digit),
+ ) {
+ (true, true) => {
+ // 0 < 00 < 1 < 01 < 001 < 2 < 02 < 002 < 10
+ let lhval = lhs.trim_start_matches('0');
+ let rhval = rhs.trim_start_matches('0');
+ Ord::cmp(&lhval.len(), &rhval.len())
+ .then_with(|| Ord::cmp(lhval, rhval))
+ .then_with(|| Ord::cmp(&lhs.len(), &rhs.len()))
+ }
+ (true, false) => return Ordering::Less,
+ (false, true) => return Ordering::Greater,
+ (false, false) => Ord::cmp(lhs, rhs),
+ };
+
+ if ordering != Ordering::Equal {
+ return ordering;
+ }
+ }
+
+ if rhs.next().is_none() {
+ Ordering::Equal
+ } else {
+ Ordering::Less
+ }
+ }
+}
+
+impl FromIterator<Comparator> for VersionReq {
+ fn from_iter<I>(iter: I) -> Self
+ where
+ I: IntoIterator<Item = Comparator>,
+ {
+ let comparators = Vec::from_iter(iter);
+ VersionReq { comparators }
+ }
+}
diff --git a/third_party/rust/semver/src/lib.rs b/third_party/rust/semver/src/lib.rs
--- a/third_party/rust/semver/src/lib.rs
+++ b/third_party/rust/semver/src/lib.rs
@@ -1,182 +1,533 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Semantic version parsing and comparison.
+//! [![github]](https://github.com/dtolnay/semver) [![crates-io]](https://crates.io/crates/semver) [![docs-rs]](https://docs.rs/semver)
//!
-//! Semantic versioning (see http://semver.org/) is a set of rules for
-//! assigning version numbers.
+//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
+//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
//!
-//! ## SemVer overview
-//!
-//! Given a version number MAJOR.MINOR.PATCH, increment the:
+//! <br>
//!
-//! 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).
+//! A parser and evaluator for Cargo's flavor of Semantic Versioning.
//!
-//! ## SemVer and the Rust ecosystem
-//!
-//! Rust itself follows the SemVer specification, as does its standard
-//! libraries. The two are not tied together.
+//! Semantic Versioning (see <https://semver.org>) is a guideline for how
+//! version numbers are assigned and incremented. It is widely followed within
+//! the Cargo/crates.io ecosystem for Rust.
//!
-//! [Cargo](http://crates.io), Rust's package manager, uses SemVer to determine
-//! which versions of packages you need installed.
+//! <br>
//!
-//! ## Versions
-//!
-//! At its simplest, the `semver` crate allows you to construct `Version`
-//! objects using the `parse` method:
+//! # Example
//!
-//! ```{rust}
-//! use semver::Version;
+//! ```
+//! use semver::{BuildMetadata, Prerelease, Version, VersionReq};
//!
-//! 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"));
-//! ```
+//! fn main() {
+//! let req = VersionReq::parse(">=1.2.3, <1.8.0").unwrap();
//!
-//! 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();
+//! // Check whether this requirement matches version 1.2.3-alpha.1 (no)
+//! let version = Version {
+//! major: 1,
+//! minor: 2,
+//! patch: 3,
+//! pre: Prerelease::new("alpha.1").unwrap(),
+//! build: BuildMetadata::EMPTY,
+//! };
+//! assert!(!req.matches(&version));
//!
-//! 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"));
+//! // Check whether it matches 1.3.0 (yes it does)
+//! let version = Version::parse("1.3.0").unwrap();
+//! assert!(req.matches(&version));
+//! }
//! ```
//!
-//! Similarly, when incrementing the major version number, the patch and minor
-//! numbers reset to zero (in accordance with section 8 of the spec)
+//! <br><br>
//!
-//! ```{rust}
-//! use semver::Version;
-//!
-//! let mut chrome_release = Version::parse("41.5.5377").unwrap();
-//! chrome_release.increment_major();
+//! # Scope of this crate
//!
-//! 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:
+//! Besides Cargo, several other package ecosystems and package managers for
+//! other languages also use SemVer: RubyGems/Bundler for Ruby, npm for
+//! JavaScript, Composer for PHP, CocoaPods for Objective-C...
//!
-//! ```{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();
+//! The `semver` crate is specifically intended to implement Cargo's
+//! interpretation of Semantic Versioning.
//!
-//! 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
+//! Where the various tools differ in their interpretation or implementation of
+//! the spec, this crate follows the implementation choices made by Cargo. If
+//! you are operating on version numbers from some other package ecosystem, you
+//! will want to use a different semver library which is appropriate to that
+//! ecosystem.
//!
-//! **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
-//! ```
+//! The extent of Cargo's SemVer support is documented in the *[Specifying
+//! Dependencies]* chapter of the Cargo reference.
//!
-//! **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
-//! ```
+//! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
+
+#![doc(html_root_url = "https://docs.rs/semver/1.0.9")]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
+#![cfg_attr(all(not(feature = "std"), not(no_alloc_crate)), no_std)]
+#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
+#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
+#![cfg_attr(no_str_strip_prefix, allow(unstable_name_collisions))]
+#![allow(
+ clippy::cast_lossless,
+ clippy::cast_possible_truncation,
+ clippy::doc_markdown,
+ clippy::items_after_statements,
+ clippy::manual_map,
+ clippy::match_bool,
+ clippy::missing_errors_doc,
+ clippy::must_use_candidate,
+ clippy::needless_doctest_main,
+ clippy::option_if_let_else,
+ clippy::ptr_as_ptr,
+ clippy::redundant_else,
+ clippy::semicolon_if_nothing_returned, // https://github.com/rust-lang/rust-clippy/issues/7324
+ clippy::similar_names,
+ clippy::unnested_or_patterns,
+ clippy::unseparated_literal_suffix,
+ clippy::wildcard_imports
+)]
+
+#[cfg(not(no_alloc_crate))]
+extern crate alloc;
+
+mod backport;
+mod display;
+mod error;
+mod eval;
+mod identifier;
+mod impls;
+mod parse;
+
+#[cfg(feature = "serde")]
+mod serde;
+
+use crate::alloc::vec::Vec;
+use crate::identifier::Identifier;
+use core::str::FromStr;
+
+#[allow(unused_imports)]
+use crate::backport::*;
+
+pub use crate::parse::Error;
+
+/// **SemVer version** as defined by <https://semver.org>.
+///
+/// # Syntax
+///
+/// - The major, minor, and patch numbers may be any integer 0 through u64::MAX.
+/// When representing a SemVer version as a string, each number is written as
+/// a base 10 integer. For example, `1.0.119`.
+///
+/// - Leading zeros are forbidden in those positions. For example `1.01.00` is
+/// invalid as a SemVer version.
+///
+/// - The pre-release identifier, if present, must conform to the syntax
+/// documented for [`Prerelease`].
+///
+/// - The build metadata, if present, must conform to the syntax documented for
+/// [`BuildMetadata`].
+///
+/// - Whitespace is not allowed anywhere in the version.
+///
+/// # Total ordering
+///
+/// Given any two SemVer versions, one is less than, greater than, or equal to
+/// the other. Versions may be compared against one another using Rust's usual
+/// comparison operators.
+///
+/// - The major, minor, and patch number are compared numerically from left to
+/// right, lexicographically ordered as a 3-tuple of integers. So for example
+/// version `1.5.0` is less than version `1.19.0`, despite the fact that
+/// "1.19.0" < "1.5.0" as ASCIIbetically compared strings and 1.19 < 1.5
+/// as real numbers.
+///
+/// - When major, minor, and patch are equal, a pre-release version is
+/// considered less than the ordinary release: version `1.0.0-alpha.1` is
+/// less than version `1.0.0`.
+///
+/// - Two pre-releases of the same major, minor, patch are compared by
+/// lexicographic ordering of dot-separated components of the pre-release
+/// string.
+///
+/// - Identifiers consisting of only digits are compared
+/// numerically: `1.0.0-pre.8` is less than `1.0.0-pre.12`.
+///
+/// - Identifiers that contain a letter or hyphen are compared in ASCII sort
+/// order: `1.0.0-pre12` is less than `1.0.0-pre8`.
+///
+/// - Any numeric identifier is always less than any non-numeric
+/// identifier: `1.0.0-pre.1` is less than `1.0.0-pre.x`.
+///
+/// Example: `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`
+#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
+pub struct Version {
+ pub major: u64,
+ pub minor: u64,
+ pub patch: u64,
+ pub pre: Prerelease,
+ pub build: BuildMetadata,
+}
+
+/// **SemVer version requirement** describing the intersection of some version
+/// comparators, such as `>=1.2.3, <1.8`.
+///
+/// # Syntax
+///
+/// - Either `*` (meaning "any"), or one or more comma-separated comparators.
+///
+/// - A [`Comparator`] is an operator ([`Op`]) and a partial version, separated
+/// by optional whitespace. For example `>=1.0.0` or `>=1.0`.
+///
+/// - Build metadata is syntactically permitted on the partial versions, but is
+/// completely ignored, as it's never relevant to whether any comparator
+/// matches a particular version.
+///
+/// - Whitespace is permitted around commas and around operators. Whitespace is
+/// not permitted within a partial version, i.e. anywhere between the major
+/// version number and its minor, patch, pre-release, or build metadata.
+#[derive(Clone, Eq, PartialEq, Hash, Debug)]
+#[cfg_attr(no_const_vec_new, derive(Default))]
+pub struct VersionReq {
+ pub comparators: Vec<Comparator>,
+}
+
+/// A pair of comparison operator and partial version, such as `>=1.2`. Forms
+/// one piece of a VersionReq.
+#[derive(Clone, Eq, PartialEq, Hash, Debug)]
+pub struct Comparator {
+ pub op: Op,
+ pub major: u64,
+ pub minor: Option<u64>,
+ /// Patch is only allowed if minor is Some.
+ pub patch: Option<u64>,
+ /// Non-empty pre-release is only allowed if patch is Some.
+ pub pre: Prerelease,
+}
+
+/// SemVer comparison operator: `=`, `>`, `>=`, `<`, `<=`, `~`, `^`, `*`.
+///
+/// # Op::Exact
+/// -  **`=I.J.K`** — exactly the version I.J.K
+/// -  **`=I.J`** — equivalent to `>=I.J.0, <I.(J+1).0`
+/// -  **`=I`** — equivalent to `>=I.0.0, <(I+1).0.0`
+///
+/// # Op::Greater
+/// -  **`>I.J.K`**
+/// -  **`>I.J`** — equivalent to `>=I.(J+1).0`
+/// -  **`>I`** — equivalent to `>=(I+1).0.0`
+///
+/// # Op::GreaterEq
+/// -  **`>=I.J.K`**
+/// -  **`>=I.J`** — equivalent to `>=I.J.0`
+/// -  **`>=I`** — equivalent to `>=I.0.0`
+///
+/// # Op::Less
+/// -  **`<I.J.K`**
+/// -  **`<I.J`** — equivalent to `<I.J.0`
+/// -  **`<I`** — equivalent to `<I.0.0`
+///
+/// # Op::LessEq
+/// -  **`<=I.J.K`**
+/// -  **`<=I.J`** — equivalent to `<I.(J+1).0`
+/// -  **`<=I`** — equivalent to `<(I+1).0.0`
+///
+/// # Op::Tilde ("patch" updates)
+/// *Tilde requirements allow the **patch** part of the semver version (the third number) to increase.*
+/// -  **`~I.J.K`** — equivalent to `>=I.J.K, <I.(J+1).0`
+/// -  **`~I.J`** — equivalent to `=I.J`
+/// -  **`~I`** — equivalent to `=I`
+///
+/// # Op::Caret ("compatible" updates)
+/// *Caret requirements allow parts that are **right of the first nonzero** part of the semver version to increase.*
+/// -  **`^I.J.K`** (for I\>0) — equivalent to `>=I.J.K, <(I+1).0.0`
+/// -  **`^0.J.K`** (for J\>0) — equivalent to `>=0.J.K, <0.(J+1).0`
+/// -  **`^0.0.K`** — equivalent to `=0.0.K`
+/// -  **`^I.J`** (for I\>0 or J\>0) — equivalent to `^I.J.0`
+/// -  **`^0.0`** — equivalent to `=0.0`
+/// -  **`^I`** — equivalent to `=I`
+///
+/// # Op::Wildcard
+/// -  **`I.J.*`** — equivalent to `=I.J`
+/// -  **`I.*`** or **`I.*.*`** — equivalent to `=I`
+#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
+#[cfg_attr(not(no_non_exhaustive), non_exhaustive)]
+pub enum Op {
+ Exact,
+ Greater,
+ GreaterEq,
+ Less,
+ LessEq,
+ Tilde,
+ Caret,
+ Wildcard,
+
+ #[cfg(no_non_exhaustive)] // rustc <1.40
+ #[doc(hidden)]
+ __NonExhaustive,
+}
-#![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))]
+/// Optional pre-release identifier on a version string. This comes after `-` in
+/// a SemVer version, like `1.0.0-alpha.1`
+///
+/// # Examples
+///
+/// Some real world pre-release idioms drawn from crates.io:
+///
+/// - **[mio]** <code>0.7.0-<b>alpha.1</b></code> — the most common style
+/// for numbering pre-releases.
+///
+/// - **[pest]** <code>1.0.0-<b>beta.8</b></code>, <code>1.0.0-<b>rc.0</b></code>
+/// — this crate makes a distinction between betas and release
+/// candidates.
+///
+/// - **[sassers]** <code>0.11.0-<b>shitshow</b></code> — ???.
+///
+/// - **[atomic-utils]** <code>0.0.0-<b>reserved</b></code> — a squatted
+/// crate name.
+///
+/// [mio]: https://crates.io/crates/mio
+/// [pest]: https://crates.io/crates/pest
+/// [atomic-utils]: https://crates.io/crates/atomic-utils
+/// [sassers]: https://crates.io/crates/sassers
+///
+/// *Tip:* Be aware that if you are planning to number your own pre-releases,
+/// you should prefer to separate the numeric part from any non-numeric
+/// identifiers by using a dot in between. That is, prefer pre-releases
+/// `alpha.1`, `alpha.2`, etc rather than `alpha1`, `alpha2` etc. The SemVer
+/// spec's rule for pre-release precedence has special treatment of numeric
+/// components in the pre-release string, but only if there are no non-digit
+/// characters in the same dot-separated component. So you'd have `alpha.2` <
+/// `alpha.11` as intended, but `alpha11` < `alpha2`.
+///
+/// # Syntax
+///
+/// Pre-release strings are a series of dot separated identifiers immediately
+/// following the patch version. Identifiers must comprise only ASCII
+/// alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must not be
+/// empty. Numeric identifiers must not include leading zeros.
+///
+/// # Total ordering
+///
+/// Pre-releases have a total order defined by the SemVer spec. It uses
+/// lexicographic ordering of dot-separated components. Identifiers consisting
+/// of only digits are compared numerically. Otherwise, identifiers are compared
+/// in ASCII sort order. Any numeric identifier is always less than any
+/// non-numeric identifier.
+///
+/// Example: `alpha` < `alpha.85` < `alpha.90` < `alpha.200` < `alpha.0a` < `alpha.1a0` < `alpha.a` < `beta`
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
+pub struct Prerelease {
+ identifier: Identifier,
+}
-extern crate semver_parser;
-
-// Serialization and deserialization support for version numbers
-#[cfg(feature = "serde")]
-extern crate serde;
+/// Optional build metadata identifier. This comes after `+` in a SemVer
+/// version, as in `0.8.1+zstd.1.5.0`.
+///
+/// # Examples
+///
+/// Some real world build metadata idioms drawn from crates.io:
+///
+/// - **[libgit2-sys]** <code>0.12.20+<b>1.1.0</b></code> — for this
+/// crate, the build metadata indicates the version of the C libgit2 library
+/// that the Rust crate is built against.
+///
+/// - **[mashup]** <code>0.1.13+<b>deprecated</b></code> — just the word
+/// "deprecated" for a crate that has been superseded by another. Eventually
+/// people will take notice of this in Cargo's build output where it lists the
+/// crates being compiled.
+///
+/// - **[google-bigquery2]** <code>2.0.4+<b>20210327</b></code> — this
+/// library is automatically generated from an official API schema, and the
+/// build metadata indicates the date on which that schema was last captured.
+///
+/// - **[fbthrift-git]** <code>0.0.6+<b>c7fcc0e</b></code> — this crate is
+/// published from snapshots of a big company monorepo. In monorepo
+/// development, there is no concept of versions, and all downstream code is
+/// just updated atomically in the same commit that breaking changes to a
+/// library are landed. Therefore for crates.io purposes, every published
+/// version must be assumed to be incompatible with the previous. The build
+/// metadata provides the source control hash of the snapshotted code.
+///
+/// [libgit2-sys]: https://crates.io/crates/libgit2-sys
+/// [mashup]: https://crates.io/crates/mashup
+/// [google-bigquery2]: https://crates.io/crates/google-bigquery2
+/// [fbthrift-git]: https://crates.io/crates/fbthrift-git
+///
+/// # Syntax
+///
+/// Build metadata is a series of dot separated identifiers immediately
+/// following the patch or pre-release version. Identifiers must comprise only
+/// ASCII alphanumerics and hyphens: `0-9`, `A-Z`, `a-z`, `-`. Identifiers must
+/// not be empty. Leading zeros *are* allowed, unlike any other place in the
+/// SemVer grammar.
+///
+/// # Total ordering
+///
+/// Build metadata is ignored in evaluating `VersionReq`; it plays no role in
+/// whether a `Version` matches any one of the comparison operators.
+///
+/// However for comparing build metadatas among one another, they do have a
+/// total order which is determined by lexicographic ordering of dot-separated
+/// components. Identifiers consisting of only digits are compared numerically.
+/// Otherwise, identifiers are compared in ASCII sort order. Any numeric
+/// identifier is always less than any non-numeric identifier.
+///
+/// Example: `demo` < `demo.85` < `demo.90` < `demo.090` < `demo.200` < `demo.1a0` < `demo.a` < `memo`
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
+pub struct BuildMetadata {
+ identifier: Identifier,
+}
-// We take the common approach of keeping our own module system private, and
-// just re-exporting the interface that we want.
+impl Version {
+ /// Create `Version` with an empty pre-release and build metadata.
+ ///
+ /// Equivalent to:
+ ///
+ /// ```
+ /// # use semver::{BuildMetadata, Prerelease, Version};
+ /// #
+ /// # const fn new(major: u64, minor: u64, patch: u64) -> Version {
+ /// Version {
+ /// major,
+ /// minor,
+ /// patch,
+ /// pre: Prerelease::EMPTY,
+ /// build: BuildMetadata::EMPTY,
+ /// }
+ /// # }
+ /// ```
+ pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
+ Version {
+ major,
+ minor,
+ patch,
+ pre: Prerelease::EMPTY,
+ build: BuildMetadata::EMPTY,
+ }
+ }
+
+ /// Create `Version` by parsing from string representation.
+ ///
+ /// # Errors
+ ///
+ /// Possible reasons for the parse to fail include:
+ ///
+ /// - `1.0` — too few numeric components. A SemVer version must have
+ /// exactly three. If you are looking at something that has fewer than
+ /// three numbers in it, it's possible it is a `VersionReq` instead (with
+ /// an implicit default `^` comparison operator).
+ ///
+ /// - `1.0.01` — a numeric component has a leading zero.
+ ///
+ /// - `1.0.unknown` — unexpected character in one of the components.
+ ///
+ /// - `1.0.0-` or `1.0.0+` — the pre-release or build metadata are
+ /// indicated present but empty.
+ ///
+ /// - `1.0.0-alpha_123` — pre-release or build metadata have something
+ /// outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`,
+ /// and `.` (dot).
+ ///
+ /// - `23456789999999999999.0.0` — overflow of a u64.
+ pub fn parse(text: &str) -> Result<Self, Error> {
+ Version::from_str(text)
+ }
+}
+
+impl VersionReq {
+ /// A `VersionReq` with no constraint on the version numbers it matches.
+ /// Equivalent to `VersionReq::parse("*").unwrap()`.
+ ///
+ /// In terms of comparators this is equivalent to `>=0.0.0`.
+ ///
+ /// Counterintuitively a `*` VersionReq does not match every possible
+ /// version number. In particular, in order for *any* `VersionReq` to match
+ /// a pre-release version, the `VersionReq` must contain at least one
+ /// `Comparator` that has an explicit major, minor, and patch version
+ /// identical to the pre-release being matched, and that has a nonempty
+ /// pre-release component. Since `*` is not written with an explicit major,
+ /// minor, and patch version, and does not contain a nonempty pre-release
+ /// component, it does not match any pre-release versions.
+ #[cfg(not(no_const_vec_new))] // rustc <1.39
+ pub const STAR: Self = VersionReq {
+ comparators: Vec::new(),
+ };
-pub use version::{Version, Identifier, SemVerError};
-pub use version::Identifier::{Numeric, AlphaNumeric};
-pub use version_req::{VersionReq, ReqParseError};
+ /// Create `VersionReq` by parsing from string representation.
+ ///
+ /// # Errors
+ ///
+ /// Possible reasons for the parse to fail include:
+ ///
+ /// - `>a.b` — unexpected characters in the partial version.
+ ///
+ /// - `@1.0.0` — unrecognized comparison operator.
+ ///
+ /// - `^1.0.0, ` — unexpected end of input.
+ ///
+ /// - `>=1.0 <2.0` — missing comma between comparators.
+ ///
+ /// - `*.*` — unsupported wildcard syntax.
+ pub fn parse(text: &str) -> Result<Self, Error> {
+ VersionReq::from_str(text)
+ }
+
+ /// Evaluate whether the given `Version` satisfies the version requirement
+ /// described by `self`.
+ pub fn matches(&self, version: &Version) -> bool {
+ eval::matches_req(self, version)
+ }
+}
+
+/// The default VersionReq is the same as [`VersionReq::STAR`].
+#[cfg(not(no_const_vec_new))]
+impl Default for VersionReq {
+ fn default() -> Self {
+ VersionReq::STAR
+ }
+}
+
+impl Comparator {
+ pub fn parse(text: &str) -> Result<Self, Error> {
+ Comparator::from_str(text)
+ }
-// SemVer-compliant versions.
-mod version;
+ pub fn matches(&self, version: &Version) -> bool {
+ eval::matches_comparator(self, version)
+ }
+}
+
+impl Prerelease {
+ pub const EMPTY: Self = Prerelease {
+ identifier: Identifier::empty(),
+ };
+
+ pub fn new(text: &str) -> Result<Self, Error> {
+ Prerelease::from_str(text)
+ }
+
+ pub fn as_str(&self) -> &str {
+ self.identifier.as_str()
+ }
-// advanced version comparisons
-mod version_req;
+ pub fn is_empty(&self) -> bool {
+ self.identifier.is_empty()
+ }
+}
+
+impl BuildMetadata {
+ pub const EMPTY: Self = BuildMetadata {
+ identifier: Identifier::empty(),
+ };
+
+ pub fn new(text: &str) -> Result<Self, Error> {
+ BuildMetadata::from_str(text)
+ }
+
+ pub fn as_str(&self) -> &str {
+ self.identifier.as_str()
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.identifier.is_empty()
+ }
+}
diff --git a/third_party/rust/semver/src/parse.rs b/third_party/rust/semver/src/parse.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/parse.rs
@@ -0,0 +1,405 @@
+use crate::backport::*;
+use crate::error::{ErrorKind, Position};
+use crate::identifier::Identifier;
+use crate::{BuildMetadata, Comparator, Op, Prerelease, Version, VersionReq};
+use core::str::FromStr;
+
+/// Error parsing a SemVer version or version requirement.
+///
+/// # Example
+///
+/// ```
+/// use semver::Version;
+///
+/// fn main() {
+/// let err = Version::parse("1.q.r").unwrap_err();
+///
+/// // "unexpected character 'q' while parsing minor version number"
+/// eprintln!("{}", err);
+/// }
+/// ```
+pub struct Error {
+ pub(crate) kind: ErrorKind,
+}
+
+impl FromStr for Version {
+ type Err = Error;
+
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
+ let mut pos = Position::Major;
+ let (major, text) = numeric_identifier(text, pos)?;
+ let text = dot(text, pos)?;
+
+ pos = Position::Minor;
+ let (minor, text) = numeric_identifier(text, pos)?;
+ let text = dot(text, pos)?;
+
+ pos = Position::Patch;
+ let (patch, text) = numeric_identifier(text, pos)?;
+
+ if text.is_empty() {
+ return Ok(Version::new(major, minor, patch));
+ }
+
+ let (pre, text) = if let Some(text) = text.strip_prefix('-') {
+ pos = Position::Pre;
+ let (pre, text) = prerelease_identifier(text)?;
+ if pre.is_empty() {
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
+ }
+ (pre, text)
+ } else {
+ (Prerelease::EMPTY, text)
+ };
+
+ let (build, text) = if let Some(text) = text.strip_prefix('+') {
+ pos = Position::Build;
+ let (build, text) = build_identifier(text)?;
+ if build.is_empty() {
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
+ }
+ (build, text)
+ } else {
+ (BuildMetadata::EMPTY, text)
+ };
+
+ if let Some(unexpected) = text.chars().next() {
+ return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)));
+ }
+
+ Ok(Version {
+ major,
+ minor,
+ patch,
+ pre,
+ build,
+ })
+ }
+}
+
+impl FromStr for VersionReq {
+ type Err = Error;
+
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
+ let text = text.trim_start_matches(' ');
+ if let Some((ch, text)) = wildcard(text) {
+ let rest = text.trim_start_matches(' ');
+ if rest.is_empty() {
+ #[cfg(not(no_const_vec_new))]
+ return Ok(VersionReq::STAR);
+ #[cfg(no_const_vec_new)] // rustc <1.39
+ return Ok(VersionReq {
+ comparators: Vec::new(),
+ });
+ } else if rest.starts_with(',') {
+ return Err(Error::new(ErrorKind::WildcardNotTheOnlyComparator(ch)));
+ } else {
+ return Err(Error::new(ErrorKind::UnexpectedAfterWildcard));
+ }
+ }
+
+ let depth = 0;
+ let mut comparators = Vec::new();
+ let len = version_req(text, &mut comparators, depth)?;
+ unsafe { comparators.set_len(len) }
+ Ok(VersionReq { comparators })
+ }
+}
+
+impl FromStr for Comparator {
+ type Err = Error;
+
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
+ let text = text.trim_start_matches(' ');
+ let (comparator, pos, rest) = comparator(text)?;
+ if !rest.is_empty() {
+ let unexpected = rest.chars().next().unwrap();
+ return Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)));
+ }
+ Ok(comparator)
+ }
+}
+
+impl FromStr for Prerelease {
+ type Err = Error;
+
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
+ let (pre, rest) = prerelease_identifier(text)?;
+ if !rest.is_empty() {
+ return Err(Error::new(ErrorKind::IllegalCharacter(Position::Pre)));
+ }
+ Ok(pre)
+ }
+}
+
+impl FromStr for BuildMetadata {
+ type Err = Error;
+
+ fn from_str(text: &str) -> Result<Self, Self::Err> {
+ let (build, rest) = build_identifier(text)?;
+ if !rest.is_empty() {
+ return Err(Error::new(ErrorKind::IllegalCharacter(Position::Build)));
+ }
+ Ok(build)
+ }
+}
+
+impl Error {
+ fn new(kind: ErrorKind) -> Self {
+ Error { kind }
+ }
+}
+
+impl Op {
+ const DEFAULT: Self = Op::Caret;
+}
+
+fn numeric_identifier(input: &str, pos: Position) -> Result<(u64, &str), Error> {
+ let mut len = 0;
+ let mut value = 0u64;
+
+ while let Some(&digit) = input.as_bytes().get(len) {
+ if digit < b'0' || digit > b'9' {
+ break;
+ }
+ if value == 0 && len > 0 {
+ return Err(Error::new(ErrorKind::LeadingZero(pos)));
+ }
+ match value
+ .checked_mul(10)
+ .and_then(|value| value.checked_add((digit - b'0') as u64))
+ {
+ Some(sum) => value = sum,
+ None => return Err(Error::new(ErrorKind::Overflow(pos))),
+ }
+ len += 1;
+ }
+
+ if len > 0 {
+ Ok((value, &input[len..]))
+ } else if let Some(unexpected) = input[len..].chars().next() {
+ Err(Error::new(ErrorKind::UnexpectedChar(pos, unexpected)))
+ } else {
+ Err(Error::new(ErrorKind::UnexpectedEnd(pos)))
+ }
+}
+
+fn wildcard(input: &str) -> Option<(char, &str)> {
+ if let Some(rest) = input.strip_prefix('*') {
+ Some(('*', rest))
+ } else if let Some(rest) = input.strip_prefix('x') {
+ Some(('x', rest))
+ } else if let Some(rest) = input.strip_prefix('X') {
+ Some(('X', rest))
+ } else {
+ None
+ }
+}
+
+fn dot(input: &str, pos: Position) -> Result<&str, Error> {
+ if let Some(rest) = input.strip_prefix('.') {
+ Ok(rest)
+ } else if let Some(unexpected) = input.chars().next() {
+ Err(Error::new(ErrorKind::UnexpectedCharAfter(pos, unexpected)))
+ } else {
+ Err(Error::new(ErrorKind::UnexpectedEnd(pos)))
+ }
+}
+
+fn prerelease_identifier(input: &str) -> Result<(Prerelease, &str), Error> {
+ let (string, rest) = identifier(input, Position::Pre)?;
+ let identifier = unsafe { Identifier::new_unchecked(string) };
+ Ok((Prerelease { identifier }, rest))
+}
+
+fn build_identifier(input: &str) -> Result<(BuildMetadata, &str), Error> {
+ let (string, rest) = identifier(input, Position::Build)?;
+ let identifier = unsafe { Identifier::new_unchecked(string) };
+ Ok((BuildMetadata { identifier }, rest))
+}
+
+fn identifier(input: &str, pos: Position) -> Result<(&str, &str), Error> {
+ let mut accumulated_len = 0;
+ let mut segment_len = 0;
+ let mut segment_has_nondigit = false;
+
+ loop {
+ match input.as_bytes().get(accumulated_len + segment_len) {
+ Some(b'A'..=b'Z') | Some(b'a'..=b'z') | Some(b'-') => {
+ segment_len += 1;
+ segment_has_nondigit = true;
+ }
+ Some(b'0'..=b'9') => {
+ segment_len += 1;
+ }
+ boundary => {
+ if segment_len == 0 {
+ if accumulated_len == 0 && boundary != Some(&b'.') {
+ return Ok(("", input));
+ } else {
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
+ }
+ }
+ if pos == Position::Pre
+ && segment_len > 1
+ && !segment_has_nondigit
+ && input[accumulated_len..].starts_with('0')
+ {
+ return Err(Error::new(ErrorKind::LeadingZero(pos)));
+ }
+ accumulated_len += segment_len;
+ if boundary == Some(&b'.') {
+ accumulated_len += 1;
+ segment_len = 0;
+ segment_has_nondigit = false;
+ } else {
+ return Ok(input.split_at(accumulated_len));
+ }
+ }
+ }
+ }
+}
+
+fn op(input: &str) -> (Op, &str) {
+ let bytes = input.as_bytes();
+ if bytes.get(0) == Some(&b'=') {
+ (Op::Exact, &input[1..])
+ } else if bytes.get(0) == Some(&b'>') {
+ if bytes.get(1) == Some(&b'=') {
+ (Op::GreaterEq, &input[2..])
+ } else {
+ (Op::Greater, &input[1..])
+ }
+ } else if bytes.get(0) == Some(&b'<') {
+ if bytes.get(1) == Some(&b'=') {
+ (Op::LessEq, &input[2..])
+ } else {
+ (Op::Less, &input[1..])
+ }
+ } else if bytes.get(0) == Some(&b'~') {
+ (Op::Tilde, &input[1..])
+ } else if bytes.get(0) == Some(&b'^') {
+ (Op::Caret, &input[1..])
+ } else {
+ (Op::DEFAULT, input)
+ }
+}
+
+fn comparator(input: &str) -> Result<(Comparator, Position, &str), Error> {
+ let (mut op, text) = op(input);
+ let default_op = input.len() == text.len();
+ let text = text.trim_start_matches(' ');
+
+ let mut pos = Position::Major;
+ let (major, text) = numeric_identifier(text, pos)?;
+ let mut has_wildcard = false;
+
+ let (minor, text) = if let Some(text) = text.strip_prefix('.') {
+ pos = Position::Minor;
+ if let Some((_, text)) = wildcard(text) {
+ has_wildcard = true;
+ if default_op {
+ op = Op::Wildcard;
+ }
+ (None, text)
+ } else {
+ let (minor, text) = numeric_identifier(text, pos)?;
+ (Some(minor), text)
+ }
+ } else {
+ (None, text)
+ };
+
+ let (patch, text) = if let Some(text) = text.strip_prefix('.') {
+ pos = Position::Patch;
+ if let Some((_, text)) = wildcard(text) {
+ if default_op {
+ op = Op::Wildcard;
+ }
+ (None, text)
+ } else if has_wildcard {
+ return Err(Error::new(ErrorKind::UnexpectedAfterWildcard));
+ } else {
+ let (patch, text) = numeric_identifier(text, pos)?;
+ (Some(patch), text)
+ }
+ } else {
+ (None, text)
+ };
+
+ let (pre, text) = if patch.is_some() && text.starts_with('-') {
+ pos = Position::Pre;
+ let text = &text[1..];
+ let (pre, text) = prerelease_identifier(text)?;
+ if pre.is_empty() {
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
+ }
+ (pre, text)
+ } else {
+ (Prerelease::EMPTY, text)
+ };
+
+ let text = if patch.is_some() && text.starts_with('+') {
+ pos = Position::Build;
+ let text = &text[1..];
+ let (build, text) = build_identifier(text)?;
+ if build.is_empty() {
+ return Err(Error::new(ErrorKind::EmptySegment(pos)));
+ }
+ text
+ } else {
+ text
+ };
+
+ let text = text.trim_start_matches(' ');
+
+ let comparator = Comparator {
+ op,
+ major,
+ minor,
+ patch,
+ pre,
+ };
+
+ Ok((comparator, pos, text))
+}
+
+fn version_req(input: &str, out: &mut Vec<Comparator>, depth: usize) -> Result<usize, Error> {
+ let (comparator, pos, text) = match comparator(input) {
+ Ok(success) => success,
+ Err(mut error) => {
+ if let Some((ch, mut rest)) = wildcard(input) {
+ rest = rest.trim_start_matches(' ');
+ if rest.is_empty() || rest.starts_with(',') {
+ error.kind = ErrorKind::WildcardNotTheOnlyComparator(ch);
+ }
+ }
+ return Err(error);
+ }
+ };
+
+ if text.is_empty() {
+ out.reserve_exact(depth + 1);
+ unsafe { out.as_mut_ptr().add(depth).write(comparator) }
+ return Ok(depth + 1);
+ }
+
+ let text = if let Some(text) = text.strip_prefix(',') {
+ text.trim_start_matches(' ')
+ } else {
+ let unexpected = text.chars().next().unwrap();
+ return Err(Error::new(ErrorKind::ExpectedCommaFound(pos, unexpected)));
+ };
+
+ const MAX_COMPARATORS: usize = 32;
+ if depth + 1 == MAX_COMPARATORS {
+ return Err(Error::new(ErrorKind::ExcessiveComparators));
+ }
+
+ // Recurse to collect parsed Comparator objects on the stack. We perform a
+ // single allocation to allocate exactly the right sized Vec only once the
+ // total number of comparators is known.
+ let len = version_req(text, out, depth + 1)?;
+ unsafe { out.as_mut_ptr().add(depth).write(comparator) }
+ Ok(len)
+}
diff --git a/third_party/rust/semver/src/serde.rs b/third_party/rust/semver/src/serde.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/src/serde.rs
@@ -0,0 +1,74 @@
+use crate::{Version, VersionReq};
+use core::fmt;
+use serde::de::{Deserialize, Deserializer, Error, Visitor};
+use serde::ser::{Serialize, Serializer};
+
+impl Serialize for Version {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.collect_str(self)
+ }
+}
+
+impl Serialize for VersionReq {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: Serializer,
+ {
+ serializer.collect_str(self)
+ }
+}
+
+impl<'de> Deserialize<'de> for Version {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct VersionVisitor;
+
+ impl<'de> Visitor<'de> for VersionVisitor {
+ type Value = Version;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("semver version")
+ }
+
+ fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ string.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(VersionVisitor)
+ }
+}
+
+impl<'de> Deserialize<'de> for VersionReq {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct VersionReqVisitor;
+
+ impl<'de> Visitor<'de> for VersionReqVisitor {
+ type Value = VersionReq;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("semver version")
+ }
+
+ fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ string.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(VersionReqVisitor)
+ }
+}
diff --git a/third_party/rust/semver/src/version.rs b/third_party/rust/semver/src/version.rs
deleted file mode 100644
--- a/third_party/rust/semver/src/version.rs
+++ /dev/null
@@ -1,759 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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;
-
-#[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
-/// 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<semver_parser::version::Identifier> 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),
- }
- }
-}
-
-#[cfg(feature = "serde")]
-impl Serialize for Identifier {
- fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
- 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<D>(deserializer: D) -> result::Result<Self, D::Error>
- 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<E>(self, numeric: u64) -> result::Result<Self::Value, E>
- where E: de::Error
- {
- Ok(Identifier::Numeric(numeric))
- }
-
- fn visit_str<E>(self, alphanumeric: &str) -> result::Result<Self::Value, E>
- 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 {
- /// 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<Identifier>,
- /// The build metadata, ignored when determining version precedence.
- pub build: Vec<Identifier>,
-}
-
-impl From<semver_parser::version::Version> 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(),
- }
- }
-}
-
-#[cfg(feature = "serde")]
-impl Serialize for Version {
- fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
- where S: Serializer
- {
- // Serialize Version as a string.
- serializer.collect_str(self)
- }
-}
-
-#[cfg(feature = "serde")]
-impl<'de> Deserialize<'de> for Version {
- fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
- 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<E>(self, v: &str) -> result::Result<Self::Value, E>
- 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.
-#[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<T> = result::Result<T, SemVerError>;
-
-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<Version> {
- 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> {
- 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<Ordering> {
- 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<H: hash::Hasher>(&self, into: &mut H) {
- self.major.hash(into);
- self.minor.hash(into);
- self.patch.hash(into);
- self.pre.hash(into);
- }
-}
-
-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;
- use super::Version;
- use super::Identifier;
- use super::SemVerError;
-
- #[test]
- fn test_parse() {
- fn parse_error(e: &str) -> result::Result<Version, SemVerError> {
- 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::new(1,2,3)));
-
- 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<Version, SemVerError> {
- 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/src/version_req.rs b/third_party/rust/semver/src/version_req.rs
deleted file mode 100644
--- a/third_party/rust/semver/src/version_req.rs
+++ /dev/null
@@ -1,895 +0,0 @@
-// 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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::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::*;
-
-/// 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(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-pub struct VersionReq {
- predicates: Vec<Predicate>,
-}
-
-impl From<semver_parser::range::VersionReq> for VersionReq {
- fn from(other: semver_parser::range::VersionReq) -> VersionReq {
- VersionReq { predicates: other.predicates.into_iter().map(From::from).collect() }
- }
-}
-
-#[cfg(feature = "serde")]
-impl Serialize for VersionReq {
- fn serialize<S>(&self, serializer: S) -> result::Result<S::Ok, S::Error>
- where S: Serializer
- {
- // Serialize VersionReq as a string.
- serializer.collect_str(self)
- }
-}
-
-#[cfg(feature = "serde")]
-impl<'de> Deserialize<'de> for VersionReq {
- fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
- 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<E>(self, v: &str) -> result::Result<Self::Value, E>
- 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(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, 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<semver_parser::range::Op> 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(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-struct Predicate {
- op: Op,
- major: u64,
- minor: Option<u64>,
- patch: Option<u64>,
- pre: Vec<Identifier>,
-}
-
-impl From<semver_parser::range::Predicate> 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<String> 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 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
- /// `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"); // synonym for ^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<VersionReq, ReqParseError> {
- 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<VersionReq> {
- 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, ReqParseError> {
- 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;
- use std::hash::{Hash, Hasher};
-
- 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);
- }
- }
-
- fn calculate_hash<T: 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");
-
- 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::<VersionReq>().unwrap().to_string(),
- "^1.0.0".to_string());
- assert_eq!("=1.0.0".parse::<VersionReq>().unwrap().to_string(),
- "= 1.0.0".to_string());
- assert_eq!("~1".parse::<VersionReq>().unwrap().to_string(),
- "~1".to_string());
- assert_eq!("~1.2".parse::<VersionReq>().unwrap().to_string(),
- "~1.2".to_string());
- assert_eq!("^1".parse::<VersionReq>().unwrap().to_string(),
- "^1".to_string());
- assert_eq!("^1.1".parse::<VersionReq>().unwrap().to_string(),
- "^1.1".to_string());
- assert_eq!("*".parse::<VersionReq>().unwrap().to_string(),
- "*".to_string());
- assert_eq!("1.*".parse::<VersionReq>().unwrap().to_string(),
- "1.*".to_string());
- assert_eq!("< 1.0.0".parse::<VersionReq>().unwrap().to_string(),
- "< 1.0.0".to_string());
- }
-
- // #[test]
- // pub fn test_from_str_errors() {
- // assert_eq!(Err(InvalidVersionRequirement), "\0".parse::<VersionReq>());
- // assert_eq!(Err(OpAlreadySet), ">= >= 0.0.2".parse::<VersionReq>());
- // assert_eq!(Err(InvalidSigil), ">== 0.0.2".parse::<VersionReq>());
- // assert_eq!(Err(VersionComponentsMustBeNumeric),
- // "a.0.0".parse::<VersionReq>());
- // assert_eq!(Err(InvalidIdentifier), "1.0.0-".parse::<VersionReq>());
- // assert_eq!(Err(MajorVersionRequired), ">=".parse::<VersionReq>());
- // }
-
- #[test]
- fn test_cargo3202() {
- let v = "0.*.*".parse::<VersionReq>().unwrap();
- assert_eq!("0.*.*", format!("{}", v.predicates[0]));
-
- let v = "0.0.*".parse::<VersionReq>().unwrap();
- assert_eq!("0.0.*", format!("{}", v.predicates[0]));
-
- 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/deprecation.rs b/third_party/rust/semver/tests/deprecation.rs
deleted file mode 100644
--- a/third_party/rust/semver/tests/deprecation.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-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/tests/node/mod.rs b/third_party/rust/semver/tests/node/mod.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/node/mod.rs
@@ -0,0 +1,43 @@
+#![cfg(test_node_semver)]
+
+use semver::Version;
+use std::fmt::{self, Display};
+use std::process::Command;
+
+#[derive(Default, Eq, PartialEq, Hash, Debug)]
+pub(super) struct VersionReq(semver::VersionReq);
+
+impl VersionReq {
+ pub(super) const STAR: Self = VersionReq(semver::VersionReq::STAR);
+
+ pub(super) fn matches(&self, version: &Version) -> bool {
+ let out = Command::new("node")
+ .arg("-e")
+ .arg(format!(
+ "console.log(require('semver').satisfies('{}', '{}'))",
+ version,
+ self.to_string().replace(',', ""),
+ ))
+ .output()
+ .unwrap();
+ if out.stdout == b"true\n" {
+ true
+ } else if out.stdout == b"false\n" {
+ false
+ } else {
+ let s = String::from_utf8_lossy(&out.stdout) + String::from_utf8_lossy(&out.stderr);
+ panic!("unexpected output: {}", s);
+ }
+ }
+}
+
+impl Display for VersionReq {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ Display::fmt(&self.0, formatter)
+ }
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn req(text: &str) -> VersionReq {
+ VersionReq(crate::util::req(text))
+}
diff --git a/third_party/rust/semver/tests/regression.rs b/third_party/rust/semver/tests/regression.rs
deleted file mode 100644
--- a/third_party/rust/semver/tests/regression.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-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/tests/serde.rs b/third_party/rust/semver/tests/serde.rs
deleted file mode 100644
--- a/third_party/rust/semver/tests/serde.rs
+++ /dev/null
@@ -1,90 +0,0 @@
-#![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::<Identified>(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::<Identified>(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::<Versioned>(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::<VersionReq>().unwrap(), serde_json::from_str(r#""1.0.0""#).unwrap());
-}
diff --git a/third_party/rust/semver/tests/test_autotrait.rs b/third_party/rust/semver/tests/test_autotrait.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/test_autotrait.rs
@@ -0,0 +1,12 @@
+fn assert_send_sync<T: Send + Sync>() {}
+
+#[test]
+fn test() {
+ assert_send_sync::<semver::BuildMetadata>();
+ assert_send_sync::<semver::Comparator>();
+ assert_send_sync::<semver::Error>();
+ assert_send_sync::<semver::Prerelease>();
+ assert_send_sync::<semver::Version>();
+ assert_send_sync::<semver::VersionReq>();
+ assert_send_sync::<semver::Op>();
+}
diff --git a/third_party/rust/semver/tests/test_identifier.rs b/third_party/rust/semver/tests/test_identifier.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/test_identifier.rs
@@ -0,0 +1,45 @@
+#![allow(
+ clippy::eq_op,
+ clippy::needless_pass_by_value,
+ clippy::toplevel_ref_arg,
+ clippy::wildcard_imports
+)]
+
+mod util;
+
+use crate::util::*;
+use semver::Prerelease;
+
+#[test]
+fn test_new() {
+ fn test(identifier: Prerelease, expected: &str) {
+ assert_eq!(identifier.is_empty(), expected.is_empty());
+ assert_eq!(identifier.len(), expected.len());
+ assert_eq!(identifier.as_str(), expected);
+ assert_eq!(identifier, identifier);
+ assert_eq!(identifier, identifier.clone());
+ }
+
+ let ref mut string = String::new();
+ let limit = if cfg!(miri) { 40 } else { 280 }; // miri is slow
+ for _ in 0..limit {
+ test(prerelease(string), string);
+ string.push('1');
+ }
+
+ if !cfg!(miri) {
+ let ref string = string.repeat(20000);
+ test(prerelease(string), string);
+ }
+}
+
+#[test]
+fn test_eq() {
+ assert_eq!(prerelease("-"), prerelease("-"));
+ assert_ne!(prerelease("a"), prerelease("aa"));
+ assert_ne!(prerelease("aa"), prerelease("a"));
+ assert_ne!(prerelease("aaaaaaaaa"), prerelease("a"));
+ assert_ne!(prerelease("a"), prerelease("aaaaaaaaa"));
+ assert_ne!(prerelease("aaaaaaaaa"), prerelease("bbbbbbbbb"));
+ assert_ne!(build_metadata("1"), build_metadata("001"));
+}
diff --git a/third_party/rust/semver/tests/test_version.rs b/third_party/rust/semver/tests/test_version.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/test_version.rs
@@ -0,0 +1,241 @@
+#![allow(
+ clippy::nonminimal_bool,
+ clippy::too_many_lines,
+ clippy::wildcard_imports
+)]
+
+mod util;
+
+use crate::util::*;
+use semver::{BuildMetadata, Prerelease, Version};
+
+#[test]
+fn test_parse() {
+ let err = version_err("");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing major version number",
+ );
+
+ let err = version_err(" ");
+ assert_to_string(
+ err,
+ "unexpected character ' ' while parsing major version number",
+ );
+
+ let err = version_err("1");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing major version number",
+ );
+
+ let err = version_err("1.2");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing minor version number",
+ );
+
+ let err = version_err("1.2.3-");
+ assert_to_string(err, "empty identifier segment in pre-release identifier");
+
+ let err = version_err("a.b.c");
+ assert_to_string(
+ err,
+ "unexpected character 'a' while parsing major version number",
+ );
+
+ let err = version_err("1.2.3 abc");
+ assert_to_string(err, "unexpected character ' ' after patch version number");
+
+ let err = version_err("1.2.3-01");
+ assert_to_string(err, "invalid leading zero in pre-release identifier");
+
+ let parsed = version("1.2.3");
+ let expected = Version::new(1, 2, 3);
+ assert_eq!(parsed, expected);
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: Prerelease::EMPTY,
+ build: BuildMetadata::EMPTY,
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3-alpha1");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: prerelease("alpha1"),
+ build: BuildMetadata::EMPTY,
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3+build5");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: Prerelease::EMPTY,
+ build: build_metadata("build5"),
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3+5build");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: Prerelease::EMPTY,
+ build: build_metadata("5build"),
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3-alpha1+build5");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: prerelease("alpha1"),
+ build: build_metadata("build5"),
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3-1.alpha1.9+build5.7.3aedf");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: prerelease("1.alpha1.9"),
+ build: build_metadata("build5.7.3aedf"),
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("1.2.3-0a.alpha1.9+05build.7.3aedf");
+ let expected = Version {
+ major: 1,
+ minor: 2,
+ patch: 3,
+ pre: prerelease("0a.alpha1.9"),
+ build: build_metadata("05build.7.3aedf"),
+ };
+ assert_eq!(parsed, expected);
+
+ let parsed = version("0.4.0-beta.1+0851523");
+ let expected = Version {
+ major: 0,
+ minor: 4,
+ patch: 0,
+ pre: prerelease("beta.1"),
+ build: build_metadata("0851523"),
+ };
+ assert_eq!(parsed, expected);
+
+ // for https://nodejs.org/dist/index.json, where some older npm versions are "1.1.0-beta-10"
+ let parsed = version("1.1.0-beta-10");
+ let expected = Version {
+ major: 1,
+ minor: 1,
+ patch: 0,
+ pre: prerelease("beta-10"),
+ build: BuildMetadata::EMPTY,
+ };
+ assert_eq!(parsed, expected);
+}
+
+#[test]
+fn test_eq() {
+ assert_eq!(version("1.2.3"), version("1.2.3"));
+ assert_eq!(version("1.2.3-alpha1"), version("1.2.3-alpha1"));
+ assert_eq!(version("1.2.3+build.42"), version("1.2.3+build.42"));
+ assert_eq!(version("1.2.3-alpha1+42"), version("1.2.3-alpha1+42"));
+}
+
+#[test]
+fn test_ne() {
+ assert_ne!(version("0.0.0"), version("0.0.1"));
+ assert_ne!(version("0.0.0"), version("0.1.0"));
+ assert_ne!(version("0.0.0"), version("1.0.0"));
+ assert_ne!(version("1.2.3-alpha"), version("1.2.3-beta"));
+ assert_ne!(version("1.2.3+23"), version("1.2.3+42"));
+}
+
+#[test]
+fn test_display() {
+ assert_to_string(version("1.2.3"), "1.2.3");
+ assert_to_string(version("1.2.3-alpha1"), "1.2.3-alpha1");
+ assert_to_string(version("1.2.3+build.42"), "1.2.3+build.42");
+ assert_to_string(version("1.2.3-alpha1+42"), "1.2.3-alpha1+42");
+}
+
+#[test]
+fn test_lt() {
+ assert!(version("0.0.0") < version("1.2.3-alpha2"));
+ assert!(version("1.0.0") < version("1.2.3-alpha2"));
+ assert!(version("1.2.0") < version("1.2.3-alpha2"));
+ assert!(version("1.2.3-alpha1") < version("1.2.3"));
+ assert!(version("1.2.3-alpha1") < version("1.2.3-alpha2"));
+ assert!(!(version("1.2.3-alpha2") < version("1.2.3-alpha2")));
+ assert!(version("1.2.3+23") < version("1.2.3+42"));
+}
+
+#[test]
+fn test_le() {
+ assert!(version("0.0.0") <= version("1.2.3-alpha2"));
+ assert!(version("1.0.0") <= version("1.2.3-alpha2"));
+ assert!(version("1.2.0") <= version("1.2.3-alpha2"));
+ assert!(version("1.2.3-alpha1") <= version("1.2.3-alpha2"));
+ assert!(version("1.2.3-alpha2") <= version("1.2.3-alpha2"));
+ assert!(version("1.2.3+23") <= version("1.2.3+42"));
+}
+
+#[test]
+fn test_gt() {
+ assert!(version("1.2.3-alpha2") > version("0.0.0"));
+ assert!(version("1.2.3-alpha2") > version("1.0.0"));
+ assert!(version("1.2.3-alpha2") > version("1.2.0"));
+ assert!(version("1.2.3-alpha2") > version("1.2.3-alpha1"));
+ assert!(version("1.2.3") > version("1.2.3-alpha2"));
+ assert!(!(version("1.2.3-alpha2") > version("1.2.3-alpha2")));
+ assert!(!(version("1.2.3+23") > version("1.2.3+42")));
+}
+
+#[test]
+fn test_ge() {
+ assert!(version("1.2.3-alpha2") >= version("0.0.0"));
+ assert!(version("1.2.3-alpha2") >= version("1.0.0"));
+ assert!(version("1.2.3-alpha2") >= version("1.2.0"));
+ assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha1"));
+ assert!(version("1.2.3-alpha2") >= version("1.2.3-alpha2"));
+ assert!(!(version("1.2.3+23") >= version("1.2.3+42")));
+}
+
+#[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(vs[i - 1]);
+ let b = version(vs[i]);
+ assert!(a < b, "nope {:?} < {:?}", a, b);
+ i += 1;
+ }
+}
+
+#[test]
+fn test_align() {
+ let version = version("1.2.3-rc1");
+ assert_eq!("1.2.3-rc1 ", format!("{:20}", version));
+ assert_eq!("*****1.2.3-rc1******", format!("{:*^20}", version));
+ assert_eq!(" 1.2.3-rc1", format!("{:>20}", version));
+}
diff --git a/third_party/rust/semver/tests/test_version_req.rs b/third_party/rust/semver/tests/test_version_req.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/test_version_req.rs
@@ -0,0 +1,443 @@
+#![allow(
+ clippy::missing_panics_doc,
+ clippy::shadow_unrelated,
+ clippy::toplevel_ref_arg,
+ clippy::wildcard_imports
+)]
+
+mod node;
+mod util;
+
+use crate::util::*;
+use std::collections::hash_map::DefaultHasher;
+use std::hash::{Hash, Hasher};
+
+#[cfg(test_node_semver)]
+use node::{req, VersionReq};
+#[cfg(not(test_node_semver))]
+use semver::VersionReq;
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+fn assert_match_all(req: &VersionReq, versions: &[&str]) {
+ for string in versions {
+ let parsed = version(string);
+ assert!(req.matches(&parsed), "did not match {}", string);
+ }
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+fn assert_match_none(req: &VersionReq, versions: &[&str]) {
+ for string in versions {
+ let parsed = version(string);
+ assert!(!req.matches(&parsed), "matched {}", string);
+ }
+}
+
+#[test]
+fn test_basic() {
+ let ref r = req("1.0.0");
+ assert_to_string(r, "^1.0.0");
+ assert_match_all(r, &["1.0.0", "1.1.0", "1.0.1"]);
+ assert_match_none(r, &["0.9.9", "0.10.0", "0.1.0", "1.0.0-pre", "1.0.1-pre"]);
+}
+
+#[test]
+#[cfg(not(no_const_vec_new))]
+fn test_default() {
+ let ref r = VersionReq::default();
+ assert_eq!(r, &VersionReq::STAR);
+}
+
+#[test]
+fn test_exact() {
+ let ref r = req("=1.0.0");
+ assert_to_string(r, "=1.0.0");
+ assert_match_all(r, &["1.0.0"]);
+ assert_match_none(r, &["1.0.1", "0.9.9", "0.10.0", "0.1.0", "1.0.0-pre"]);
+
+ let ref r = req("=0.9.0");
+ assert_to_string(r, "=0.9.0");
+ assert_match_all(r, &["0.9.0"]);
+ assert_match_none(r, &["0.9.1", "1.9.0", "0.0.9", "0.9.0-pre"]);
+
+ let ref r = req("=0.0.2");
+ assert_to_string(r, "=0.0.2");
+ assert_match_all(r, &["0.0.2"]);
+ assert_match_none(r, &["0.0.1", "0.0.3", "0.0.2-pre"]);
+
+ let ref r = req("=0.1.0-beta2.a");
+ assert_to_string(r, "=0.1.0-beta2.a");
+ assert_match_all(r, &["0.1.0-beta2.a"]);
+ assert_match_none(r, &["0.9.1", "0.1.0", "0.1.1-beta2.a", "0.1.0-beta2"]);
+
+ let ref r = req("=0.1.0+meta");
+ assert_to_string(r, "=0.1.0");
+ assert_match_all(r, &["0.1.0", "0.1.0+meta", "0.1.0+any"]);
+}
+
+#[test]
+pub fn test_greater_than() {
+ let ref r = req(">= 1.0.0");
+ assert_to_string(r, ">=1.0.0");
+ assert_match_all(r, &["1.0.0", "2.0.0"]);
+ assert_match_none(r, &["0.1.0", "0.0.1", "1.0.0-pre", "2.0.0-pre"]);
+
+ let ref r = req(">= 2.1.0-alpha2");
+ assert_to_string(r, ">=2.1.0-alpha2");
+ assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha3", "2.1.0", "3.0.0"]);
+ assert_match_none(
+ r,
+ &["2.0.0", "2.1.0-alpha1", "2.0.0-alpha2", "3.0.0-alpha2"],
+ );
+}
+
+#[test]
+pub fn test_less_than() {
+ let ref r = req("< 1.0.0");
+ assert_to_string(r, "<1.0.0");
+ assert_match_all(r, &["0.1.0", "0.0.1"]);
+ assert_match_none(r, &["1.0.0", "1.0.0-beta", "1.0.1", "0.9.9-alpha"]);
+
+ let ref r = req("<= 2.1.0-alpha2");
+ assert_match_all(r, &["2.1.0-alpha2", "2.1.0-alpha1", "2.0.0", "1.0.0"]);
+ assert_match_none(
+ r,
+ &["2.1.0", "2.2.0-alpha1", "2.0.0-alpha2", "1.0.0-alpha2"],
+ );
+
+ let ref r = req(">1.0.0-alpha, <1.0.0");
+ assert_match_all(r, &["1.0.0-beta"]);
+
+ let ref r = req(">1.0.0-alpha, <1.0");
+ assert_match_none(r, &["1.0.0-beta"]);
+
+ let ref r = req(">1.0.0-alpha, <1");
+ assert_match_none(r, &["1.0.0-beta"]);
+}
+
+#[test]
+pub fn test_multiple() {
+ let ref r = req("> 0.0.9, <= 2.5.3");
+ assert_to_string(r, ">0.0.9, <=2.5.3");
+ assert_match_all(r, &["0.0.10", "1.0.0", "2.5.3"]);
+ assert_match_none(r, &["0.0.8", "2.5.4"]);
+
+ let ref r = req("0.3.0, 0.4.0");
+ assert_to_string(r, "^0.3.0, ^0.4.0");
+ assert_match_none(r, &["0.0.8", "0.3.0", "0.4.0"]);
+
+ let ref r = req("<= 0.2.0, >= 0.5.0");
+ assert_to_string(r, "<=0.2.0, >=0.5.0");
+ assert_match_none(r, &["0.0.8", "0.3.0", "0.5.1"]);
+
+ let ref r = req("0.1.0, 0.1.4, 0.1.6");
+ assert_to_string(r, "^0.1.0, ^0.1.4, ^0.1.6");
+ assert_match_all(r, &["0.1.6", "0.1.9"]);
+ assert_match_none(r, &["0.1.0", "0.1.4", "0.2.0"]);
+
+ let err = req_err("> 0.1.0,");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing major version number",
+ );
+
+ let err = req_err("> 0.3.0, ,");
+ assert_to_string(
+ err,
+ "unexpected character ',' while parsing major version number",
+ );
+
+ let ref r = req(">=0.5.1-alpha3, <0.6");
+ assert_to_string(r, ">=0.5.1-alpha3, <0.6");
+ assert_match_all(
+ r,
+ &[
+ "0.5.1-alpha3",
+ "0.5.1-alpha4",
+ "0.5.1-beta",
+ "0.5.1",
+ "0.5.5",
+ ],
+ );
+ assert_match_none(
+ r,
+ &["0.5.1-alpha1", "0.5.2-alpha3", "0.5.5-pre", "0.5.0-pre"],
+ );
+ assert_match_none(r, &["0.6.0", "0.6.0-pre"]);
+
+ // https://github.com/steveklabnik/semver/issues/56
+ let err = req_err("1.2.3 - 2.3.4");
+ assert_to_string(err, "expected comma after patch version number, found '-'");
+}
+
+#[test]
+pub fn test_whitespace_delimited_comparator_sets() {
+ // https://github.com/steveklabnik/semver/issues/55
+ let err = req_err("> 0.0.9 <= 2.5.3");
+ assert_to_string(err, "expected comma after patch version number, found '<'");
+}
+
+#[test]
+pub fn test_tilde() {
+ let ref r = req("~1");
+ assert_match_all(r, &["1.0.0", "1.0.1", "1.1.1"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "0.0.9"]);
+
+ let ref r = req("~1.2");
+ assert_match_all(r, &["1.2.0", "1.2.1"]);
+ assert_match_none(r, &["1.1.1", "1.3.0", "0.0.9"]);
+
+ let ref r = req("~1.2.2");
+ assert_match_all(r, &["1.2.2", "1.2.4"]);
+ assert_match_none(r, &["1.2.1", "1.9.0", "1.0.9", "2.0.1", "0.1.3"]);
+
+ let ref r = req("~1.2.3-beta.2");
+ assert_match_all(r, &["1.2.3", "1.2.4", "1.2.3-beta.2", "1.2.3-beta.4"]);
+ assert_match_none(r, &["1.3.3", "1.1.4", "1.2.3-beta.1", "1.2.4-beta.2"]);
+}
+
+#[test]
+pub fn test_caret() {
+ let ref r = req("^1");
+ assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1", "1.0.1"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "0.1.4"]);
+ assert_match_none(r, &["1.0.0-beta1", "0.1.0-alpha", "1.0.1-pre"]);
+
+ let ref r = req("^1.1");
+ assert_match_all(r, &["1.1.2", "1.1.0", "1.2.1"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.0.1", "0.1.4"]);
+
+ let ref r = req("^1.1.2");
+ assert_match_all(r, &["1.1.2", "1.1.4", "1.2.1"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
+ assert_match_none(r, &["1.1.2-alpha1", "1.1.3-alpha1", "2.9.0-alpha1"]);
+
+ let ref r = req("^0.1.2");
+ assert_match_all(r, &["0.1.2", "0.1.4"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1"]);
+ assert_match_none(r, &["0.1.2-beta", "0.1.3-alpha", "0.2.0-pre"]);
+
+ let ref r = req("^0.5.1-alpha3");
+ assert_match_all(
+ r,
+ &[
+ "0.5.1-alpha3",
+ "0.5.1-alpha4",
+ "0.5.1-beta",
+ "0.5.1",
+ "0.5.5",
+ ],
+ );
+ assert_match_none(
+ r,
+ &[
+ "0.5.1-alpha1",
+ "0.5.2-alpha3",
+ "0.5.5-pre",
+ "0.5.0-pre",
+ "0.6.0",
+ ],
+ );
+
+ let ref r = req("^0.0.2");
+ assert_match_all(r, &["0.0.2"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.0.1", "0.1.4"]);
+
+ let ref r = req("^0.0");
+ assert_match_all(r, &["0.0.2", "0.0.0"]);
+ assert_match_none(r, &["0.9.1", "2.9.0", "1.1.1", "0.1.4"]);
+
+ let ref r = req("^0");
+ assert_match_all(r, &["0.9.1", "0.0.2", "0.0.0"]);
+ assert_match_none(r, &["2.9.0", "1.1.1"]);
+
+ let ref r = req("^1.4.2-beta.5");
+ assert_match_all(
+ r,
+ &["1.4.2", "1.4.3", "1.4.2-beta.5", "1.4.2-beta.6", "1.4.2-c"],
+ );
+ assert_match_none(
+ 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_wildcard() {
+ let err = req_err("");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing major version number",
+ );
+
+ let ref r = req("*");
+ assert_match_all(r, &["0.9.1", "2.9.0", "0.0.9", "1.0.1", "1.1.1"]);
+ assert_match_none(r, &["1.0.0-pre"]);
+
+ for s in &["x", "X"] {
+ assert_eq!(*r, req(s));
+ }
+
+ let ref r = req("1.*");
+ assert_match_all(r, &["1.2.0", "1.2.1", "1.1.1", "1.3.0"]);
+ assert_match_none(r, &["0.0.9", "1.2.0-pre"]);
+
+ for s in &["1.x", "1.X", "1.*.*"] {
+ assert_eq!(*r, req(s));
+ }
+
+ let ref r = req("1.2.*");
+ assert_match_all(r, &["1.2.0", "1.2.2", "1.2.4"]);
+ assert_match_none(r, &["1.9.0", "1.0.9", "2.0.1", "0.1.3", "1.2.2-pre"]);
+
+ for s in &["1.2.x", "1.2.X"] {
+ assert_eq!(*r, req(s));
+ }
+}
+
+#[test]
+pub fn test_logical_or() {
+ // https://github.com/steveklabnik/semver/issues/57
+ let err = req_err("=1.2.3 || =2.3.4");
+ assert_to_string(err, "expected comma after patch version number, found '|'");
+
+ let err = req_err("1.1 || =1.2.3");
+ assert_to_string(err, "expected comma after minor version number, found '|'");
+
+ let err = req_err("6.* || 8.* || >= 10.*");
+ assert_to_string(err, "expected comma after minor version number, found '|'");
+}
+
+#[test]
+pub fn test_any() {
+ #[cfg(not(no_const_vec_new))]
+ let ref r = VersionReq::STAR;
+ #[cfg(no_const_vec_new)]
+ let ref r = VersionReq {
+ comparators: Vec::new(),
+ };
+ assert_match_all(r, &["0.0.1", "0.1.0", "1.0.0"]);
+}
+
+#[test]
+pub fn test_pre() {
+ let ref r = req("=2.1.1-really.0");
+ assert_match_all(r, &["2.1.1-really.0"]);
+}
+
+#[test]
+pub fn test_parse_errors() {
+ let err = req_err("\0");
+ assert_to_string(
+ err,
+ "unexpected character '\\0' while parsing major version number",
+ );
+
+ let err = req_err(">= >= 0.0.2");
+ assert_to_string(
+ err,
+ "unexpected character '>' while parsing major version number",
+ );
+
+ let err = req_err(">== 0.0.2");
+ assert_to_string(
+ err,
+ "unexpected character '=' while parsing major version number",
+ );
+
+ let err = req_err("a.0.0");
+ assert_to_string(
+ err,
+ "unexpected character 'a' while parsing major version number",
+ );
+
+ let err = req_err("1.0.0-");
+ assert_to_string(err, "empty identifier segment in pre-release identifier");
+
+ let err = req_err(">=");
+ assert_to_string(
+ err,
+ "unexpected end of input while parsing major version number",
+ );
+}
+
+#[test]
+fn test_cargo3202() {
+ let ref r = req("0.*.*");
+ assert_to_string(r, "0.*");
+ assert_match_all(r, &["0.5.0"]);
+
+ let ref r = req("0.0.*");
+ assert_to_string(r, "0.0.*");
+}
+
+#[test]
+fn test_digit_after_wildcard() {
+ let err = req_err("*.1");
+ assert_to_string(err, "unexpected character after wildcard in version req");
+
+ let err = req_err("1.*.1");
+ assert_to_string(err, "unexpected character after wildcard in version req");
+
+ let err = req_err(">=1.*.1");
+ assert_to_string(err, "unexpected character after wildcard in version req");
+}
+
+#[test]
+fn test_eq_hash() {
+ fn calculate_hash(value: impl Hash) -> u64 {
+ let mut hasher = DefaultHasher::new();
+ value.hash(&mut hasher);
+ hasher.finish()
+ }
+
+ assert!(req("^1") == req("^1"));
+ assert!(calculate_hash(req("^1")) == calculate_hash(req("^1")));
+ assert!(req("^1") != req("^2"));
+}
+
+#[test]
+fn test_leading_digit_in_pre_and_build() {
+ for op in &["=", ">", ">=", "<", "<=", "~", "^"] {
+ // digit then alpha
+ req(&format!("{} 1.2.3-1a", op));
+ req(&format!("{} 1.2.3+1a", op));
+
+ // digit then alpha (leading zero)
+ req(&format!("{} 1.2.3-01a", op));
+ req(&format!("{} 1.2.3+01", op));
+
+ // multiple
+ req(&format!("{} 1.2.3-1+1", op));
+ req(&format!("{} 1.2.3-1-1+1-1-1", op));
+ req(&format!("{} 1.2.3-1a+1a", op));
+ req(&format!("{} 1.2.3-1a-1a+1a-1a-1a", op));
+ }
+}
+
+#[test]
+fn test_wildcard_and_another() {
+ let err = req_err("*, 0.20.0-any");
+ assert_to_string(
+ err,
+ "wildcard req (*) must be the only comparator in the version req",
+ );
+
+ let err = req_err("0.20.0-any, *");
+ assert_to_string(
+ err,
+ "wildcard req (*) must be the only comparator in the version req",
+ );
+
+ let err = req_err("0.20.0-any, *, 1.0");
+ assert_to_string(
+ err,
+ "wildcard req (*) must be the only comparator in the version req",
+ );
+}
diff --git a/third_party/rust/semver/tests/util/mod.rs b/third_party/rust/semver/tests/util/mod.rs
new file mode 100644
--- /dev/null
+++ b/third_party/rust/semver/tests/util/mod.rs
@@ -0,0 +1,39 @@
+#![allow(dead_code)]
+
+use semver::{BuildMetadata, Error, Prerelease, Version, VersionReq};
+use std::fmt::Display;
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn version(text: &str) -> Version {
+ Version::parse(text).unwrap()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn version_err(text: &str) -> Error {
+ Version::parse(text).unwrap_err()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn req(text: &str) -> VersionReq {
+ VersionReq::parse(text).unwrap()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn req_err(text: &str) -> Error {
+ VersionReq::parse(text).unwrap_err()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn prerelease(text: &str) -> Prerelease {
+ Prerelease::new(text).unwrap()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn build_metadata(text: &str) -> BuildMetadata {
+ BuildMetadata::new(text).unwrap()
+}
+
+#[cfg_attr(not(no_track_caller), track_caller)]
+pub(super) fn assert_to_string(value: impl Display, expected: &str) {
+ assert_eq!(value.to_string(), expected);
+}
diff --git a/toolkit/library/rust/shared/Cargo.toml b/toolkit/library/rust/shared/Cargo.toml
--- a/toolkit/library/rust/shared/Cargo.toml
+++ b/toolkit/library/rust/shared/Cargo.toml
@@ -16,17 +16,17 @@ nsstring = { path = "../../../../xpcom/r
netwerk_helper = { path = "../../../../netwerk/base/rust-helper" }
xpcom = { path = "../../../../xpcom/rust/xpcom" }
prefs_parser = { path = "../../../../modules/libpref/parser" }
static_prefs = { path = "../../../../modules/libpref/init/static_prefs" }
profiler_helper = { path = "../../../../tools/profiler/rust-helper", optional = true }
mozurl = { path = "../../../../netwerk/base/mozurl" }
webrender_bindings = { path = "../../../../gfx/webrender_bindings" }
cubeb-coreaudio = { git = "https://github.com/mozilla/cubeb-coreaudio-rs", rev = "44eca95823bb57e964cf7b6d9791ed2ccb4b2108", optional = true }
-cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="df4dc0288b07b865440f4c7e41ca49ca9ccffc63", optional = true, features=["pulse-dlopen"] }
+cubeb-pulse = { git = "https://github.com/mozilla/cubeb-pulse-rs", rev="1f1fe1e08e01a9a534ec7f079702a583a0899ce7", optional = true, features=["pulse-dlopen"] }
cubeb-sys = { version = "0.10", optional = true, features=["gecko-in-tree"] }
audioipc2-client = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
audioipc2-server = { git = "https://github.com/kinetiknz/audioipc-2", rev = "85e9839059f4bf8f68130825b8fd02c39a6a51b9", optional = true } # macos (v2) branch
audioipc-client = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
audioipc-server = { git = "https://github.com/mozilla/audioipc-2", rev = "c144368c4e084ec0f076af6262970655c2d99e8d", optional = true }
encoding_glue = { path = "../../../../intl/encoding_glue" }
authenticator = "0.3.1"
gkrust_utils = { path = "../../../../xpcom/rust/gkrust_utils" }
diff --git a/xpcom/rust/gkrust_utils/Cargo.toml b/xpcom/rust/gkrust_utils/Cargo.toml
--- a/xpcom/rust/gkrust_utils/Cargo.toml
+++ b/xpcom/rust/gkrust_utils/Cargo.toml
@@ -1,8 +1,8 @@
[package]
name = "gkrust_utils"
version = "0.1.0"
authors = ["Jonathan Kingston <jkt@mozilla.com>"]
[dependencies]
-semver = "0.9"
+semver = "1.0"
nsstring = { path = "../nsstring" }
2022-09-22 13:16:08 +00:00
diff --git a/third_party/rust/packed_simd_2/Cargo.toml b/third_party/rust/packed_simd_2/Cargo.toml
--- a/third_party/rust/packed_simd_2/Cargo.toml
+++ b/third_party/rust/packed_simd_2/Cargo.toml
@@ -24,7 +24,7 @@ codecov = { repository = "rust-lang/pack
core_arch = { version = "0.1.5", optional = true }
[build-dependencies]
-rustc_version = "0.2"
+rustc_version = "0.4"
[features]
default = []
diff --git a/third_party/rust/packed_simd_2/.cargo-checksum.json b/third_party/rust/packed_simd_2/.cargo-checksum.json
--- a/third_party/rust/packed_simd_2/.cargo-checksum.json
+++ b/third_party/rust/packed_simd_2/.cargo-checksum.json
@@ -1,1 +1,1 @@
-{"files":{".appveyor.yml":"f1ed01850e0d725f9498f52a1a63ddf40702ad6e0bf5b2d7c4c04d76e96794a3",".travis.yml":"30a61a5ec53355fc1f3585e1690280308c2b7961701abc11e8389b235b647178","Cargo.toml":"e76b42f3247fccb7174046c499bfaae5430d83cadeb8140259fcae34613483cf","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fa4dd64f66972217d35b7653338c9e2011ccd8f3008ae7c0103272d4287f9b1d","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"a766fba121243a9b617432c592873801adb74c3a2f4a24d9d45859b8ce9357fc","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"0f1746108cc30bf9b9ba45bcde7b19fc1a8bdf5b0258035b4eb8dc69b75efac4","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"786f799d0b56eb54d7b6c4b00e1aed4ce81776e14e44767e083c89d014b72004","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"e8bc363837cd9c2d8b22402acb8c1c329efc11ba5d12170603d2fe2eae9da059","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"47998d45b781d797b9e6085ebe898d90de0c952b54537a8db4e8d7503eb032d9","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"93fb44df3d7fd31ead158570667c97b5076a05c3d968af4a84bc13819a8f2db8","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"da1c39a3ff1fe22e41395fa7c8934e90b4c1788e551b9aec6e38bfd94effc437","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"5a022299f56730cf8c432a07391e95e199cfa36dc8da2a96c9d185c8de93e913","ci/docker/x86_64-linux-android/Dockerfile":"685040273cf350d5509e580ac451555efa19790c8723ca2af066adadc6880ad2","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab
\ No newline at end of file
+{"files":{".appveyor.yml":"f1ed01850e0d725f9498f52a1a63ddf40702ad6e0bf5b2d7c4c04d76e96794a3",".travis.yml":"30a61a5ec53355fc1f3585e1690280308c2b7961701abc11e8389b235b647178","Cargo.toml":"2cab084b3d55d0b307788b02a6206a3ec39fee027535dc62d6421bce70e2e2c1","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"fa4dd64f66972217d35b7653338c9e2011ccd8f3008ae7c0103272d4287f9b1d","bors.toml":"dee881dc69b9b7834e4eba5d95c3ed5a416d4628815a167d6a22d4cb4fb064b8","build.rs":"a766fba121243a9b617432c592873801adb74c3a2f4a24d9d45859b8ce9357fc","ci/all.sh":"2ae6b2445b4db83833e40b37efd0016c6b9879ee988b9b3ef94db5439a3e1606","ci/android-install-ndk.sh":"0f1746108cc30bf9b9ba45bcde7b19fc1a8bdf5b0258035b4eb8dc69b75efac4","ci/android-install-sdk.sh":"3490432022c5c8f5a115c084f7a9aca1626f96c0c87ffb62019228c4346b47e4","ci/android-sysimage.sh":"ebf4e5daa1f0fe1b2092b79f0f3f161c4c4275cb744e52352c4d81ab451e4c5a","ci/benchmark.sh":"b61d19ef6b90deba8fb79dee74c8b062d94844676293da346da87bb78a9a49a4","ci/deploy_and_run_on_ios_simulator.rs":"ec8ecf82d92072676aa47f0d1a3d021b60a7ae3531153ef12d2ff4541fc294dc","ci/docker/aarch64-linux-android/Dockerfile":"ace2e7d33c87bc0f6d3962a4a3408c04557646f7f51ab99cfbf574906796b016","ci/docker/aarch64-unknown-linux-gnu/Dockerfile":"da88c0d50f16dc08448c7fdf1fa5ed2cbe576acf9e7dd85b5b818621b2a8c702","ci/docker/arm-linux-androideabi/Dockerfile":"370e55d3330a413a3ccf677b3afb3e0ef9018a5fab263faa97ae8ac017fc2286","ci/docker/arm-unknown-linux-gnueabi/Dockerfile":"bb5f8ae890707c128652290ffc544447643bf12037ddd73c6ad6989f848cb380","ci/docker/arm-unknown-linux-gnueabihf/Dockerfile":"1afaefcbc05b740859acd4e067bc92439be6bcbe8f2e9678474fb434bcd398d9","ci/docker/armv7-unknown-linux-gnueabihf/Dockerfile":"8282ea707a94109beed47a57574755e2d58401735904a03f85fb64c578c53b4f","ci/docker/i586-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/i686-unknown-linux-gnu/Dockerfile":"49792922269f371bd29da4727e9085101b27be67a6b97755d0196c63317f7abb","ci/docker/mips-unknown-linux-gnu/Dockerfile":"b2ebc25797612c4f8395fe9d407725156044955bfbcf442036b7f55b43a5f9da","ci/docker/mips64-unknown-linux-gnuabi64/Dockerfile":"b0c1692ac65bc56dd30494b1993d8e929c48cc9c4b92029b7c7592af6d4f9220","ci/docker/mips64el-unknown-linux-gnuabi64/Dockerfile":"4e9249c179300138141d0b2b7401b11897f64aed69f541f078c1db4594df2827","ci/docker/mipsel-unknown-linux-musl/Dockerfile":"3164c52b0dcbb01afa78292b15b5c43503ccf0491cf6eb801ec2bf22ae274e52","ci/docker/powerpc-unknown-linux-gnu/Dockerfile":"786f799d0b56eb54d7b6c4b00e1aed4ce81776e14e44767e083c89d014b72004","ci/docker/powerpc64-unknown-linux-gnu/Dockerfile":"e8bc363837cd9c2d8b22402acb8c1c329efc11ba5d12170603d2fe2eae9da059","ci/docker/powerpc64le-unknown-linux-gnu/Dockerfile":"47998d45b781d797b9e6085ebe898d90de0c952b54537a8db4e8d7503eb032d9","ci/docker/s390x-unknown-linux-gnu/Dockerfile":"93fb44df3d7fd31ead158570667c97b5076a05c3d968af4a84bc13819a8f2db8","ci/docker/sparc64-unknown-linux-gnu/Dockerfile":"da1c39a3ff1fe22e41395fa7c8934e90b4c1788e551b9aec6e38bfd94effc437","ci/docker/thumbv7neon-linux-androideabi/Dockerfile":"c2decd5591bd7a09378901bef629cd944acf052eb55e4f35b79eb9cb4d62246a","ci/docker/thumbv7neon-unknown-linux-gnueabihf/Dockerfile":"51955a8bf3c4d440f47382af6f5426ebff94ab01a04da36175babda9a057740f","ci/docker/wasm32-unknown-unknown/Dockerfile":"5a022299f56730cf8c432a07391e95e199cfa36dc8da2a96c9d185c8de93e913","ci/docker/x86_64-linux-android/Dockerfile":"685040273cf350d5509e580ac451555efa19790c8723ca2af066adadc6880ad2","ci/docker/x86_64-unknown-linux-gnu-emulated/Dockerfile":"44b6203d9290bfdc53d81219f0937e1110847a23dd982ec8c4de388354f01536","ci/docker/x86_64-unknown-linux-gnu/Dockerfile":"7f4e3ca5fa288ea70edb4d1f75309708cd30b192e2e4444e61c4d5b3b58f89cf","ci/dox.sh":"434e9611c52e389312d2b03564adf09429f10cc76fe66a8644adb104903b87b7","ci/linux-s390x.sh":"d6b732d7795b4ba131326aff893bca6228a7d2eb0e9402f135705413dbbe0dce","ci/linux-sparc64.sh":"c92966838b1ab
\ No newline at end of file