winget_types/shared/
manifest_version.rs

1use core::{fmt, num::ParseIntError, str::FromStr};
2
3use thiserror::Error;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
6#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
7#[cfg_attr(feature = "serde", serde(try_from = "&str"))]
8pub struct ManifestVersion(u16, u16, u16);
9
10#[derive(Error, Debug, Eq, PartialEq)]
11pub enum ManifestVersionError {
12    #[error("Manifest version must have a major part")]
13    NoMajorVersion,
14    #[error("Manifest version must have a minor part")]
15    NoMinorVersion,
16    #[error("Manifest version must have a patch part")]
17    NoPatchVersion,
18    #[error(transparent)]
19    InvalidPart(#[from] ParseIntError),
20}
21
22impl ManifestVersion {
23    pub const DEFAULT: Self = Self(1, 10, 0);
24    const PARTS_COUNT: u8 = 3;
25    const SEPARATOR: char = '.';
26
27    /// Creates a new `ManifestVersion` from a `major`, `minor`, and `patch` part.
28    #[must_use]
29    #[inline]
30    pub const fn new(major: u16, minor: u16, patch: u16) -> Self {
31        Self(major, minor, patch)
32    }
33}
34
35impl Default for ManifestVersion {
36    fn default() -> Self {
37        Self::DEFAULT
38    }
39}
40
41impl fmt::Display for ManifestVersion {
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        write!(f, "{}.{}.{}", self.0, self.1, self.2)
44    }
45}
46
47impl FromStr for ManifestVersion {
48    type Err = ManifestVersionError;
49
50    fn from_str(s: &str) -> Result<Self, Self::Err> {
51        let mut parts = s.splitn(Self::PARTS_COUNT as usize, Self::SEPARATOR);
52
53        let major = parts
54            .next()
55            .ok_or(ManifestVersionError::NoMajorVersion)?
56            .parse::<u16>()?;
57        let minor = parts
58            .next()
59            .ok_or(ManifestVersionError::NoMinorVersion)?
60            .parse::<u16>()?;
61        let patch = parts
62            .next()
63            .ok_or(ManifestVersionError::NoPatchVersion)?
64            .parse::<u16>()?;
65
66        Ok(Self(major, minor, patch))
67    }
68}
69
70impl TryFrom<&str> for ManifestVersion {
71    type Error = ManifestVersionError;
72
73    #[inline]
74    fn try_from(value: &str) -> Result<Self, Self::Error> {
75        value.parse()
76    }
77}
78
79#[cfg(feature = "serde")]
80impl serde::Serialize for ManifestVersion
81where
82    Self: fmt::Display,
83{
84    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
85    where
86        S: serde::Serializer,
87    {
88        serializer.collect_str(&self)
89    }
90}