use semver::{BuildMetadata, Prerelease, Version};
use serde::{Serialize, Serializer};
use crate::encoding::{Decodable, DecodeError, Encodable};
use crate::module::registry::ModuleDecoderRegistry;
pub fn cargo_pkg() -> &'static str {
env!("CARGO_PKG_VERSION")
}
pub fn cargo_pkg_release() -> &'static str {
release_version(cargo_pkg())
}
pub fn release_version(version: &str) -> &str {
version
.split(['-', '+'])
.next()
.expect("split always returns at least one item")
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct DkgVersion {
setup_code_version: Box<Version>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct DkgVersionCompatibility {
major: u64,
minor: u64,
vendor: Option<BuildMetadata>,
}
impl DkgVersion {
pub fn parse(version: &str) -> Result<Self, semver::Error> {
let mut setup_code_version = Version::parse(version)?;
setup_code_version.pre = Prerelease::EMPTY;
Ok(Self {
setup_code_version: Box::new(setup_code_version),
})
}
pub fn setup_code_version(&self) -> &Version {
&self.setup_code_version
}
pub fn compatibility_version(&self) -> DkgVersionCompatibility {
DkgVersionCompatibility {
major: self.setup_code_version.major,
minor: self.setup_code_version.minor,
vendor: (!self.setup_code_version.build.is_empty())
.then(|| self.setup_code_version.build.clone()),
}
}
}
impl std::fmt::Display for DkgVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.setup_code_version.fmt(f)
}
}
impl Serialize for DkgVersion {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.collect_str(self)
}
}
impl Encodable for DkgVersion {
fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
self.to_string().consensus_encode(writer)
}
}
impl Decodable for DkgVersion {
fn consensus_decode_partial_from_finite_reader<D: std::io::Read>(
d: &mut D,
modules: &ModuleDecoderRegistry,
) -> Result<Self, DecodeError> {
let version = String::consensus_decode_partial_from_finite_reader(d, modules)?;
Self::parse(&version).map_err(DecodeError::from_err)
}
}
impl std::fmt::Display for DkgVersionCompatibility {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}.{}", self.major, self.minor)?;
if let Some(vendor) = &self.vendor {
write!(f, "+{vendor}")?;
}
Ok(())
}
}
pub fn git_hash() -> &'static str {
option_env!("FEDIMINT_BUILD_CODE_VERSION").unwrap_or("0000000000000000000000000000000000000001")
}
pub fn non_zero_version_hash(hash: &str) -> Option<&str> {
if hash.bytes().all(|b| b == b'0') {
None
} else {
Some(hash)
}
}
#[cfg(test)]
mod tests;