winget_types/installer/
install_modes.rs

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