Add SemVer
struct and related impl's
This commit is contained in:
parent
bb187d4f8c
commit
8009575765
13
src/error.rs
13
src/error.rs
@ -1,8 +1,13 @@
|
|||||||
use std::{fmt, num::TryFromIntError};
|
use std::{
|
||||||
|
fmt,
|
||||||
|
num::{ParseIntError, TryFromIntError},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
FromUint,
|
FromUint,
|
||||||
|
Range,
|
||||||
|
ParseInt,
|
||||||
ParsePreRelease,
|
ParsePreRelease,
|
||||||
ParseSemver,
|
ParseSemver,
|
||||||
TryFromInt,
|
TryFromInt,
|
||||||
@ -21,3 +26,9 @@ impl From<TryFromIntError> for Error {
|
|||||||
Self::TryFromInt
|
Self::TryFromInt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<ParseIntError> for Error {
|
||||||
|
fn from(_value: ParseIntError) -> Self {
|
||||||
|
Self::ParseInt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
mod error;
|
mod error;
|
||||||
mod prerelease;
|
mod prerelease;
|
||||||
|
mod semver;
|
||||||
|
|
||||||
pub use {error::Error, prerelease::PreRelease};
|
pub use {error::Error, prerelease::PreRelease, semver::SemVer};
|
||||||
|
|
||||||
|
pub static MAX_U12: u16 = 4096;
|
||||||
|
@ -0,0 +1,87 @@
|
|||||||
|
use {
|
||||||
|
crate::{Error, PreRelease, MAX_U12},
|
||||||
|
serde::{Deserialize, Serialize},
|
||||||
|
std::{cmp::Ordering, fmt, str::FromStr},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
|
||||||
|
pub struct SemVer {
|
||||||
|
pub major: u16,
|
||||||
|
pub minor: u16,
|
||||||
|
pub patch: u16,
|
||||||
|
pub pre: PreRelease,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for SemVer {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}.{}.{}", self.major, self.minor, self.patch)?;
|
||||||
|
match self.pre {
|
||||||
|
PreRelease::None => Ok(()),
|
||||||
|
p => write!(f, "_{p}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for SemVer {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let (s, pre) = match s.split_once('_') {
|
||||||
|
Some((a, b)) => (a, b.parse::<PreRelease>()?),
|
||||||
|
None => (s, PreRelease::None),
|
||||||
|
};
|
||||||
|
let split = s.split('.').collect::<Vec<_>>();
|
||||||
|
match split.len() {
|
||||||
|
3 => {
|
||||||
|
let major = split.first().unwrap().parse::<u16>()?;
|
||||||
|
let minor = split.get(1).unwrap().parse::<u16>()?;
|
||||||
|
let patch = split.get(2).unwrap().parse::<u16>()?;
|
||||||
|
if major > MAX_U12 || minor > MAX_U12 || patch > MAX_U12 {
|
||||||
|
return Err(Error::Range);
|
||||||
|
}
|
||||||
|
Ok(Self {
|
||||||
|
major,
|
||||||
|
minor,
|
||||||
|
patch,
|
||||||
|
pre,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(Error::ParseSemver),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<SemVer> for u64 {
|
||||||
|
fn from(value: SemVer) -> Self {
|
||||||
|
let major = u64::from(value.major) << 52;
|
||||||
|
let minor = u64::from(value.minor) << 40;
|
||||||
|
let patch = u64::from(value.patch) << 28;
|
||||||
|
let pre = u64::from(u16::from(value.pre));
|
||||||
|
major | minor | patch | pre
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq for SemVer {
|
||||||
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.major == other.major
|
||||||
|
&& self.minor == other.minor
|
||||||
|
&& self.patch == other.patch
|
||||||
|
&& self.pre == other.pre
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Eq for SemVer {}
|
||||||
|
|
||||||
|
impl Ord for SemVer {
|
||||||
|
fn cmp(&self, other: &Self) -> Ordering {
|
||||||
|
let a = u64::from(*self);
|
||||||
|
let b = u64::from(*other);
|
||||||
|
a.cmp(&b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for SemVer {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
Some(self.cmp(other))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user