use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use std::cmp::PartialOrd;
#[derive(Serialize, Debug, PartialEq, Clone)]
pub struct Version {
pub major: u32,
pub minor: u32,
pub patch: u32,
pub build: u32,
}
impl PartialOrd for Version {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
if self.major != other.major {
return self.major.partial_cmp(&other.major);
}
if self.minor != other.minor {
return self.minor.partial_cmp(&other.minor);
}
if self.patch != other.patch {
return self.patch.partial_cmp(&other.patch);
}
if self.build != other.build {
return self.build.partial_cmp(&other.build);
}
Some(std::cmp::Ordering::Equal)
}
fn lt(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(std::cmp::Ordering::Less)
}
fn le(&self, other: &Self) -> bool {
self.partial_cmp(other) != Some(std::cmp::Ordering::Greater)
}
fn gt(&self, other: &Self) -> bool {
self.partial_cmp(other) == Some(std::cmp::Ordering::Greater)
}
fn ge(&self, other: &Self) -> bool {
self.partial_cmp(other) != Some(std::cmp::Ordering::Less)
}
}
impl<'de> Deserialize<'de> for Version {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VersionVisitor;
impl<'de> Visitor<'de> for VersionVisitor {
type Value = Version;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a version string in dot format")
}
fn visit_str<E>(self, value: &str) -> Result<Version, E>
where
E: de::Error,
{
let parts: Vec<&str> = value.split('.').collect();
if parts.len() == 4 {
let major: Result<u32, E> = parts[0].parse().map_err(de::Error::custom);
let minor: Result<u32, E> = parts[1].parse().map_err(de::Error::custom);
let patch: Result<u32, E> = parts[2].parse().map_err(de::Error::custom);
let build: Result<u32, E> = parts[3].parse().map_err(de::Error::custom);
Ok(Version {
major: major?,
minor: minor?,
patch: patch?,
build: build?,
})
} else {
Err(de::Error::custom("Invalid version string format"))
}
}
}
deserializer.deserialize_str(VersionVisitor)
}
}