2024-01-22 01:10:33 -05:00
|
|
|
Contents
|
|
|
|
========
|
|
|
|
- [Introduction](#introduction)
|
|
|
|
- [Usage](#usage)
|
|
|
|
- [Internals](#internals)
|
|
|
|
|
|
|
|
## Introduction
|
|
|
|
This crate aims to provide methods for parsing, formatting, comparing and ordering
|
|
|
|
version numbers in most of the common formats in use today. In a perfect world, all
|
|
|
|
software be it free or non-free would use semantic versioning and strictly stick to
|
|
|
|
the rules governing semver. In the real world version numbers may be given using 1,
|
|
|
|
2, 3 or 4 digits and may or may not be consistent between releases. One release may
|
|
|
|
take the form "2.4" and be followed by a "2.4.1" release. A robust library for parsing
|
|
|
|
and comparing versions must be able to compare the two for ordering purposes in
|
|
|
|
order to determine that "2.4.1" is a newer patch release in the "2.4" series. In
|
|
|
|
addition, Pre-release numbering must be accounted for and the library must be able to
|
|
|
|
determine that an alpha is older than a beta, a full release newer than a release
|
|
|
|
candidate.
|
|
|
|
|
|
|
|
This library provides a `Version` struct which can handle 1 to 4 numerical fields for
|
|
|
|
semver-like versioning plus alpha, beta or rc prereleases, plus git revisions. It also
|
|
|
|
tracks machine architecture, and will return -ne if the version numbers match but not
|
|
|
|
the arch when doing comparisons.
|
|
|
|
|
|
|
|
## Usage
|
|
|
|
For the time being, this crate is not yet release on crates.io. It can be used from
|
|
|
|
git in your Cargo.toml file like so:
|
|
|
|
```Toml
|
|
|
|
version = { git = "https://codeberg.org/jeang3nie/version-rs" }
|
|
|
|
```
|
|
|
|
### Parsing and formatting
|
|
|
|
`Version` implements `Display` and `FromStr`.
|
|
|
|
```
|
|
|
|
use version::{prelude::VersionError, Version};
|
|
|
|
|
|
|
|
fn main() -> Result::<(), VersionError> {
|
|
|
|
let vstr = "2.0.3_alpha1-aarch64";
|
|
|
|
let v: Version = vstr.parse()?;
|
|
|
|
assert_eq!(v.to_string(), vstr);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
```
|
|
|
|
### Comparison
|
|
|
|
`Version` implements `PartialOrd` and `PartialEq`
|
|
|
|
```
|
|
|
|
use version::{prelude::VersionError, Version};
|
|
|
|
|
|
|
|
fn main() -> Result<(), VersionError> {
|
|
|
|
let va: Version = "1.0-x86_64".parse()?;
|
|
|
|
let vb: Version = "1.0.0-x86_64".parse()?;
|
|
|
|
let vc: Version = "1.0_rc4-x86_64".parse()?;
|
|
|
|
let vd: Version = "1.0-riscv64".parse()?;
|
|
|
|
assert_eq!(va, vb);
|
|
|
|
assert!(vb > vc);
|
|
|
|
assert_ne!(va, vd);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
## Internals
|
|
|
|
When comparing version numbers for equality or ordering, the semver-like versions
|
|
|
|
are first encoded into a single `u64`, allowing for an easy comparison using the
|
|
|
|
`==`, `<` and `>` operators. This is done using some simple bit shifting logic.
|
|
|
|
The twelve least significant bits, or LSB, are given for any numerical component to
|
|
|
|
the prerelease number. The next four bits are used as bitflags representing the
|
|
|
|
type of prerelease, which may be `PreRelease::None` (which gets the highest bit in
|
|
|
|
the set).
|
|
|
|
|
2024-01-31 22:59:31 -05:00
|
|
|
| bits | 15 | 14 | 13 | 12 | 11 | 0-10 |
|
|
|
|
| ---- | --- | --- | --- | --- | --- | ---- |
|
|
|
|
| use | PreRelease::None | PreRelease::Rc | PreRelease::Beta | PreRelease::Alpha | PreRelease::Git | Numerical component |
|
2024-01-22 01:10:33 -05:00
|
|
|
|
2024-01-31 22:59:31 -05:00
|
|
|
This gives an upper limit of 2^11 or 2048 for the numerical component of the prerelease,
|
|
|
|
and 2^12 or 4096 for each SemVer field, which is more
|
2024-01-22 01:10:33 -05:00
|
|
|
than adequate. By placing the flags in this way, alpha releases will always be lower
|
|
|
|
than beta, which will be lower than release candidates, which will be lower than no
|
|
|
|
pre-release versions.
|
|
|
|
|
|
|
|
The fields major, minor, patch and build each get 12 of the remaining bits, arranged
|
|
|
|
so that major is the most significant followed by minor, patch and build.
|
|
|
|
|
|
|
|
| bits | 52-63 | 40-51 | 28-39 | 16-27 |
|
|
|
|
| ---- | ----- | ----- | ----- | ----- |
|
|
|
|
| use | major | minor | patch | build |
|
|
|
|
|
|
|
|
In this way, version "1.0" will be equal to "1.0.0" and less than "1.0.1" in a simple
|
|
|
|
comparison operation, without requiring complex match statements.
|
|
|
|
|
|
|
|
In this way the traits PartialEq, Eq, PartialOrd and Ord can be implemented in a
|
|
|
|
straightforward and concise manner for the various versioning schemes.
|