wslplugins_rs/
distribution_id.rs1use crate::{CoreWSLDistributionInformation, UserDistributionID};
19#[cfg(feature = "serde")]
20use serde::{Deserialize, Serialize};
21use std::fmt::Display;
22
23pub use crate::user_distribution_id::UserDistributionIDConversionError;
24
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
47pub enum DistributionID {
48 System,
51 User(UserDistributionID),
53}
54
55impl DistributionID {
56 #[must_use]
58 #[inline]
59 pub const fn is_user(&self) -> bool {
60 matches!(*self, Self::User(_))
61 }
62 #[must_use]
64 #[inline]
65 pub const fn is_system(&self) -> bool {
66 matches!(*self, Self::System)
67 }
68}
69
70impl From<UserDistributionID> for DistributionID {
71 #[inline]
72 fn from(value: UserDistributionID) -> Self {
73 Self::User(value)
74 }
75}
76
77impl From<&UserDistributionID> for DistributionID {
78 #[inline]
79 fn from(value: &UserDistributionID) -> Self {
80 Self::User(*value)
81 }
82}
83
84impl<T: CoreWSLDistributionInformation> From<&T> for DistributionID {
85 #[inline]
87 fn from(value: &T) -> Self {
88 value.id().into()
89 }
90}
91
92impl From<Option<UserDistributionID>> for DistributionID {
93 #[inline]
95 fn from(value: Option<UserDistributionID>) -> Self {
96 value.map_or(Self::System, Self::User)
97 }
98}
99
100impl From<DistributionID> for Option<UserDistributionID> {
101 #[inline]
103 fn from(value: DistributionID) -> Self {
104 match value {
105 DistributionID::System => None,
106 DistributionID::User(id) => Some(id),
107 }
108 }
109}
110
111impl Display for DistributionID {
112 #[inline]
116 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
117 match self {
118 Self::System => f.write_str("System"),
119 Self::User(id) => std::fmt::Display::fmt(id, f),
120 }
121 }
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127 use crate::api::errors::require_update_error::Result;
128 use proptest::prelude::*;
129 use std::ffi::OsString;
130
131 #[derive(Clone, Copy)]
132 struct TestDistribution {
133 id: UserDistributionID,
134 }
135
136 impl CoreWSLDistributionInformation for TestDistribution {
137 fn id(&self) -> UserDistributionID {
138 self.id
139 }
140
141 fn name(&self) -> OsString {
142 OsString::from("test")
143 }
144
145 fn package_family_name(&self) -> Option<OsString> {
146 None
147 }
148
149 fn flavor(&self) -> Result<Option<OsString>> {
150 Ok(None)
151 }
152
153 fn version(&self) -> Result<Option<OsString>> {
154 Ok(None)
155 }
156 }
157
158 #[test]
159 fn is_system_returns_true_for_system_distribution() {
160 assert!(DistributionID::System.is_system());
161 }
162
163 #[test]
164 fn is_user_returns_false_for_system_distribution() {
165 assert!(!DistributionID::System.is_user());
166 }
167
168 #[test]
169 fn from_none_returns_system() {
170 assert_eq!(
171 DistributionID::from(Option::<UserDistributionID>::None),
172 DistributionID::System
173 );
174 }
175
176 #[test]
177 fn option_from_system_returns_none() {
178 let maybe_user: Option<UserDistributionID> = DistributionID::System.into();
179 assert_eq!(maybe_user, None);
180 }
181
182 #[test]
183 fn display_for_system_is_system() {
184 assert_eq!(format!("{}", DistributionID::System), "System");
185 }
186
187 proptest! {
188 #[test]
189 fn is_system_returns_false_for_user_distribution(raw_id in any::<u128>()) {
190 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
191
192 prop_assert!(!DistributionID::User(user_id).is_system());
193 }
194
195 #[test]
196 fn is_user_returns_true_for_user_distribution(raw_id in any::<u128>()) {
197 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
198
199 prop_assert!(DistributionID::User(user_id).is_user());
200 }
201
202 #[test]
203 fn try_from_user_returns_inner_id(raw_id in any::<u128>()) {
204 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
205
206 prop_assert_eq!(
207 UserDistributionID::try_from(DistributionID::User(user_id)),
208 Ok(user_id)
209 );
210 }
211
212 #[test]
213 fn from_user_distribution_id_wraps_user_variant(raw_id in any::<u128>()) {
214 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
215
216 prop_assert_eq!(DistributionID::from(user_id), DistributionID::User(user_id));
217 }
218
219 #[test]
220 fn from_user_distribution_id_reference_wraps_user_variant(raw_id in any::<u128>()) {
221 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
222
223 prop_assert_eq!(DistributionID::from(&user_id), DistributionID::User(user_id));
224 }
225
226 #[test]
227 fn from_some_user_distribution_id_wraps_user_variant(raw_id in any::<u128>()) {
228 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
229
230 prop_assert_eq!(
231 DistributionID::from(Some(user_id)),
232 DistributionID::User(user_id)
233 );
234 }
235
236 #[test]
237 fn option_from_user_distribution_returns_some_inner_id(raw_id in any::<u128>()) {
238 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
239 let maybe_user: Option<UserDistributionID> = DistributionID::User(user_id).into();
240
241 prop_assert_eq!(maybe_user, Some(user_id));
242 }
243
244 #[test]
245 fn display_for_user_delegates_to_user_distribution_id(raw_id in any::<u128>()) {
246 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
247
248 prop_assert_eq!(
249 format!("{}", DistributionID::User(user_id)),
250 format!("{user_id}")
251 );
252 }
253
254 #[test]
255 fn from_core_distribution_information_uses_the_underlying_id(raw_id in any::<u128>()) {
256 let user_id = UserDistributionID::from(windows_core::GUID::from_u128(raw_id));
257 let distribution = TestDistribution { id: user_id };
258
259 prop_assert_eq!(DistributionID::from(&distribution), DistributionID::User(user_id));
260 }
261 }
262}