Skip to main content

hyperi_rustlib/cli/
version.rs

1// Project:   hyperi-rustlib
2// File:      src/cli/version.rs
3// Purpose:   Version information types
4// Language:  Rust
5//
6// License:   BUSL-1.1
7// Copyright: (c) 2026 HYPERI PTY LIMITED
8
9//! Version information for DFE services.
10
11use std::fmt;
12
13/// Service version information.
14///
15/// Populated at build time via `env!()` macros or passed by the application.
16#[derive(Debug, Clone)]
17pub struct VersionInfo {
18    /// Service name (e.g. "dfe-loader").
19    pub name: String,
20    /// Semantic version (e.g. "1.9.7").
21    pub version: String,
22    /// Git commit SHA (short).
23    pub commit: Option<String>,
24    /// Build date (RFC 3339).
25    pub build_date: Option<String>,
26    /// Rust compiler version.
27    pub rustc_version: Option<String>,
28    /// Target triple (e.g. "x86_64-unknown-linux-gnu").
29    pub target: Option<String>,
30    /// rustlib version.
31    pub rustlib_version: String,
32}
33
34impl VersionInfo {
35    /// Create with required fields, using rustlib version from this crate.
36    #[must_use]
37    pub fn new(name: impl Into<String>, version: impl Into<String>) -> Self {
38        Self {
39            name: name.into(),
40            version: version.into(),
41            commit: None,
42            build_date: None,
43            rustc_version: None,
44            target: None,
45            rustlib_version: crate::VERSION.to_string(),
46        }
47    }
48
49    /// Set git commit SHA.
50    #[must_use]
51    pub fn with_commit(mut self, commit: impl Into<String>) -> Self {
52        self.commit = Some(commit.into());
53        self
54    }
55
56    /// Set build date.
57    #[must_use]
58    pub fn with_build_date(mut self, date: impl Into<String>) -> Self {
59        self.build_date = Some(date.into());
60        self
61    }
62
63    /// Set Rust compiler version.
64    #[must_use]
65    pub fn with_rustc(mut self, version: impl Into<String>) -> Self {
66        self.rustc_version = Some(version.into());
67        self
68    }
69
70    /// Set target triple.
71    #[must_use]
72    pub fn with_target(mut self, target: impl Into<String>) -> Self {
73        self.target = Some(target.into());
74        self
75    }
76
77    /// Short version string: "name version (commit)".
78    #[must_use]
79    pub fn short(&self) -> String {
80        match &self.commit {
81            Some(c) => format!("{} {} ({})", self.name, self.version, c),
82            None => format!("{} {}", self.name, self.version),
83        }
84    }
85}
86
87impl fmt::Display for VersionInfo {
88    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89        writeln!(f, "{} {}", self.name, self.version)?;
90        if let Some(ref c) = self.commit {
91            writeln!(f, "  commit:  {c}")?;
92        }
93        if let Some(ref d) = self.build_date {
94            writeln!(f, "  built:   {d}")?;
95        }
96        if let Some(ref r) = self.rustc_version {
97            writeln!(f, "  rustc:   {r}")?;
98        }
99        if let Some(ref t) = self.target {
100            writeln!(f, "  target:  {t}")?;
101        }
102        write!(f, "  rustlib: {}", self.rustlib_version)
103    }
104}
105
106#[cfg(test)]
107mod tests {
108    use super::*;
109
110    #[test]
111    fn test_version_info_new() {
112        let v = VersionInfo::new("dfe-loader", "1.9.7");
113        assert_eq!(v.name, "dfe-loader");
114        assert_eq!(v.version, "1.9.7");
115        assert!(v.commit.is_none());
116        assert_eq!(v.rustlib_version, crate::VERSION);
117    }
118
119    #[test]
120    fn test_version_info_builder() {
121        let v = VersionInfo::new("dfe-loader", "1.9.7")
122            .with_commit("abc1234")
123            .with_build_date("2026-03-03")
124            .with_rustc("1.85.0")
125            .with_target("x86_64-unknown-linux-gnu");
126
127        assert_eq!(v.commit.as_deref(), Some("abc1234"));
128        assert_eq!(v.build_date.as_deref(), Some("2026-03-03"));
129        assert_eq!(v.rustc_version.as_deref(), Some("1.85.0"));
130        assert_eq!(v.target.as_deref(), Some("x86_64-unknown-linux-gnu"));
131    }
132
133    #[test]
134    fn test_version_info_short() {
135        let v = VersionInfo::new("dfe-loader", "1.9.7").with_commit("abc1234");
136        assert_eq!(v.short(), "dfe-loader 1.9.7 (abc1234)");
137
138        let v2 = VersionInfo::new("dfe-loader", "1.9.7");
139        assert_eq!(v2.short(), "dfe-loader 1.9.7");
140    }
141
142    #[test]
143    fn test_version_info_display() {
144        let v = VersionInfo::new("dfe-loader", "1.9.7")
145            .with_commit("abc1234")
146            .with_target("x86_64-unknown-linux-gnu");
147
148        let output = v.to_string();
149        assert!(output.contains("dfe-loader 1.9.7"));
150        assert!(output.contains("commit:  abc1234"));
151        assert!(output.contains("target:  x86_64-unknown-linux-gnu"));
152        assert!(output.contains(&format!("rustlib: {}", crate::VERSION)));
153    }
154}