use std::{
fmt::Display,
sync::atomic::{AtomicU64, Ordering},
};
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct PackageVersion(u64);
impl PackageVersion {
pub fn from_u64(value: u64) -> Self {
Self(value)
}
pub fn to_u64(&self) -> u64 {
self.0
}
fn from_version(major: u16, minor: u16, patch: u16) -> Self {
Self(((major as u64) << 32) | ((minor as u64) << 16) | patch as u64)
}
pub fn major(&self) -> u16 {
((self.0 >> 32) & (u16::MAX as u64)) as u16
}
pub fn minor(&self) -> u16 {
((self.0 >> 16) & (u16::MAX as u64)) as u16
}
pub fn patch(&self) -> u16 {
((self.0) & (u16::MAX as u64)) as u16
}
pub fn get() -> PackageVersion {
static PACKAGE_VERSION: AtomicU64 = AtomicU64::new(0);
if PACKAGE_VERSION.load(Ordering::Relaxed) == 0 {
let major = option_env!("CARGO_PKG_VERSION_MAJOR")
.and_then(|s| s.parse::<u16>().ok())
.unwrap_or(u16::MAX);
let minor = option_env!("CARGO_PKG_VERSION_MINOR")
.and_then(|s| s.parse::<u16>().ok())
.unwrap_or(u16::MAX);
let patch = option_env!("CARGO_PKG_VERSION_PATCH")
.and_then(|s| s.parse::<u16>().ok())
.unwrap_or(u16::MAX);
PACKAGE_VERSION.store(
PackageVersion::from_version(major, minor, patch).0,
Ordering::Relaxed,
);
}
PackageVersion::from_u64(PACKAGE_VERSION.load(Ordering::Relaxed))
}
}
impl Display for PackageVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}.{}", self.major(), self.minor(), self.patch())
}
}