https://github.com/gngeorgiev/semver_rs
:memo: Semantic version parsing and comparison for Rust, based on the node-semver package.
https://github.com/gngeorgiev/semver_rs
rust semver-parser
Last synced: 9 days ago
JSON representation
:memo: Semantic version parsing and comparison for Rust, based on the node-semver package.
- Host: GitHub
- URL: https://github.com/gngeorgiev/semver_rs
- Owner: gngeorgiev
- License: mit
- Created: 2019-04-20T22:10:14.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2021-11-22T18:07:44.000Z (over 3 years ago)
- Last Synced: 2025-03-29T12:35:02.793Z (about 1 month ago)
- Topics: rust, semver-parser
- Language: Rust
- Homepage:
- Size: 451 KB
- Stars: 9
- Watchers: 1
- Forks: 3
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# SemVer
 [](https://docs.rs/semver_rs) [](https://crates.io/crates/semver_rs)
Semantic version parsing and comparison ([semver](https://semver.org/)). The implementation of this crate is based on the
[node-semver](https://github.com/npm/node-semver#readme) 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`:
```toml
semver_rs = "0.2"
```## Usage
### Comparing two versions
```rust
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
```rust
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
```rust
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:
```toml
semver_rs = { version = "0.2", features = ["serde"] }
``````rust
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](https://github.com/casey/just) and run the setup:
```shell
cargo install just && just setup
```## Run bench
To run the benchmarks populating the next point run:
```shell
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](https://github.com/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.```shell
┌─────────┬───────────────────────┬───────────┬───────────────┬────────┬─────────────────────┐
│ (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.