Skip to main content

xmtp_mls_core/
version.rs

1use std::sync::Arc;
2
3use xmtp_mls_group_state::libxmtp_version::LibXMTPVersion;
4
5#[derive(Clone, Debug, PartialEq)]
6pub struct VersionInfo {
7    pkg_version: Arc<str>,
8    /// `pkg_version` parsed once at construction. This is the client's own
9    /// build identity, not remote data, so it is always valid semver
10    /// (see [`VersionInfo::new`]) — receive-path guards can compare against
11    /// it without re-parsing the string on every message.
12    pkg_semver: LibXMTPVersion,
13}
14
15impl Default for VersionInfo {
16    fn default() -> Self {
17        Self::new(env!("CARGO_PKG_VERSION"))
18    }
19}
20
21impl VersionInfo {
22    /// Build a `VersionInfo`, parsing and caching the semver form.
23    ///
24    /// `version` is the client's own package version — in production always
25    /// the compile-time `CARGO_PKG_VERSION`. A non-semver value is a build
26    /// or configuration bug, not runtime data, so it panics here rather than
27    /// silently disabling the below-floor pause on every group later.
28    fn new(version: &str) -> Self {
29        let pkg_semver = LibXMTPVersion::parse(version)
30            .unwrap_or_else(|_| panic!("client pkg_version {version:?} is not valid semver"));
31        Self {
32            pkg_version: version.into(),
33            pkg_semver,
34        }
35    }
36
37    pub fn pkg_version(&self) -> &str {
38        &self.pkg_version
39    }
40
41    /// The client's own version, parsed once at construction. Prefer this
42    /// over re-parsing [`pkg_version`](Self::pkg_version) on hot paths.
43    pub fn pkg_semver(&self) -> &LibXMTPVersion {
44        &self.pkg_semver
45    }
46
47    /// Makes this the version of a client a test builds, instead of the
48    /// package version.
49    #[cfg(any(test, feature = "test-hooks"))]
50    pub fn test_update_version(&mut self, version: &str) {
51        *self = Self::new(version);
52    }
53}