5 releases
0.2.0 | Nov 22, 2021 |
---|---|
0.1.3 | Apr 30, 2019 |
0.1.2 | Apr 30, 2019 |
0.1.1 | Apr 30, 2019 |
0.1.0 | Apr 30, 2019 |
#1169 in Parser implementations
114 downloads per month
Used in 2 crates
77KB
1.5K
SLoC
SemVer
Semantic version parsing and comparison (semver). The implementation of this crate is based on the node-semver npm package. The tests are taken directly from node-semver's repo. This should make this crate as good at parsing semver expressions as the node package manager.
Installation
Add this to your [dependencies]
section in Cargo.toml
:
semver_rs = "0.2"
Usage
Comparing two versions
use semver_rs::Version;
// by constructing version instances manually
let ver1 = Version::new("2.0.0").parse()?;
let ver2 = Version::new("1.2.3").parse()?;
assert!(ver1 > ver2);
// by using the exported helper function
use semver_rs::compare;
use std::cmp::Ordering;
assert!(compare("2.0.0", "1.2.3", None)? == Ordering::Greater);
Checking whether a version is in a range
use semver_rs::{Range, Version};
// by constructing version instances manually
let range = Range::new(">=1.2.3").parse()?;
let ver = Version::new("1.2.4").parse()?;
assert!(range.test(&ver));
// by using the exported helper function
use semver_rs::satisfies;
assert!(satisfies("1.2.4", ">=1.2.4", None)?);
Parsing with specific options
use semver_rs::{Version, Range, Options};
let opts = Options::builder().loose(true).include_prerelease(true).build();
let range = Range::new(">=1.2.3").with_options(opts).parse()?;
let ver = Version::new("1.2.4-pre1").with_options(opts).parse()?;
assert!(range.test(&ver));
Serializing
In order to allow serializing the semver structs allow the serde
feature:
semver_rs = { version = "0.2", features = ["serde"] }
use semver_rs::{Range, Options};
let opts = Options::builder().loose(true).include_prerelease(true).build();
let range = Range::new(">=1.2.3").with_options(opts).parse().unwrap();
let _ = serde_json::to_string(&opts).unwrap();
Development
Install just and run the setup:
cargo install just && just setup
Run bench
To run the benchmarks populating the next point run:
just bench
This shell script collects some ranges from random npm packages and compares the results for the three implementations -
semver_node
, semver_rs
and steveklabnik/semver
. From the table bellow the results can be observed.
Comparisons and considerations with other crates
At the time of writing this README there's only one other crate in the Rust ecosystem capable of parsing semver - steveklabnik/semver. While this crate is being used in cargo and is clearly doing its job there very well, while comparing arbitrary semver strings from a number of NPM packages I found it unable to parse a lot of them. Since its implementation of semver was vastly different from NPM's I decided to base this crate on NPM's package in the hopes of making it easier to keep up with any updates in the future. I kept the implementation as close as possible so the code structure and the way input is parsed should be very similar.
One trade-off this implementation had to make was a tiny bit of performance. Since the parsing is based heavily on Regex it's a little bit slower. There are still a lot of string allocations that can be eliminated, especially in parsing Ranges and Versions with prereleases.
┌─────────┬───────────────────────┬───────────┬───────────────┬────────┬─────────────────────┐
│ (index) │ name │ satisfies │ not_satisfies │ errors │ average_us │
├─────────┼───────────────────────┼───────────┼───────────────┼────────┼─────────────────────┤
│ 0 │ 'semver_node' │ 14 │ 451 │ 1 │ 32.68025751072961 │
│ 1 │ 'semver_rs' │ 14 │ 451 │ 1 │ 8.454935622317597 │
│ 2 │ 'steveklabnik/semver' │ 11 │ 445 │ 10 │ 0.27682403433476394 │
└─────────┴───────────────────────┴───────────┴───────────────┴────────┴─────────────────────┘
In conclussion semver_rs
is faster than semver_node
and slower than steveklabnik/semver
. It's also as accurate
in parsing as semver_node
, while steveklabnik/semver
couldn't handle 9 of the ranges.
Dependencies
~2.5–4MB
~75K SLoC