rtb_app/version.rs
1//! Build-time version information.
2
3use semver::Version;
4use serde::{Deserialize, Serialize};
5
6/// Version information captured at build time.
7///
8/// Populate the `version` field from `env!("CARGO_PKG_VERSION")` (the
9/// [`VersionInfo::from_env`] helper does this) and inject `commit` /
10/// `date` via your `build.rs` (the `vergen` or `built` crates are
11/// canonical).
12#[derive(Debug, Clone, Serialize, Deserialize)]
13pub struct VersionInfo {
14 /// Parsed semantic version.
15 pub version: Version,
16
17 /// Short commit SHA, if known at build time.
18 #[serde(default)]
19 pub commit: Option<String>,
20
21 /// ISO-8601 build timestamp, if known at build time.
22 #[serde(default)]
23 pub date: Option<String>,
24}
25
26impl VersionInfo {
27 /// Construct from a parsed semver. `commit` and `date` start unset
28 /// — add them with [`Self::with_commit`] / [`Self::with_date`].
29 #[must_use]
30 pub const fn new(version: Version) -> Self {
31 Self { version, commit: None, date: None }
32 }
33
34 /// Fluent setter for the commit SHA.
35 #[must_use]
36 pub fn with_commit(mut self, commit: impl Into<String>) -> Self {
37 self.commit = Some(commit.into());
38 self
39 }
40
41 /// Fluent setter for the build timestamp.
42 #[must_use]
43 pub fn with_date(mut self, date: impl Into<String>) -> Self {
44 self.date = Some(date.into());
45 self
46 }
47
48 /// Convenience: parse `CARGO_PKG_VERSION` with a silent fallback to
49 /// `0.0.0` when parsing fails (which in turn is flagged by
50 /// [`Self::is_development`]).
51 ///
52 /// Call this inside `fn main()` — it's evaluated per-invocation,
53 /// not per-build.
54 #[must_use]
55 pub fn from_env() -> Self {
56 let raw = env!("CARGO_PKG_VERSION");
57 let version = Version::parse(raw).unwrap_or_else(|_| Version::new(0, 0, 0));
58 Self::new(version)
59 }
60
61 /// `true` when this build is a development / pre-release build.
62 ///
63 /// Development is any of:
64 ///
65 /// * `major == 0` (pre-1.0 builds are always considered development),
66 /// * a non-empty pre-release identifier (`-alpha`, `-dev.5`, …),
67 /// * version exactly `0.0.0` (the [`Self::from_env`] fallback).
68 #[must_use]
69 pub fn is_development(&self) -> bool {
70 self.version.major == 0 || !self.version.pre.is_empty()
71 }
72}