Skip to main content

rskit_version/
semver.rs

1//! Semantic version parsing and requirement helpers.
2
3pub use ::semver::{Version, VersionReq};
4
5/// Parses a semantic version string.
6///
7/// Returns `None` when `value` is not valid `SemVer`.
8///
9/// # Examples
10///
11/// ```
12/// let version = rskit_version::semver::parse_version("1.2.3").unwrap();
13/// assert_eq!(version.major, 1);
14/// ```
15#[must_use]
16pub fn parse_version(value: &str) -> Option<Version> {
17    Version::parse(value).ok()
18}
19
20/// Parses a semantic version requirement.
21///
22/// Returns `None` when `requirement` is not a valid `SemVer` requirement.
23///
24/// # Examples
25///
26/// ```
27/// let requirement = rskit_version::semver::parse_requirement(">=1.2").unwrap();
28/// let version = rskit_version::semver::parse_version("1.3.0").unwrap();
29/// assert!(requirement.matches(&version));
30/// ```
31#[must_use]
32pub fn parse_requirement(requirement: &str) -> Option<VersionReq> {
33    VersionReq::parse(requirement).ok()
34}
35
36/// Returns whether a semantic version string satisfies a semantic version requirement.
37///
38/// Returns `None` when either input cannot be parsed.
39///
40/// # Examples
41///
42/// ```
43/// assert_eq!(
44///     rskit_version::semver::matches_requirement("1.3.0", ">=1.2"),
45///     Some(true)
46/// );
47/// ```
48#[must_use]
49pub fn matches_requirement(version: &str, requirement: &str) -> Option<bool> {
50    let version = parse_version(version)?;
51    let requirement = parse_requirement(requirement)?;
52    Some(requirement.matches(&version))
53}
54
55#[cfg(test)]
56mod tests {
57    use super::*;
58
59    #[test]
60    fn parses_versions() {
61        let version = parse_version("1.2.3-alpha.1+build.5").expect("version should parse");
62        assert_eq!(version.major, 1);
63        assert_eq!(version.minor, 2);
64        assert_eq!(version.patch, 3);
65        assert_eq!(parse_version("1.2"), None);
66    }
67
68    #[test]
69    fn parses_requirements() {
70        let requirement = parse_requirement("^1.2").expect("requirement should parse");
71        assert!(requirement.matches(&Version::parse("1.3.0").expect("version should parse")));
72        assert_eq!(parse_requirement("not a requirement"), None);
73    }
74
75    #[test]
76    fn checks_requirement_matches() {
77        assert_eq!(matches_requirement("1.3.0", ">=1.2"), Some(true));
78        assert_eq!(matches_requirement("1.1.0", ">=1.2"), Some(false));
79        assert_eq!(matches_requirement("invalid", ">=1.2"), None);
80        assert_eq!(matches_requirement("1.3.0", "invalid"), None);
81    }
82}