bity_ic_types/build_version.rs
1//! Provides version management utilities for Internet Computer canisters.
2//!
3//! This module implements a semantic versioning system through the `BuildVersion` struct,
4//! following the MAJOR.MINOR.PATCH format.
5
6use candid::CandidType;
7use serde::{Deserialize, Serialize};
8use std::fmt::{Display, Formatter};
9use std::str::FromStr;
10
11/// Represents a semantic version number following the MAJOR.MINOR.PATCH format.
12///
13/// # Examples
14///
15/// ```
16/// use types::BuildVersion;
17///
18/// let version = BuildVersion::new(1, 2, 3);
19/// assert_eq!(version.to_string(), "1.2.3");
20///
21/// let parsed = "1.2.3".parse::<BuildVersion>().unwrap();
22/// assert_eq!(version, parsed);
23/// ```
24#[derive(
25 CandidType, Serialize, Deserialize, Clone, Copy, Debug, Default, Ord, PartialOrd, Eq, PartialEq,
26)]
27pub struct BuildVersion {
28 /// Major version number, incremented for incompatible API changes
29 pub major: u32,
30 /// Minor version number, incremented for backwards-compatible functionality additions
31 pub minor: u32,
32 /// Patch version number, incremented for backwards-compatible bug fixes
33 pub patch: u32,
34}
35
36impl BuildVersion {
37 /// Creates a new BuildVersion with the specified version numbers.
38 ///
39 /// # Arguments
40 ///
41 /// * `major` - The major version number
42 /// * `minor` - The minor version number
43 /// * `patch` - The patch version number
44 pub fn new(major: u32, minor: u32, patch: u32) -> BuildVersion {
45 BuildVersion {
46 major,
47 minor,
48 patch,
49 }
50 }
51
52 /// Returns the minimum possible version (0.0.0).
53 pub fn min() -> BuildVersion {
54 BuildVersion::default()
55 }
56}
57
58impl Display for BuildVersion {
59 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
60 f.write_str(&format!("{}.{}.{}", self.major, self.minor, self.patch))
61 }
62}
63
64impl FromStr for BuildVersion {
65 type Err = String;
66
67 fn from_str(s: &str) -> Result<Self, Self::Err> {
68 let parts: Vec<_> = s.split('.').collect();
69 if parts.len() != 3 {
70 return Err(format!("Unable to parse version: {s}"));
71 }
72
73 let major = u32::from_str(parts[0]).map_err(|e| e.to_string())?;
74 let minor = u32::from_str(parts[1]).map_err(|e| e.to_string())?;
75 let patch = u32::from_str(parts[2]).map_err(|e| e.to_string())?;
76
77 Ok(BuildVersion {
78 major,
79 minor,
80 patch,
81 })
82 }
83}