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