hpk/src/version/rapid.rs

195 lines
5.0 KiB
Rust

use crate::SemVer;
use {
crate::Version,
serde::{Deserialize, Serialize},
std::{cmp::Ordering, error::Error, fmt, num::ParseIntError, str::FromStr},
};
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Rapid {
pub major: u32,
pub minor: u32,
}
impl fmt::Display for Rapid {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}.{}", self.major, self.minor)
}
}
impl PartialOrd for Rapid {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
match self.major.partial_cmp(&other.major) {
Some(Ordering::Greater) => Some(Ordering::Greater),
Some(Ordering::Less) => Some(Ordering::Less),
Some(Ordering::Equal) => self.minor.partial_cmp(&other.minor),
None => None,
}
}
}
impl Ord for Rapid {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
match self.major.cmp(&other.major) {
Ordering::Greater => Ordering::Greater,
Ordering::Less => Ordering::Less,
Ordering::Equal => self.minor.cmp(&other.minor),
}
}
}
impl PartialEq<u32> for Rapid {
fn eq(&self, other: &u32) -> bool {
self.major == *other && self.minor == 0
}
}
impl PartialOrd<u32> for Rapid {
fn partial_cmp(&self, other: &u32) -> Option<Ordering> {
match self.major.partial_cmp(other) {
Some(Ordering::Greater) => Some(Ordering::Greater),
Some(Ordering::Less) => Some(Ordering::Less),
None => None,
Some(Ordering::Equal) => {
if self.minor == 0 {
Some(Ordering::Equal)
} else {
Some(Ordering::Greater)
}
}
}
}
}
impl PartialEq<SemVer> for Rapid {
fn eq(&self, other: &SemVer) -> bool {
other.eq(self)
}
}
impl PartialOrd<SemVer> for Rapid {
fn partial_cmp(&self, other: &SemVer) -> Option<Ordering> {
match other.partial_cmp(self) {
Some(Ordering::Less) => Some(Ordering::Greater),
Some(Ordering::Greater) => Some(Ordering::Less),
Some(Ordering::Equal) => Some(Ordering::Equal),
None => None,
}
}
}
impl PartialEq<Rapid> for u32 {
fn eq(&self, other: &Rapid) -> bool {
other.eq(self)
}
}
impl PartialOrd<Rapid> for u32 {
fn partial_cmp(&self, other: &Rapid) -> Option<Ordering> {
match other.partial_cmp(self) {
Some(Ordering::Equal) => Some(Ordering::Equal),
Some(Ordering::Less) => Some(Ordering::Greater),
Some(Ordering::Greater) => Some(Ordering::Less),
None => None,
}
}
}
#[derive(Debug, PartialEq)]
pub struct ParseRapidError;
impl fmt::Display for ParseRapidError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Error parsing Rapid version")
}
}
impl Error for ParseRapidError {}
impl From<ParseIntError> for ParseRapidError {
fn from(_value: ParseIntError) -> Self {
Self
}
}
impl FromStr for Rapid {
type Err = ParseRapidError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let split = s.split('.').collect::<Vec<_>>();
match split.len() {
2 => {
let major = split.first().unwrap().parse::<u32>()?;
let minor = split.get(1).unwrap().parse::<u32>()?;
Ok(Self { major, minor })
}
_ => Err(ParseRapidError),
}
}
}
impl TryFrom<Version> for Rapid {
type Error = ParseRapidError;
fn try_from(value: Version) -> Result<Self, Self::Error> {
match value {
Version::SemVer(s) => {
if s.patch == 0 {
Ok(Self {
major: s.major,
minor: s.minor,
})
} else {
Err(ParseRapidError)
}
}
Version::Rapid(s) => Ok(s),
Version::Number(major) => Ok(Self { major, minor: 0 }),
Version::Git(_) => Err(ParseRapidError),
}
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn parse_semver() {
assert_eq!(
"93.0".parse::<Rapid>(),
Ok(Rapid {
major: 93,
minor: 0,
})
);
}
#[test]
fn rapid_num_eq() {
let rapid = Rapid { major: 42, minor: 0 };
assert_eq!(rapid, 42);
}
#[test]
fn rapid_num_gt() {
let rapid = Rapid { major: 1, minor: 42 };
assert!(rapid > 1);
}
#[test]
fn rapid_semver_eq() {
let rapid = Rapid { major: 42, minor: 69 };
let semver = SemVer { major: 42, minor: 69, patch: 0 };
assert_eq!(rapid, semver);
}
#[test]
fn rapid_semver_lt() {
let rapid = Rapid { major: 42, minor: 69 };
let semver = SemVer { major: 42, minor: 69, patch: 1 };
assert!(rapid < semver);
}
}