1use crate::DATABANK_VERSION;
2use lazy_static::lazy_static;
3use serde::{Deserialize, Serialize};
4use std::{
5 env::consts::{ARCH, OS},
6 str::FromStr,
7 sync::OnceLock,
8};
9
10const GIT_HASH: &str = match option_env!("GITHUB_SHA") {
15 Some(hash) => hash,
16 None => "cargo",
18};
19
20#[cfg(debug_assertions)]
21const PROFILE: &str = "debug";
22#[cfg(not(debug_assertions))]
23const PROFILE: &str = "release";
24
25lazy_static! {
26 pub static ref VERSION: String = NodeVersion::get().to_string();
27}
28
29pub static NODE_VERSION: OnceLock<NodeVersion> = OnceLock::new();
33
34#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
36pub struct Version {
37 major: u8,
38 minor: u8,
39 patch: u8,
40}
41
42impl Version {
43 pub fn new(major: u8, minor: u8, patch: u8) -> Self {
44 Self { major, minor, patch }
45 }
46}
47
48impl FromStr for Version {
49 type Err = ();
50
51 fn from_str(s: &str) -> Result<Self, Self::Err> {
52 let s = if let Some(pos) = s.find('_') {
53 s.split_at(pos).0
54 } else {
55 s
56 };
57 let mut parts = s.split('.');
58 let major = parts.next().ok_or(())?.parse().map_err(|_| ())?;
59 let minor = parts.next().ok_or(())?.parse().map_err(|_| ())?;
60 let patch = parts.next().ok_or(())?.parse().map_err(|_| ())?;
61 Ok(Self { major, minor, patch })
62 }
63}
64
65impl std::fmt::Display for Version {
66 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
67 write!(f, "{}.{}.{}", self.major, self.minor, self.patch)
68 }
69}
70
71#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
73#[serde(rename_all = "camelCase")]
74pub struct NodeVersion {
75 pub profile: String,
76 pub target: String,
77 pub version: String,
78 pub git_hash: String,
79}
80
81impl NodeVersion {
82 pub fn get() -> &'static NodeVersion {
84 NODE_VERSION.get_or_init(|| NodeVersion {
85 profile: PROFILE.to_string(),
86 target: format!("{}-{}", OS, ARCH),
87 version: format!("{}.0", DATABANK_VERSION),
88 git_hash: GIT_HASH.to_string(),
89 })
90 }
91
92 pub fn version(&self) -> Option<Version> {
93 self.version.parse().ok()
94 }
95}
96
97impl std::fmt::Display for NodeVersion {
98 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99 f.write_fmt(format_args!(
100 "{}-{}-{}-{}",
101 self.version, self.git_hash, self.target, self.profile
102 ))
103 }
104}
105
106impl FromStr for NodeVersion {
107 type Err = ();
108
109 fn from_str(s: &str) -> Result<Self, Self::Err> {
110 let mut parts = s.split('-');
111 let version = parts.next().ok_or(())?.to_string();
112 let git_hash = parts.next().ok_or(())?.to_string();
113 let os = parts.next().ok_or(())?;
114 let arch = parts.next().ok_or(())?;
115 let target = format!("{}-{}", os, arch);
116 let profile = parts.next().ok_or(())?.to_string();
117 Ok(Self {
118 version,
119 git_hash,
120 target,
121 profile,
122 })
123 }
124}