use semver::{Version, VersionReq};
use std::fmt;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct BackendVersion {
version: Version,
}
impl BackendVersion {
#[must_use]
pub fn new(major: u64, minor: u64, patch: u64) -> Self {
Self {
version: Version::new(major, minor, patch),
}
}
pub fn parse(s: &str) -> Result<Self, semver::Error> {
Ok(Self {
version: Version::parse(s)?,
})
}
#[must_use]
pub fn major(&self) -> u64 {
self.version.major
}
#[must_use]
pub fn minor(&self) -> u64 {
self.version.minor
}
#[must_use]
pub fn patch(&self) -> u64 {
self.version.patch
}
#[must_use]
pub fn is_compatible_with(&self, other: &Self) -> bool {
self.version.major == other.version.major
}
pub fn satisfies(&self, req: &str) -> Result<bool, semver::Error> {
let req = VersionReq::parse(req)?;
Ok(req.matches(&self.version))
}
#[must_use]
pub const fn as_semver(&self) -> &Version {
&self.version
}
}
impl fmt::Display for BackendVersion {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.version)
}
}
impl From<Version> for BackendVersion {
fn from(version: Version) -> Self {
Self { version }
}
}
impl From<BackendVersion> for Version {
fn from(backend_version: BackendVersion) -> Self {
backend_version.version
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_version_creation() {
let version = BackendVersion::new(1, 2, 3);
assert_eq!(version.major(), 1);
assert_eq!(version.minor(), 2);
assert_eq!(version.patch(), 3);
}
#[test]
fn test_version_parse() {
let version = BackendVersion::parse("1.2.3").unwrap();
assert_eq!(version.major(), 1);
assert_eq!(version.minor(), 2);
assert_eq!(version.patch(), 3);
}
#[test]
fn test_version_display() {
let version = BackendVersion::new(1, 2, 3);
assert_eq!(version.to_string(), "1.2.3");
}
#[test]
fn test_version_compatibility() {
let v1 = BackendVersion::new(1, 2, 3);
let v2 = BackendVersion::new(1, 3, 0);
let v3 = BackendVersion::new(2, 0, 0);
assert!(v1.is_compatible_with(&v2));
assert!(v2.is_compatible_with(&v1));
assert!(!v1.is_compatible_with(&v3));
assert!(!v3.is_compatible_with(&v1));
}
#[test]
fn test_version_satisfies() {
let version = BackendVersion::new(1, 2, 3);
assert!(version.satisfies("^1.0.0").unwrap());
assert!(version.satisfies("^1.2.0").unwrap());
assert!(version.satisfies(">=1.0.0").unwrap());
assert!(!version.satisfies("^2.0.0").unwrap());
assert!(!version.satisfies("<1.0.0").unwrap());
}
#[test]
fn test_invalid_version_parse() {
assert!(BackendVersion::parse("invalid").is_err());
assert!(BackendVersion::parse("1.2").is_err());
}
}