1use semver::{BuildMetadata, Prerelease, Version};
2use serde::{Serialize, Serializer};
3
4use crate::encoding::{Decodable, DecodeError, Encodable};
5use crate::module::registry::ModuleDecoderRegistry;
6
7pub fn cargo_pkg() -> &'static str {
9 env!("CARGO_PKG_VERSION")
10}
11
12pub fn cargo_pkg_release() -> &'static str {
14 release_version(cargo_pkg())
15}
16
17pub fn release_version(version: &str) -> &str {
19 version
20 .split(['-', '+'])
21 .next()
22 .expect("split always returns at least one item")
23}
24
25#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
31pub struct DkgVersion {
32 setup_code_version: Box<Version>,
34}
35
36#[derive(Debug, Clone, Eq, PartialEq)]
38pub struct DkgVersionCompatibility {
39 major: u64,
41 minor: u64,
43 vendor: Option<BuildMetadata>,
45}
46
47impl DkgVersion {
48 pub fn parse(version: &str) -> Result<Self, semver::Error> {
50 let mut setup_code_version = Version::parse(version)?;
51 setup_code_version.pre = Prerelease::EMPTY;
52
53 Ok(Self {
54 setup_code_version: Box::new(setup_code_version),
55 })
56 }
57
58 pub fn setup_code_version(&self) -> &Version {
60 &self.setup_code_version
61 }
62
63 pub fn compatibility_version(&self) -> DkgVersionCompatibility {
65 DkgVersionCompatibility {
66 major: self.setup_code_version.major,
67 minor: self.setup_code_version.minor,
68 vendor: (!self.setup_code_version.build.is_empty())
69 .then(|| self.setup_code_version.build.clone()),
70 }
71 }
72}
73
74impl std::fmt::Display for DkgVersion {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 self.setup_code_version.fmt(f)
77 }
78}
79
80impl Serialize for DkgVersion {
81 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
82 where
83 S: Serializer,
84 {
85 serializer.collect_str(self)
86 }
87}
88
89impl Encodable for DkgVersion {
90 fn consensus_encode<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
91 self.to_string().consensus_encode(writer)
92 }
93}
94
95impl Decodable for DkgVersion {
96 fn consensus_decode_partial_from_finite_reader<D: std::io::Read>(
97 d: &mut D,
98 modules: &ModuleDecoderRegistry,
99 ) -> Result<Self, DecodeError> {
100 let version = String::consensus_decode_partial_from_finite_reader(d, modules)?;
101 Self::parse(&version).map_err(DecodeError::from_err)
102 }
103}
104
105impl std::fmt::Display for DkgVersionCompatibility {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 write!(f, "{}.{}", self.major, self.minor)?;
108 if let Some(vendor) = &self.vendor {
109 write!(f, "+{vendor}")?;
110 }
111 Ok(())
112 }
113}
114
115pub fn git_hash() -> &'static str {
122 option_env!("FEDIMINT_BUILD_CODE_VERSION").unwrap_or("0000000000000000000000000000000000000001")
123}
124
125pub fn non_zero_version_hash(hash: &str) -> Option<&str> {
128 if hash.bytes().all(|b| b == b'0') {
129 None
130 } else {
131 Some(hash)
132 }
133}
134
135#[cfg(test)]
136mod tests;