summaryrefslogtreecommitdiffstats
path: root/vendor/rustc-semver
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /vendor/rustc-semver
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/rustc-semver')
-rw-r--r--vendor/rustc-semver/.cargo-checksum.json1
-rw-r--r--vendor/rustc-semver/CODE_OF_CONDUCT.md78
-rw-r--r--vendor/rustc-semver/COPYRIGHT6
-rw-r--r--vendor/rustc-semver/Cargo.toml24
-rw-r--r--vendor/rustc-semver/LICENSE-APACHE201
-rw-r--r--vendor/rustc-semver/LICENSE-MIT21
-rw-r--r--vendor/rustc-semver/README.md60
-rw-r--r--vendor/rustc-semver/cov.sh34
-rw-r--r--vendor/rustc-semver/rust-toolchain1
-rw-r--r--vendor/rustc-semver/src/lib.rs665
10 files changed, 1091 insertions, 0 deletions
diff --git a/vendor/rustc-semver/.cargo-checksum.json b/vendor/rustc-semver/.cargo-checksum.json
new file mode 100644
index 000000000..5b5ebc2e6
--- /dev/null
+++ b/vendor/rustc-semver/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CODE_OF_CONDUCT.md":"db2ffb3942498eedec1424ae1d7fcb1b86563a008a6312f9d04a8f6aa11d2077","COPYRIGHT":"acc1fde07c321191aa7ae8d0f51f85c47d1d927da0ee23fcab74876079a893a2","Cargo.toml":"c935404a26ff20dd1c99bb21a6a7ba05eb322ab4fae89803378207acf43c1c8c","LICENSE-APACHE":"042bdce5c48778791dc426d40035721df1331c79daf7da306f6904cc76b471fa","LICENSE-MIT":"f60a51f5a545fcf856eca49cdb61c7b54af862889a91b4c973cbd8013d86ef1d","README.md":"314996b2c7492689cdd3da63d8bb06a7246af9d2d2c7765e180ff1d779b0f22d","cov.sh":"db16152c8992f9291076f35083b17141f48b246638f2a9015d435f3773c2554e","rust-toolchain":"2b92ea252be0fbc26f70317cdaa7b6411ea634b50d55338cd8c495e4dbf25d1d","src/lib.rs":"978fc659a78f71e7a9f0b15fbdbf9113b2ad5ac30718d97fcde782ae0bfbc05d"},"package":"5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84"} \ No newline at end of file
diff --git a/vendor/rustc-semver/CODE_OF_CONDUCT.md b/vendor/rustc-semver/CODE_OF_CONDUCT.md
new file mode 100644
index 000000000..ff38ab01b
--- /dev/null
+++ b/vendor/rustc-semver/CODE_OF_CONDUCT.md
@@ -0,0 +1,78 @@
+
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+In the interest of fostering an open and welcoming environment, we as
+contributors and maintainers pledge to make participation in our project and our
+community a harassment-free experience for everyone, regardless of age, body
+size, disability, ethnicity, sex characteristics, gender identity and
+expression, level of experience, education, socio-economic status, nationality,
+personal appearance, race, religion, or sexual identity and orientation.
+
+## Our Standards
+
+Examples of behavior that contributes to creating a positive environment
+include:
+
+* Using welcoming and inclusive language
+* Being respectful of differing viewpoints and experiences
+* Gracefully accepting constructive criticism
+* Focusing on what is best for the community
+* Showing empathy towards other community members
+
+Examples of unacceptable behavior by participants include:
+
+* The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+* Trolling, insulting/derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+ professional setting
+
+## Our Responsibilities
+
+Project maintainers are responsible for clarifying the standards of acceptable
+behavior and are expected to take appropriate and fair corrective action in
+response to any instances of unacceptable behavior.
+
+Project maintainers have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, or to ban temporarily or permanently any
+contributor for other behaviors that they deem inappropriate, threatening,
+offensive, or harmful.
+
+## Scope
+
+This Code of Conduct applies within all project spaces, and it also applies when
+an individual is representing the project or its community in public spaces.
+Examples of representing a project or community include using an official
+project e-mail address, posting via an official social media account, or acting
+as an appointed representative at an online or offline event. Representation of
+a project may be further defined and clarified by project maintainers.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported by contacting the project team at hello@flip1995.com. All complaints
+will be reviewed and investigated and will result in a response that is deemed
+necessary and appropriate to the circumstances. The project team is obligated to
+maintain confidentiality with regard to the reporter of an incident. Further
+details of specific enforcement policies may be posted separately.
+
+Project maintainers who do not follow or enforce the Code of Conduct in good
+faith may face temporary or permanent repercussions as determined by other
+members of the project's leadership.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 1.4, available at
+https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see
+https://www.contributor-covenant.org/faq
diff --git a/vendor/rustc-semver/COPYRIGHT b/vendor/rustc-semver/COPYRIGHT
new file mode 100644
index 000000000..a0bca23e9
--- /dev/null
+++ b/vendor/rustc-semver/COPYRIGHT
@@ -0,0 +1,6 @@
+Copyright 2020 Philipp Krones
+
+Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+https://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+https://opensource.org/licenses/MIT>, at your option. Files in the project may
+not be copied, modified, or distributed except according to those terms.
diff --git a/vendor/rustc-semver/Cargo.toml b/vendor/rustc-semver/Cargo.toml
new file mode 100644
index 000000000..0996d5189
--- /dev/null
+++ b/vendor/rustc-semver/Cargo.toml
@@ -0,0 +1,24 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+edition = "2018"
+name = "rustc-semver"
+version = "1.1.0"
+authors = ["flip1995 <hello@philkrones.com>"]
+description = "Crate for parsing versions of Rust releases"
+keywords = ["parser", "version", "semver", "rustc"]
+categories = ["parsing", "config"]
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/flip1995/rustc-semver"
+
+[dependencies]
diff --git a/vendor/rustc-semver/LICENSE-APACHE b/vendor/rustc-semver/LICENSE-APACHE
new file mode 100644
index 000000000..87ab8aa4d
--- /dev/null
+++ b/vendor/rustc-semver/LICENSE-APACHE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright 2020 Philipp Krones
+
+ 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/vendor/rustc-semver/LICENSE-MIT b/vendor/rustc-semver/LICENSE-MIT
new file mode 100644
index 000000000..76c1579fb
--- /dev/null
+++ b/vendor/rustc-semver/LICENSE-MIT
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Philipp Krones
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/vendor/rustc-semver/README.md b/vendor/rustc-semver/README.md
new file mode 100644
index 000000000..d5ee06909
--- /dev/null
+++ b/vendor/rustc-semver/README.md
@@ -0,0 +1,60 @@
+[![Coverage](https://img.shields.io/badge/dynamic/json?color=brightgreen&label=coverage&query=%24.data%5B0%5D.totals.lines.percent&suffix=%25&url=https%3A%2F%2Fraw.githubusercontent.com%2Fflip1995%2Frustc-semver%2Fgh-pages%2Fcov.json)](https://flip1995.github.io/rustc-semver/)
+[![Tests](https://github.com/flip1995/rustc-semver/workflows/Tests/badge.svg)](https://github.com/flip1995/rustc-semver/actions?query=branch%3Amaster+event%3Apush+workflow%3ATests)
+
+# Rustc Semver
+
+This crate provides a minimalistic parser for Rust versions.
+
+## Description
+
+The parser will only accept Versions in the form
+
+```text
+<major>.<minor>.<patch>
+```
+
+and 3 special versions:
+
+- `1.0.0-alpha`
+- `1.0.0-alpha.2`
+- `1.0.0-beta`
+
+This covers every version of `rustc` that were released to date.
+
+## Usage
+
+There are 2 functions to create a `RustcVersion`:
+
+1. `const RustcVersion::new(u32, u32, u32)`: This is mainly used to create
+ constants
+2. `RustcVersion::parse(&str)`: Usually you want to parse a version with this
+ function
+
+If you have a `RustcVersion` you can compare them, like you would expect:
+
+```rust
+assert!(RustcVersion::parse("1.42.0")? < RustcVersion::parse("1.43")?);
+```
+
+If you want to check whether one version meets another version according to the
+[Caret Requirements], there is the method `RustcVersion::meets`:
+
+```rust
+assert!(RustcVersion::new(1, 48, 0).meets(RustcVersion::parse("1.42")?));
+```
+
+[Caret Requirements]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
+
+## Code of Conduct
+
+This repository adopts the [Contributor Covenant Code of
+Conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct/)
+
+## License
+
+Copyright 2020 Philipp Krones
+
+Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+https://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
+https://opensource.org/licenses/MIT>, at your option. Files in the project may
+not be copied, modified, or distributed except according to those terms.
diff --git a/vendor/rustc-semver/cov.sh b/vendor/rustc-semver/cov.sh
new file mode 100644
index 000000000..e3b42c7e8
--- /dev/null
+++ b/vendor/rustc-semver/cov.sh
@@ -0,0 +1,34 @@
+cargo clean
+rm -rf cov/rustc-semver/
+rm -rf cov/*
+
+RUSTFLAGS="-Zinstrument-coverage" \
+LLVM_PROFILE_FILE="$(pwd)/cov/rustc-semver%m.profraw" \
+ cargo +nightly test
+
+llvm-profdata merge -sparse cov/rustc-semver*.profraw -o cov/rustc-semver.profdata
+
+case $1 in
+ "--json")
+ llvm-cov export \
+ --instr-profile=cov/rustc-semver.profdata \
+ --summary-only \
+ --format=text \
+ $(find target/debug/deps -executable -type f) | python3 -m json.tool > cov.json
+ ;;
+ "--html")
+ cargo install rustfilt
+ llvm-cov show \
+ --instr-profile=cov/rustc-semver.profdata \
+ --Xdemangler=rustfilt \
+ --show-line-counts-or-regions \
+ --output-dir=cov/rustc-semver \
+ --format=html \
+ $(find target/debug/deps -executable -type f)
+ ;;
+ *)
+ echo "Use with either --html or --json"
+ exit 1
+ ;;
+esac
+
diff --git a/vendor/rustc-semver/rust-toolchain b/vendor/rustc-semver/rust-toolchain
new file mode 100644
index 000000000..2bf5ad044
--- /dev/null
+++ b/vendor/rustc-semver/rust-toolchain
@@ -0,0 +1 @@
+stable
diff --git a/vendor/rustc-semver/src/lib.rs b/vendor/rustc-semver/src/lib.rs
new file mode 100644
index 000000000..86396e7b6
--- /dev/null
+++ b/vendor/rustc-semver/src/lib.rs
@@ -0,0 +1,665 @@
+#![no_std]
+
+use core::{cmp::Ordering, fmt::Display, num::ParseIntError};
+
+/// `Error` represents an Error during parsing of a [`RustcVersion`].
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum Error {
+ /// A version was passed that has too many elements seperated by `'.'`.
+ TooManyElements,
+ /// A version was passed that neither is a [`SpecialVersion`], nor a
+ /// normal [`RustcVersion`].
+ NotASpecialVersion,
+ /// A version was passed, that was either an empty string or a part of the
+ /// version was left out, e.g. `1. .3`
+ EmptyVersionPart,
+ /// A version was passed that has unallowed chracters.
+ ParseIntError,
+}
+
+impl From<ParseIntError> for Error {
+ fn from(_: ParseIntError) -> Self {
+ Self::ParseIntError
+ }
+}
+
+/// Result type for this crate
+pub type Result<T> = core::result::Result<T, Error>;
+
+/// `RustcVersion` represents a version of the Rust Compiler.
+///
+/// This struct only supports the [`NormalVersion`] format
+/// ```text
+/// major.minor.patch
+/// ```
+/// and 3 special formats represented by the [`SpecialVersion`] enum.
+///
+/// A version can be created with one of the functions [`RustcVersion::new`] or
+/// [`RustcVersion::parse`]. The [`RustcVersion::new`] method only supports the
+/// normal version format.
+///
+/// You can compare two versions, just as you would expect:
+///
+/// ```rust
+/// use rustc_semver::RustcVersion;
+///
+/// assert!(RustcVersion::new(1, 34, 0) > RustcVersion::parse("1.10").unwrap());
+/// assert!(RustcVersion::new(1, 34, 0) > RustcVersion::parse("0.9").unwrap());
+/// ```
+///
+/// This comparison is semver conform according to the [semver definition of
+/// precedence]. However, if you want to check whether one version meets
+/// another version according to the [Caret Requirements], you should use
+/// [`RustcVersion::meets`].
+///
+/// [Caret Requirements]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
+/// [semver definition of precedence]: https://semver.org/#spec-item-11
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum RustcVersion {
+ Normal(NormalVersion),
+ Special(SpecialVersion),
+}
+
+/// `NormalVersion` represents a normal version used for all releases since
+/// Rust 1.0.0.
+///
+/// This struct supports versions in the format
+/// ```test
+/// major.minor.patch
+/// ```
+#[derive(Debug, Copy, Clone)]
+pub struct NormalVersion {
+ major: u32,
+ minor: u32,
+ patch: u32,
+ omitted: OmittedParts,
+}
+
+#[derive(Debug, Copy, Clone)]
+enum OmittedParts {
+ None,
+ Minor,
+ Patch,
+}
+
+impl From<usize> for OmittedParts {
+ fn from(parts: usize) -> Self {
+ match parts {
+ 1 => Self::Minor,
+ 2 => Self::Patch,
+ 3 => Self::None,
+ _ => unreachable!(
+ "This function should never be called with `parts == 0` or `parts > 3`"
+ ),
+ }
+ }
+}
+
+/// `SpecialVersion` represents a special version from the first releases.
+///
+/// Before Rust 1.0.0, there were two alpha and one beta release, namely
+///
+/// - `1.0.0-alpha`
+/// - `1.0.0-alpha.2`
+/// - `1.0.0-beta`
+///
+/// This enum represents those releases.
+#[derive(Debug, Eq, PartialEq, Copy, Clone)]
+pub enum SpecialVersion {
+ Alpha,
+ Alpha2,
+ Beta,
+}
+
+impl PartialOrd for RustcVersion {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for RustcVersion {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match (self, other) {
+ (Self::Normal(ver), Self::Normal(o_ver)) => ver.cmp(o_ver),
+ (Self::Normal(NormalVersion { major, .. }), Self::Special(_)) => {
+ if *major >= 1 {
+ Ordering::Greater
+ } else {
+ Ordering::Less
+ }
+ }
+ (Self::Special(_), Self::Normal(NormalVersion { major, .. })) => {
+ if *major >= 1 {
+ Ordering::Less
+ } else {
+ Ordering::Greater
+ }
+ }
+ (Self::Special(s_ver), Self::Special(o_s_ver)) => s_ver.cmp(o_s_ver),
+ }
+ }
+}
+
+impl PartialOrd for NormalVersion {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for NormalVersion {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match self.major.cmp(&other.major) {
+ Ordering::Equal => match self.minor.cmp(&other.minor) {
+ Ordering::Equal => self.patch.cmp(&other.patch),
+ ord => ord,
+ },
+ ord => ord,
+ }
+ }
+}
+
+impl PartialEq for NormalVersion {
+ fn eq(&self, other: &Self) -> bool {
+ self.major == other.major && self.minor == other.minor && self.patch == other.patch
+ }
+}
+
+impl Eq for NormalVersion {}
+
+impl PartialOrd for SpecialVersion {
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl Ord for SpecialVersion {
+ fn cmp(&self, other: &Self) -> Ordering {
+ match (self, other) {
+ (Self::Alpha, Self::Alpha)
+ | (Self::Alpha2, Self::Alpha2)
+ | (Self::Beta, Self::Beta) => Ordering::Equal,
+ (Self::Alpha, _) | (Self::Alpha2, Self::Beta) => Ordering::Less,
+ (Self::Beta, _) | (Self::Alpha2, Self::Alpha) => Ordering::Greater,
+ }
+ }
+}
+
+impl Display for RustcVersion {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ Self::Normal(NormalVersion {
+ major,
+ minor,
+ patch,
+ ..
+ }) => write!(f, "{}.{}.{}", major, minor, patch),
+ Self::Special(special) => write!(f, "{}", special),
+ }
+ }
+}
+
+impl Display for SpecialVersion {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ match self {
+ Self::Alpha => write!(f, "1.0.0-alpha"),
+ Self::Alpha2 => write!(f, "1.0.0-alpha.2"),
+ Self::Beta => write!(f, "1.0.0-beta"),
+ }
+ }
+}
+
+impl From<[u32; 3]> for NormalVersion {
+ fn from(arr: [u32; 3]) -> Self {
+ NormalVersion {
+ major: arr[0],
+ minor: arr[1],
+ patch: arr[2],
+ omitted: OmittedParts::None,
+ }
+ }
+}
+
+const ACCEPTED_SPECIAL_VERSIONS: [(&str, SpecialVersion); 3] = [
+ ("1.0.0-alpha", SpecialVersion::Alpha),
+ ("1.0.0-alpha.2", SpecialVersion::Alpha2),
+ ("1.0.0-beta", SpecialVersion::Beta),
+];
+
+impl RustcVersion {
+ /// `RustcVersion::new` is a `const` constructor for a `RustcVersion`.
+ ///
+ /// This function is primarily used to construct constants, for everything
+ /// else use [`RustcVersion::parse`].
+ ///
+ /// This function only allows to construct normal versions. For special
+ /// versions, construct them directly with the [`SpecialVersion`] enum.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use rustc_semver::RustcVersion;
+ ///
+ /// const MY_FAVORITE_RUST: RustcVersion = RustcVersion::new(1, 48, 0);
+ ///
+ /// assert!(MY_FAVORITE_RUST > RustcVersion::new(1, 0, 0))
+ /// ```
+ pub const fn new(major: u32, minor: u32, patch: u32) -> Self {
+ Self::Normal(NormalVersion {
+ major,
+ minor,
+ patch,
+ omitted: OmittedParts::None,
+ })
+ }
+
+ /// `RustcVersion::parse` parses a [`RustcVersion`].
+ ///
+ /// This function can parse all normal and special versions. It is possbile
+ /// to omit parts of the version, like the patch or minor version part. So
+ /// `1`, `1.0`, and `1.0.0` are all valid inputs and will result in the
+ /// same version.
+ ///
+ /// # Errors
+ ///
+ /// This function returns an [`Error`], if the passed string is not a valid
+ /// [`RustcVersion`]
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use rustc_semver::{SpecialVersion, RustcVersion};
+ ///
+ /// let ver = RustcVersion::new(1, 0, 0);
+ ///
+ /// assert_eq!(RustcVersion::parse("1").unwrap(), ver);
+ /// assert_eq!(RustcVersion::parse("1.0").unwrap(), ver);
+ /// assert_eq!(RustcVersion::parse("1.0.0").unwrap(), ver);
+ /// assert_eq!(
+ /// RustcVersion::parse("1.0.0-alpha").unwrap(),
+ /// RustcVersion::Special(SpecialVersion::Alpha)
+ /// );
+ /// ```
+ pub fn parse(version: &str) -> Result<Self> {
+ let special_version = ACCEPTED_SPECIAL_VERSIONS.iter().find_map(|sv| {
+ if version == sv.0 {
+ Some(sv.1)
+ } else {
+ None
+ }
+ });
+ if let Some(special_version) = special_version {
+ return Ok(RustcVersion::Special(special_version));
+ }
+
+ let mut rustc_version = [0_u32; 3];
+ let mut parts = 0;
+ for (i, part) in version.split('.').enumerate() {
+ let part = part.trim();
+ if part.is_empty() {
+ return Err(Error::EmptyVersionPart);
+ }
+ if i == 3 {
+ return Err(Error::TooManyElements);
+ }
+ match str::parse(part) {
+ Ok(part) => rustc_version[i] = part,
+ Err(e) => {
+ if i == 2 {
+ return Err(Error::NotASpecialVersion);
+ } else {
+ return Err(e.into());
+ }
+ }
+ }
+
+ parts = i + 1;
+ }
+
+ let mut ver = NormalVersion::from(rustc_version);
+ ver.omitted = OmittedParts::from(parts);
+ Ok(RustcVersion::Normal(ver))
+ }
+
+ /// `RustcVersion::meets` implements a semver conform version check
+ /// according to the [Caret Requirements].
+ ///
+ /// Note that [`SpecialVersion`]s only meet themself and no other version
+ /// meets a [`SpecialVersion`]. This is because [according to semver],
+ /// special versions are considered unstable and "might not satisfy the
+ /// intended compatibility requirements as denoted by \[their\] associated
+ /// normal version".
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use rustc_semver::RustcVersion;
+ ///
+ /// assert!(RustcVersion::new(1, 30, 0).meets(RustcVersion::parse("1.29").unwrap()));
+ /// assert!(!RustcVersion::new(1, 30, 0).meets(RustcVersion::parse("1.31").unwrap()));
+ ///
+ /// assert!(RustcVersion::new(0, 2, 1).meets(RustcVersion::parse("0.2").unwrap()));
+ /// assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::parse("0.2").unwrap()));
+ /// ```
+ ///
+ /// [Caret Requirements]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#caret-requirements
+ /// [according to semver]: https://semver.org/#spec-item-9
+ pub fn meets(self, other: Self) -> bool {
+ match (self, other) {
+ (RustcVersion::Special(_), _) | (_, RustcVersion::Special(_)) => self == other,
+ (RustcVersion::Normal(ver), RustcVersion::Normal(o_ver)) => {
+ // In any case must `self` be bigger than `other`, with the major part matching
+ // the other version.
+ let mut meets = ver >= o_ver && ver.major == o_ver.major;
+
+ // In addition, the left-most non-zero digit must not be modified.
+ match o_ver.omitted {
+ OmittedParts::None => {
+ // Nothing was omitted, this means that everything must match in case of
+ // leading zeros.
+ if o_ver.major == 0 {
+ // Leading 0 in major position, check for
+ // `self.minor == other.minor`
+ meets &= ver.minor == o_ver.minor;
+
+ if o_ver.minor == 0 {
+ // Leading 0 in minor position, check for
+ // `self.patch == other.patch`.
+ meets &= ver.patch == o_ver.patch;
+ }
+ }
+ }
+ OmittedParts::Patch => {
+ // The patch version was omitted, this means the patch version of `self`
+ // does not have to match the patch version of `other`.
+ if o_ver.major == 0 {
+ meets &= ver.minor == o_ver.minor;
+ }
+ }
+ OmittedParts::Minor => {
+ // The minor (and patch) version was omitted, this means
+ // the minor and patch version of `self` do not have to
+ // match the minor and patch version of `other`
+ }
+ }
+
+ meets
+ }
+ }
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use super::*;
+
+ #[test]
+ fn omitted_parts() {
+ assert_eq!(
+ RustcVersion::parse("1.0.0").unwrap(),
+ RustcVersion::new(1, 0, 0)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0").unwrap(),
+ RustcVersion::new(1, 0, 0)
+ );
+ assert_eq!(
+ RustcVersion::parse("1").unwrap(),
+ RustcVersion::new(1, 0, 0)
+ );
+ }
+
+ #[test]
+ fn special_versions() {
+ assert_eq!(
+ RustcVersion::parse("1.0.0-alpha").unwrap(),
+ RustcVersion::Special(SpecialVersion::Alpha)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-alpha.2").unwrap(),
+ RustcVersion::Special(SpecialVersion::Alpha2)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-beta").unwrap(),
+ RustcVersion::Special(SpecialVersion::Beta)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-sigma"),
+ Err(Error::NotASpecialVersion)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0beta"),
+ Err(Error::NotASpecialVersion)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.1.0-beta"),
+ Err(Error::NotASpecialVersion)
+ );
+ }
+
+ #[test]
+ fn less_than() {
+ let bigger = RustcVersion::new(1, 30, 1);
+ assert!(RustcVersion::parse("1.0.0").unwrap() < bigger);
+ assert!(RustcVersion::parse("1.0").unwrap() < bigger);
+ assert!(RustcVersion::parse("1").unwrap() < bigger);
+ assert!(RustcVersion::parse("1.30").unwrap() < bigger);
+ assert!(RustcVersion::parse("1.0.0-beta").unwrap() < bigger);
+ assert!(RustcVersion::parse("0.9").unwrap() < RustcVersion::Special(SpecialVersion::Alpha));
+ assert!(
+ RustcVersion::parse("1.0.0-alpha").unwrap()
+ < RustcVersion::Special(SpecialVersion::Alpha2)
+ );
+ assert!(
+ RustcVersion::parse("1.0.0-alpha").unwrap()
+ < RustcVersion::Special(SpecialVersion::Beta)
+ );
+ assert!(
+ RustcVersion::parse("1.0.0-alpha.2").unwrap()
+ < RustcVersion::Special(SpecialVersion::Beta)
+ );
+ }
+
+ #[test]
+ fn equal() {
+ assert_eq!(
+ RustcVersion::parse("1.22.0").unwrap(),
+ RustcVersion::new(1, 22, 0)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.22").unwrap(),
+ RustcVersion::new(1, 22, 0)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.48.1").unwrap(),
+ RustcVersion::new(1, 48, 1)
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-alpha")
+ .unwrap()
+ .cmp(&RustcVersion::Special(SpecialVersion::Alpha)),
+ Ordering::Equal
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-alpha.2")
+ .unwrap()
+ .cmp(&RustcVersion::Special(SpecialVersion::Alpha2)),
+ Ordering::Equal
+ );
+ assert_eq!(
+ RustcVersion::parse("1.0.0-beta")
+ .unwrap()
+ .cmp(&RustcVersion::Special(SpecialVersion::Beta)),
+ Ordering::Equal
+ );
+ }
+
+ #[test]
+ fn greater_than() {
+ let less = RustcVersion::new(1, 15, 1);
+ assert!(RustcVersion::parse("1.16.0").unwrap() > less);
+ assert!(RustcVersion::parse("1.16").unwrap() > less);
+ assert!(RustcVersion::parse("2").unwrap() > less);
+ assert!(RustcVersion::parse("1.15.2").unwrap() > less);
+ assert!(
+ RustcVersion::parse("1.0.0-beta").unwrap()
+ > RustcVersion::Special(SpecialVersion::Alpha2)
+ );
+ assert!(
+ RustcVersion::parse("1.0.0-beta").unwrap()
+ > RustcVersion::Special(SpecialVersion::Alpha)
+ );
+ assert!(
+ RustcVersion::parse("1.0.0-alpha.2").unwrap()
+ > RustcVersion::Special(SpecialVersion::Alpha)
+ );
+ assert!(RustcVersion::parse("1.0.0-alpha.2").unwrap() > RustcVersion::new(0, 8, 0));
+ assert!(
+ RustcVersion::parse("1.45.2").unwrap() > RustcVersion::Special(SpecialVersion::Alpha2)
+ );
+ }
+
+ #[test]
+ fn edge_cases() {
+ assert_eq!(RustcVersion::parse(""), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse(" "), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse("\t"), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse("1."), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse("1. "), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse("1.\t"), Err(Error::EmptyVersionPart));
+ assert_eq!(RustcVersion::parse("1. \t.3"), Err(Error::EmptyVersionPart));
+ assert_eq!(
+ RustcVersion::parse(" 1 . \t 3.\r 5").unwrap(),
+ RustcVersion::new(1, 3, 5)
+ );
+ }
+
+ #[test]
+ fn formatting() {
+ extern crate alloc;
+ use alloc::string::{String, ToString};
+ assert_eq!(
+ RustcVersion::new(1, 42, 28).to_string(),
+ String::from("1.42.28")
+ );
+ assert_eq!(
+ RustcVersion::Special(SpecialVersion::Alpha).to_string(),
+ String::from("1.0.0-alpha")
+ );
+ assert_eq!(
+ RustcVersion::Special(SpecialVersion::Alpha2).to_string(),
+ String::from("1.0.0-alpha.2")
+ );
+ assert_eq!(
+ RustcVersion::Special(SpecialVersion::Beta).to_string(),
+ String::from("1.0.0-beta")
+ );
+ }
+
+ #[test]
+ fn too_many_elements() {
+ assert_eq!(
+ RustcVersion::parse("1.0.0.100"),
+ Err(Error::TooManyElements)
+ );
+ }
+
+ #[test]
+ fn alpha_numeric_version() {
+ assert_eq!(RustcVersion::parse("a.0.1"), Err(Error::ParseIntError));
+ assert_eq!(RustcVersion::parse("2.x.1"), Err(Error::ParseIntError));
+ assert_eq!(RustcVersion::parse("0.2.s"), Err(Error::NotASpecialVersion));
+ }
+
+ #[test]
+ fn meets_full() {
+ // Nothing was omitted
+ assert!(RustcVersion::new(1, 2, 3).meets(RustcVersion::new(1, 2, 3)));
+ assert!(RustcVersion::new(1, 2, 5).meets(RustcVersion::new(1, 2, 3)));
+ assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::new(1, 2, 3)));
+ assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::new(1, 2, 3)));
+ assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::new(1, 0, 0)));
+
+ assert!(RustcVersion::new(0, 2, 3).meets(RustcVersion::new(0, 2, 3)));
+ assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::new(0, 2, 3)));
+ assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::new(0, 2, 3)));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::new(0, 2, 3)));
+
+ assert!(RustcVersion::new(0, 0, 3).meets(RustcVersion::new(0, 0, 3)));
+ assert!(!RustcVersion::new(0, 0, 5).meets(RustcVersion::new(0, 0, 3)));
+ assert!(!RustcVersion::new(0, 1, 0).meets(RustcVersion::new(0, 0, 3)));
+
+ assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::new(0, 0, 0)));
+ assert!(!RustcVersion::new(0, 0, 1).meets(RustcVersion::new(0, 0, 0)));
+ }
+
+ #[test]
+ fn meets_no_patch() {
+ // Patch was omitted
+ assert!(RustcVersion::new(1, 2, 0).meets(RustcVersion::parse("1.2").unwrap()));
+ assert!(RustcVersion::new(1, 2, 5).meets(RustcVersion::parse("1.2").unwrap()));
+ assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::parse("1.2").unwrap()));
+ assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::parse("1.2").unwrap()));
+ assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::parse("1.0").unwrap()));
+
+ assert!(RustcVersion::new(0, 2, 0).meets(RustcVersion::parse("0.2").unwrap()));
+ assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::parse("0.2").unwrap()));
+ assert!(!RustcVersion::new(0, 3, 0).meets(RustcVersion::parse("0.2").unwrap()));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("0.2").unwrap()));
+
+ assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::parse("0.0").unwrap()));
+ assert!(RustcVersion::new(0, 0, 5).meets(RustcVersion::parse("0.0").unwrap()));
+ assert!(!RustcVersion::new(0, 1, 0).meets(RustcVersion::parse("0.0").unwrap()));
+ }
+
+ #[test]
+ fn meets_no_minor() {
+ // Minor was omitted
+ assert!(RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("1").unwrap()));
+ assert!(RustcVersion::new(1, 3, 0).meets(RustcVersion::parse("1").unwrap()));
+ assert!(!RustcVersion::new(2, 0, 0).meets(RustcVersion::parse("1").unwrap()));
+ assert!(!RustcVersion::new(0, 9, 0).meets(RustcVersion::parse("1").unwrap()));
+
+ assert!(RustcVersion::new(0, 0, 0).meets(RustcVersion::parse("0").unwrap()));
+ assert!(RustcVersion::new(0, 0, 1).meets(RustcVersion::parse("0").unwrap()));
+ assert!(RustcVersion::new(0, 2, 5).meets(RustcVersion::parse("0").unwrap()));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::parse("0").unwrap()));
+ }
+
+ #[test]
+ fn meets_special() {
+ assert!(RustcVersion::Special(SpecialVersion::Alpha)
+ .meets(RustcVersion::Special(SpecialVersion::Alpha)));
+ assert!(RustcVersion::Special(SpecialVersion::Alpha2)
+ .meets(RustcVersion::Special(SpecialVersion::Alpha2)));
+ assert!(RustcVersion::Special(SpecialVersion::Beta)
+ .meets(RustcVersion::Special(SpecialVersion::Beta)));
+ assert!(!RustcVersion::Special(SpecialVersion::Alpha)
+ .meets(RustcVersion::Special(SpecialVersion::Alpha2)));
+ assert!(!RustcVersion::Special(SpecialVersion::Alpha)
+ .meets(RustcVersion::Special(SpecialVersion::Beta)));
+ assert!(!RustcVersion::Special(SpecialVersion::Alpha2)
+ .meets(RustcVersion::Special(SpecialVersion::Beta)));
+ assert!(!RustcVersion::Special(SpecialVersion::Alpha).meets(RustcVersion::new(1, 0, 0)));
+ assert!(!RustcVersion::Special(SpecialVersion::Alpha2).meets(RustcVersion::new(1, 0, 0)));
+ assert!(!RustcVersion::Special(SpecialVersion::Beta).meets(RustcVersion::new(1, 0, 0)));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Alpha)));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Alpha2)));
+ assert!(!RustcVersion::new(1, 0, 0).meets(RustcVersion::Special(SpecialVersion::Beta)));
+ }
+
+ #[test]
+ #[should_panic(
+ expected = "This function should never be called with `parts == 0` or `parts > 3`"
+ )]
+ fn omitted_parts_with_zero() {
+ OmittedParts::from(0);
+ }
+
+ #[test]
+ #[should_panic(
+ expected = "This function should never be called with `parts == 0` or `parts > 3`"
+ )]
+ fn omitted_parts_with_four() {
+ OmittedParts::from(4);
+ }
+}