winget_types/installer/
platform.rs1use core::{fmt, str::FromStr};
2
3use bitflags::bitflags;
4use thiserror::Error;
5
6bitflags! {
7 #[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Ord, PartialOrd, Hash)]
9 pub struct Platform: u8 {
10 const WINDOWS_DESKTOP = 1;
11 const WINDOWS_UNIVERSAL = 1 << 1;
12 }
13}
14
15const WINDOWS_DESKTOP: &str = "Windows.Desktop";
16const WINDOWS_UNIVERSAL: &str = "Windows.Universal";
17
18impl fmt::Display for Platform {
19 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20 match *self {
21 Self::WINDOWS_DESKTOP => f.write_str(WINDOWS_DESKTOP),
22 Self::WINDOWS_UNIVERSAL => f.write_str(WINDOWS_UNIVERSAL),
23 _ => bitflags::parser::to_writer(self, f),
24 }
25 }
26}
27
28#[derive(Error, Debug, Eq, PartialEq)]
29#[error("Platform did not match either `{WINDOWS_DESKTOP}` or `{WINDOWS_UNIVERSAL}`")]
30pub struct PlatformParseError;
31
32impl FromStr for Platform {
33 type Err = PlatformParseError;
34
35 fn from_str(s: &str) -> Result<Self, Self::Err> {
36 match s {
37 WINDOWS_DESKTOP => Ok(Self::WINDOWS_DESKTOP),
38 WINDOWS_UNIVERSAL => Ok(Self::WINDOWS_UNIVERSAL),
39 _ => Err(PlatformParseError),
40 }
41 }
42}
43
44#[cfg(feature = "serde")]
45impl serde::Serialize for Platform {
46 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47 where
48 S: serde::Serializer,
49 {
50 use serde::ser::SerializeSeq;
51
52 let mut seq = serializer.serialize_seq(Some(self.iter().count()))?;
53 for platform in self.iter() {
54 match platform {
55 Self::WINDOWS_DESKTOP => seq.serialize_element(WINDOWS_DESKTOP)?,
56 Self::WINDOWS_UNIVERSAL => seq.serialize_element(WINDOWS_UNIVERSAL)?,
57 _ => {}
58 }
59 }
60 seq.end()
61 }
62}
63
64#[cfg(feature = "serde")]
65impl<'de> serde::Deserialize<'de> for Platform {
66 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
67 where
68 D: serde::Deserializer<'de>,
69 {
70 struct PlatformVisitor;
71
72 impl<'de> serde::de::Visitor<'de> for PlatformVisitor {
73 type Value = Platform;
74
75 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
76 formatter.write_str("a sequence of platform strings")
77 }
78
79 fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
80 where
81 V: serde::de::SeqAccess<'de>,
82 {
83 let mut platform = Platform::empty();
84
85 while let Some(value) = seq.next_element::<&str>()? {
86 match value {
87 WINDOWS_DESKTOP => platform |= Platform::WINDOWS_DESKTOP,
88 WINDOWS_UNIVERSAL => platform |= Platform::WINDOWS_UNIVERSAL,
89 _ => {
90 return Err(serde::de::Error::unknown_variant(
91 value,
92 &[WINDOWS_DESKTOP, WINDOWS_UNIVERSAL],
93 ));
94 }
95 }
96 }
97
98 Ok(platform)
99 }
100 }
101
102 deserializer.deserialize_seq(PlatformVisitor)
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 #[cfg(feature = "serde")]
109 use indoc::indoc;
110 #[cfg(feature = "serde")]
111 use rstest::rstest;
112
113 use super::{Platform, PlatformParseError};
114
115 #[cfg(feature = "serde")]
116 #[rstest]
117 #[case(
118 Platform::all(),
119 indoc! {"
120 - Windows.Desktop
121 - Windows.Universal
122 "}
123 )]
124 #[case(
125 Platform::empty(),
126 indoc! {"
127 []
128 "}
129 )]
130 #[case(
131 Platform::WINDOWS_DESKTOP,
132 indoc! {"
133 - Windows.Desktop
134 "}
135 )]
136 #[case(
137 Platform::WINDOWS_UNIVERSAL,
138 indoc! {"
139 - Windows.Universal
140 "}
141 )]
142 fn serialize_platform(#[case] platform: Platform, #[case] expected: &str) {
143 assert_eq!(serde_yaml::to_string(&platform).unwrap(), expected);
144 }
145
146 #[cfg(feature = "serde")]
147 #[rstest]
148 #[case(
149 indoc! {"
150 - Windows.Desktop
151 - Windows.Universal
152 "},
153 Platform::all(),
154 )]
155 #[case(
156 indoc! {"
157 []
158 "},
159 Platform::empty()
160 )]
161 #[case(
162 indoc! {"
163 - Windows.Desktop
164 "},
165 Platform::WINDOWS_DESKTOP
166 )]
167 #[case(
168 indoc! {"
169 - Windows.Universal
170 "},
171 Platform::WINDOWS_UNIVERSAL
172 )]
173 fn deserialize_platform(#[case] input: &str, #[case] expected: Platform) {
174 assert_eq!(serde_yaml::from_str::<Platform>(input).unwrap(), expected);
175 }
176
177 #[cfg(feature = "serde")]
178 #[test]
179 fn platform_serialize_ordered() {
180 let input = indoc! {"
181 - Windows.Universal
182 - Windows.Desktop
183 "};
184
185 let deserialized = serde_yaml::from_str::<Platform>(input).unwrap();
186
187 assert_eq!(
188 serde_yaml::to_string(&deserialized).unwrap(),
189 indoc! {"
190 - Windows.Desktop
191 - Windows.Universal
192 "}
193 );
194 }
195
196 #[test]
197 fn from_str() {
198 assert!("Windows.Desktop".parse::<Platform>().is_ok());
199 assert!("Windows.Universal".parse::<Platform>().is_ok());
200 assert_eq!(
201 "WindowsDesktop".parse::<Platform>().err().unwrap(),
202 PlatformParseError
203 );
204 }
205}