#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use std::str::FromStr;
use thiserror::Error;
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct Version {
pub major: u64,
pub minor: u64,
pub patch: u64,
}
impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
let major_ordering = self.major.partial_cmp(&other.major);
if let Some(d) = major_ordering {
if d.is_ne() {
return Some(d);
}
}
let minor_ordering = self.minor.partial_cmp(&other.minor);
if let Some(d) = minor_ordering {
if d.is_ne() {
return Some(d);
}
}
self.patch.partial_cmp(&other.patch)
}
}
impl Ord for Version {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
let major_ordering = self.major.cmp(&other.major);
if major_ordering.is_ne() {
return major_ordering;
}
let minor_ordering = self.minor.cmp(&other.minor);
if minor_ordering.is_ne() {
return minor_ordering;
}
self.patch.cmp(&other.patch)
}
}
impl Version {
#[inline]
pub const fn new(major: u64, minor: u64, patch: u64) -> Self {
Version {
major,
minor,
patch,
}
}
pub fn new_from_str(input: &str) -> Result<Self, VersionParseError> {
let splits: Vec<&str> = input.split('.').collect();
if splits.len() != 3 {
return Err(VersionParseError::FormatWrong);
}
let major_str = splits.get(0).unwrap();
let major = u64::from_str(major_str).map_err(|_| VersionParseError::MajorParseError)?;
let minor_str = splits.get(1).unwrap();
let minor = u64::from_str(minor_str).map_err(|_| VersionParseError::MinorParseError)?;
let patch_str = splits.get(2).unwrap();
let patch = u64::from_str(patch_str).map_err(|_| VersionParseError::PatchParseError)?;
Ok(Self::new(major, minor, patch))
}
}
#[derive(Error, Debug)]
pub enum VersionParseError {
#[error("Format of version string is wrong")]
FormatWrong,
#[error("Parsing error in major")]
MajorParseError,
#[error("Major element was not found")]
MajorNotFound,
#[error("Minor Parse Error")]
MinorParseError,
#[error("Minor element was not found")]
MinorNotFound,
#[error("Patch Parse Error")]
PatchParseError,
#[error("Patch element was not found")]
PatchNotFound,
}
impl FromStr for Version {
type Err = VersionParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Self::new_from_str(s)
}
}
#[cfg(feature = "alloc")]
impl ToString for Version {
fn to_string(&self) -> String {
format!("{}.{}.{}", self.major, self.minor, self.patch)
}
}