1use {
2 crate::{client_ids::ClientId, compute_commit},
3 rand::{Rng, rng},
4 serde::{Deserialize, Serialize},
5 solana_sanitize::Sanitize,
6 solana_serde_varint as serde_varint,
7 std::{convert::TryInto, fmt},
8};
9#[cfg_attr(feature = "frozen-abi", derive(AbiExample))]
10#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
11pub struct Version {
12 #[serde(with = "serde_varint")]
13 pub major: u16,
14 #[serde(with = "serde_varint")]
15 pub minor: u16,
16 #[serde(with = "serde_varint")]
17 pub patch: u16,
18 pub commit: u32, pub feature_set: u32, #[serde(with = "serde_varint")]
21 pub client: u16,
22}
23
24impl Version {
25 pub fn as_semver_version(&self) -> semver::Version {
26 semver::Version::new(self.major as u64, self.minor as u64, self.patch as u64)
27 }
28
29 pub fn client(&self) -> ClientId {
30 ClientId::from(self.client)
31 }
32}
33
34impl Default for Version {
35 fn default() -> Self {
36 let feature_set =
37 u32::from_le_bytes(agave_feature_set::ID.as_ref()[..4].try_into().unwrap());
38 Self {
39 major: env!("CARGO_PKG_VERSION_MAJOR").parse().unwrap(),
40 minor: env!("CARGO_PKG_VERSION_MINOR").parse().unwrap(),
41 patch: env!("CARGO_PKG_VERSION_PATCH").parse().unwrap(),
42 commit: compute_commit(option_env!("CI_COMMIT"))
43 .or(compute_commit(option_env!("AGAVE_GIT_COMMIT_HASH")))
44 .unwrap_or_else(|| rng().random::<u32>()),
45 feature_set,
46 client: u16::try_from(ClientId::Agave).unwrap(),
48 }
49 }
50}
51
52impl fmt::Display for Version {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 write!(f, "{}.{}.{}", self.major, self.minor, self.patch,)
55 }
56}
57
58impl fmt::Debug for Version {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 write!(
61 f,
62 "{}.{}.{} (src:{:08x}; feat:{}, client:{:?})",
63 self.major,
64 self.minor,
65 self.patch,
66 self.commit,
67 self.feature_set,
68 self.client(),
69 )
70 }
71}
72
73impl Sanitize for Version {}