winget_types/shared/
manifest_version.rs1use std::{num::ParseIntError, str::FromStr};
2
3use const_format::{ConstDebug, Error, Formatter, writec};
4use derive_more::Display;
5use serde_with::{DeserializeFromStr, SerializeDisplay};
6use thiserror::Error;
7
8#[derive(
9 ConstDebug,
10 Debug,
11 Display,
12 Eq,
13 PartialEq,
14 Ord,
15 PartialOrd,
16 Hash,
17 SerializeDisplay,
18 DeserializeFromStr,
19)]
20#[display("{_0}.{_1}.{_2}")]
21pub struct ManifestVersion(u16, u16, u16);
22
23#[derive(Error, Debug, Eq, PartialEq)]
24pub enum ManifestVersionError {
25 #[error("Manifest version must have a major part")]
26 NoMajorVersion,
27 #[error("Manifest version must have a minor part")]
28 NoMinorVersion,
29 #[error("Manifest version must have a patch part")]
30 NoPatchVersion,
31 #[error(transparent)]
32 InvalidPart(#[from] ParseIntError),
33}
34
35impl ManifestVersion {
36 pub const DEFAULT: Self = Self(1, 9, 0);
37 const PARTS_COUNT: u8 = 3;
38 const SEPARATOR: char = '.';
39
40 pub fn new<S: AsRef<str>>(input: S) -> Result<Self, ManifestVersionError> {
41 let mut parts = input
42 .as_ref()
43 .splitn(Self::PARTS_COUNT as usize, Self::SEPARATOR);
44 let major = parts
45 .next()
46 .ok_or(ManifestVersionError::NoMajorVersion)?
47 .parse::<u16>()?;
48 let minor = parts
49 .next()
50 .ok_or(ManifestVersionError::NoMinorVersion)?
51 .parse::<u16>()?;
52 let patch = parts
53 .next()
54 .ok_or(ManifestVersionError::NoPatchVersion)?
55 .parse::<u16>()?;
56 Ok(Self(major, minor, patch))
57 }
58
59 pub const fn const_display_fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
60 writec!(f, "{}.{}.{}", self.0, self.1, self.2)
61 }
62}
63
64impl Default for ManifestVersion {
65 fn default() -> Self {
66 Self::DEFAULT
67 }
68}
69
70impl FromStr for ManifestVersion {
71 type Err = ManifestVersionError;
72
73 fn from_str(s: &str) -> Result<Self, Self::Err> {
74 Self::new(s)
75 }
76}