summaryrefslogtreecommitdiffstats
path: root/vendor/semver/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/semver/src')
-rw-r--r--vendor/semver/src/backport.rs51
-rw-r--r--vendor/semver/src/display.rs165
-rw-r--r--vendor/semver/src/error.rs124
-rw-r--r--vendor/semver/src/eval.rs181
-rw-r--r--vendor/semver/src/identifier.rs400
-rw-r--r--vendor/semver/src/impls.rs156
-rw-r--r--vendor/semver/src/lib.rs543
-rw-r--r--vendor/semver/src/parse.rs405
-rw-r--r--vendor/semver/src/serde.rs109
9 files changed, 2134 insertions, 0 deletions
diff --git a/vendor/semver/src/backport.rs b/vendor/semver/src/backport.rs
new file mode 100644
index 000000000..c7751b29f
--- /dev/null
+++ b/vendor/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/vendor/semver/src/display.rs b/vendor/semver/src/display.rs
new file mode 100644
index 000000000..3c2871bb9
--- /dev/null
+++ b/vendor/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/vendor/semver/src/error.rs b/vendor/semver/src/error.rs
new file mode 100644
index 000000000..a514e3f11
--- /dev/null
+++ b/vendor/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/vendor/semver/src/eval.rs b/vendor/semver/src/eval.rs
new file mode 100644
index 000000000..e6e38949a
--- /dev/null
+++ b/vendor/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/vendor/semver/src/identifier.rs b/vendor/semver/src/identifier.rs
new file mode 100644
index 000000000..170a4e05e
--- /dev/null
+++ b/vendor/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/vendor/semver/src/impls.rs b/vendor/semver/src/impls.rs
new file mode 100644
index 000000000..c3b6c6013
--- /dev/null
+++ b/vendor/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/vendor/semver/src/lib.rs b/vendor/semver/src/lib.rs
new file mode 100644
index 000000000..5185b752d
--- /dev/null
+++ b/vendor/semver/src/lib.rs
@@ -0,0 +1,543 @@
+//! [![github]](https://github.com/dtolnay/semver)&ensp;[![crates-io]](https://crates.io/crates/semver)&ensp;[![docs-rs]](https://docs.rs/semver)
+//!
+//! [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&logo=docs.rs
+//!
+//! <br>
+//!
+//! A parser and evaluator for Cargo's flavor of Semantic Versioning.
+//!
+//! 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.
+//!
+//! <br>
+//!
+//! # Example
+//!
+//! ```
+//! use semver::{BuildMetadata, Prerelease, Version, VersionReq};
+//!
+//! fn main() {
+//! let req = VersionReq::parse(">=1.2.3, <1.8.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));
+//!
+//! // Check whether it matches 1.3.0 (yes it does)
+//! let version = Version::parse("1.3.0").unwrap();
+//! assert!(req.matches(&version));
+//! }
+//! ```
+//!
+//! <br><br>
+//!
+//! # Scope of this crate
+//!
+//! Besides Cargo, several other package ecosystems and package managers for
+//! other languages also use SemVer:&ensp;RubyGems/Bundler for Ruby, npm for
+//! JavaScript, Composer for PHP, CocoaPods for Objective-C...
+//!
+//! 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.
+//!
+//! [Specifying Dependencies]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
+
+#![doc(html_root_url = "https://docs.rs/semver/1.0.12")]
+#![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" &lt; "1.5.0" as ASCIIbetically compared strings and 1.19 &lt; 1.5
+/// as real numbers.
+///
+/// - When major, minor, and patch are equal, a pre-release version is
+/// considered less than the ordinary release:&ensp;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:&ensp;`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:&ensp;`1.0.0-pre12` is less than `1.0.0-pre8`.
+///
+/// - Any numeric identifier is always less than any non-numeric
+/// identifier:&ensp;`1.0.0-pre.1` is less than `1.0.0-pre.x`.
+///
+/// Example:&ensp;`1.0.0-alpha`&ensp;&lt;&ensp;`1.0.0-alpha.1`&ensp;&lt;&ensp;`1.0.0-alpha.beta`&ensp;&lt;&ensp;`1.0.0-beta`&ensp;&lt;&ensp;`1.0.0-beta.2`&ensp;&lt;&ensp;`1.0.0-beta.11`&ensp;&lt;&ensp;`1.0.0-rc.1`&ensp;&lt;&ensp;`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
+/// - &ensp;**`=I.J.K`**&emsp;&mdash;&emsp;exactly the version I.J.K
+/// - &ensp;**`=I.J`**&emsp;&mdash;&emsp;equivalent to `>=I.J.0, <I.(J+1).0`
+/// - &ensp;**`=I`**&emsp;&mdash;&emsp;equivalent to `>=I.0.0, <(I+1).0.0`
+///
+/// # Op::Greater
+/// - &ensp;**`>I.J.K`**
+/// - &ensp;**`>I.J`**&emsp;&mdash;&emsp;equivalent to `>=I.(J+1).0`
+/// - &ensp;**`>I`**&emsp;&mdash;&emsp;equivalent to `>=(I+1).0.0`
+///
+/// # Op::GreaterEq
+/// - &ensp;**`>=I.J.K`**
+/// - &ensp;**`>=I.J`**&emsp;&mdash;&emsp;equivalent to `>=I.J.0`
+/// - &ensp;**`>=I`**&emsp;&mdash;&emsp;equivalent to `>=I.0.0`
+///
+/// # Op::Less
+/// - &ensp;**`<I.J.K`**
+/// - &ensp;**`<I.J`**&emsp;&mdash;&emsp;equivalent to `<I.J.0`
+/// - &ensp;**`<I`**&emsp;&mdash;&emsp;equivalent to `<I.0.0`
+///
+/// # Op::LessEq
+/// - &ensp;**`<=I.J.K`**
+/// - &ensp;**`<=I.J`**&emsp;&mdash;&emsp;equivalent to `<I.(J+1).0`
+/// - &ensp;**`<=I`**&emsp;&mdash;&emsp;equivalent to `<(I+1).0.0`
+///
+/// # Op::Tilde&emsp;("patch" updates)
+/// *Tilde requirements allow the **patch** part of the semver version (the third number) to increase.*
+/// - &ensp;**`~I.J.K`**&emsp;&mdash;&emsp;equivalent to `>=I.J.K, <I.(J+1).0`
+/// - &ensp;**`~I.J`**&emsp;&mdash;&emsp;equivalent to `=I.J`
+/// - &ensp;**`~I`**&emsp;&mdash;&emsp;equivalent to `=I`
+///
+/// # Op::Caret&emsp;("compatible" updates)
+/// *Caret requirements allow parts that are **right of the first nonzero** part of the semver version to increase.*
+/// - &ensp;**`^I.J.K`**&ensp;(for I\>0)&emsp;&mdash;&emsp;equivalent to `>=I.J.K, <(I+1).0.0`
+/// - &ensp;**`^0.J.K`**&ensp;(for J\>0)&emsp;&mdash;&emsp;equivalent to `>=0.J.K, <0.(J+1).0`
+/// - &ensp;**`^0.0.K`**&emsp;&mdash;&emsp;equivalent to `=0.0.K`
+/// - &ensp;**`^I.J`**&ensp;(for I\>0 or J\>0)&emsp;&mdash;&emsp;equivalent to `^I.J.0`
+/// - &ensp;**`^0.0`**&emsp;&mdash;&emsp;equivalent to `=0.0`
+/// - &ensp;**`^I`**&emsp;&mdash;&emsp;equivalent to `=I`
+///
+/// # Op::Wildcard
+/// - &ensp;**`I.J.*`**&emsp;&mdash;&emsp;equivalent to `=I.J`
+/// - &ensp;**`I.*`**&ensp;or&ensp;**`I.*.*`**&emsp;&mdash;&emsp;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,
+}
+
+/// 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> &mdash; the most common style
+/// for numbering pre-releases.
+///
+/// - **[pest]** <code>1.0.0-<b>beta.8</b></code>,&ensp;<code>1.0.0-<b>rc.0</b></code>
+/// &mdash; this crate makes a distinction between betas and release
+/// candidates.
+///
+/// - **[sassers]** <code>0.11.0-<b>shitshow</b></code> &mdash; ???.
+///
+/// - **[atomic-utils]** <code>0.0.0-<b>reserved</b></code> &mdash; 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` &lt;
+/// `alpha.11` as intended, but `alpha11` &lt; `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:&ensp;`alpha`&ensp;&lt;&ensp;`alpha.85`&ensp;&lt;&ensp;`alpha.90`&ensp;&lt;&ensp;`alpha.200`&ensp;&lt;&ensp;`alpha.0a`&ensp;&lt;&ensp;`alpha.1a0`&ensp;&lt;&ensp;`alpha.a`&ensp;&lt;&ensp;`beta`
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
+pub struct Prerelease {
+ identifier: Identifier,
+}
+
+/// 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> &mdash; 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> &mdash; 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> &mdash; 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> &mdash; 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:&ensp;`demo`&ensp;&lt;&ensp;`demo.85`&ensp;&lt;&ensp;`demo.90`&ensp;&lt;&ensp;`demo.090`&ensp;&lt;&ensp;`demo.200`&ensp;&lt;&ensp;`demo.1a0`&ensp;&lt;&ensp;`demo.a`&ensp;&lt;&ensp;`memo`
+#[derive(Default, Clone, Eq, PartialEq, Hash)]
+pub struct BuildMetadata {
+ identifier: Identifier,
+}
+
+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` &mdash; 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` &mdash; a numeric component has a leading zero.
+ ///
+ /// - `1.0.unknown` &mdash; unexpected character in one of the components.
+ ///
+ /// - `1.0.0-` or `1.0.0+` &mdash; the pre-release or build metadata are
+ /// indicated present but empty.
+ ///
+ /// - `1.0.0-alpha_123` &mdash; pre-release or build metadata have something
+ /// outside the allowed characters, which are `0-9`, `A-Z`, `a-z`, `-`,
+ /// and `.` (dot).
+ ///
+ /// - `23456789999999999999.0.0` &mdash; 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(),
+ };
+
+ /// Create `VersionReq` by parsing from string representation.
+ ///
+ /// # Errors
+ ///
+ /// Possible reasons for the parse to fail include:
+ ///
+ /// - `>a.b` &mdash; unexpected characters in the partial version.
+ ///
+ /// - `@1.0.0` &mdash; unrecognized comparison operator.
+ ///
+ /// - `^1.0.0, ` &mdash; unexpected end of input.
+ ///
+ /// - `>=1.0 <2.0` &mdash; missing comma between comparators.
+ ///
+ /// - `*.*` &mdash; 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)
+ }
+
+ pub fn matches(&self, version: &Version) -> bool {
+ eval::matches_comparator(self, version)
+ }
+}
+
+impl Prerelease {
+ // Work around https://github.com/rust-lang/rust/issues/97933
+ #[cfg(all(doc, semver_rustdoc_workaround))]
+ pub const EMPTY: Self = "";
+
+ #[cfg(not(all(doc, semver_rustdoc_workaround)))]
+ 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()
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.identifier.is_empty()
+ }
+}
+
+impl BuildMetadata {
+ // Work around https://github.com/rust-lang/rust/issues/97933
+ #[cfg(all(doc, semver_rustdoc_workaround))]
+ pub const EMPTY: Self = "";
+
+ #[cfg(not(all(doc, semver_rustdoc_workaround)))]
+ 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/vendor/semver/src/parse.rs b/vendor/semver/src/parse.rs
new file mode 100644
index 000000000..6a8f6ffba
--- /dev/null
+++ b/vendor/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.first() == Some(&b'=') {
+ (Op::Exact, &input[1..])
+ } else if bytes.first() == Some(&b'>') {
+ if bytes.get(1) == Some(&b'=') {
+ (Op::GreaterEq, &input[2..])
+ } else {
+ (Op::Greater, &input[1..])
+ }
+ } else if bytes.first() == Some(&b'<') {
+ if bytes.get(1) == Some(&b'=') {
+ (Op::LessEq, &input[2..])
+ } else {
+ (Op::Less, &input[1..])
+ }
+ } else if bytes.first() == Some(&b'~') {
+ (Op::Tilde, &input[1..])
+ } else if bytes.first() == 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/vendor/semver/src/serde.rs b/vendor/semver/src/serde.rs
new file mode 100644
index 000000000..1fcc7d87f
--- /dev/null
+++ b/vendor/semver/src/serde.rs
@@ -0,0 +1,109 @@
+use crate::{Comparator, 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 Serialize for Comparator {
+ 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)
+ }
+}
+
+impl<'de> Deserialize<'de> for Comparator {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: Deserializer<'de>,
+ {
+ struct ComparatorVisitor;
+
+ impl<'de> Visitor<'de> for ComparatorVisitor {
+ type Value = Comparator;
+
+ fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str("semver comparator")
+ }
+
+ fn visit_str<E>(self, string: &str) -> Result<Self::Value, E>
+ where
+ E: Error,
+ {
+ string.parse().map_err(Error::custom)
+ }
+ }
+
+ deserializer.deserialize_str(ComparatorVisitor)
+ }
+}