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:
= "0.2"
Usage
Comparing two versions
use Version;
// by constructing version instances manually
let ver1 = new.parse?;
let ver2 = new.parse?;
assert!;
// by using the exported helper function
use compare;
use Ordering;
assert!;
Checking whether a version is in a range
use ;
// by constructing version instances manually
let range = new.parse?;
let ver = new.parse?;
assert!;
// by using the exported helper function
use satisfies;
assert!;
Parsing with specific options
use ;
let opts = builder.loose.include_prerelease.build;
let range = new.with_options.parse?;
let ver = new.with_options.parse?;
assert!;
Serializing
In order to allow serializing the semver structs allow the serde feature:
= { = "0.2", = ["serde"] }
use ;
let opts = builder.loose.include_prerelease.build;
let range = new.with_options.parse.unwrap;
let _ = to_string.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.