wslplugins_rs/wsl_version/
capability.rs1use super::WSLVersion;
2use crate::api::errors::RequirementDefinition;
3use std::collections::HashSet;
4use strum::{Display, EnumIter};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Display, EnumIter)]
8#[non_exhaustive]
9pub enum WSLVersionCapability {
10 DistributionInitPid,
12 DistributionRegisteredHook,
14 DistributionUnregisteredHook,
16 ExecuteBinaryInDistribution,
18 DistributionFlavor,
20 DistributionVersion,
22}
23
24impl WSLVersionCapability {
25 #[must_use]
27 #[inline]
28 pub const fn required_version(self) -> WSLVersion {
29 match self {
30 Self::DistributionInitPid => WSLVersion::new(2, 0, 5),
31 Self::DistributionRegisteredHook
32 | Self::DistributionUnregisteredHook
33 | Self::ExecuteBinaryInDistribution => WSLVersion::new(2, 1, 2),
34 Self::DistributionFlavor | Self::DistributionVersion => WSLVersion::new(2, 4, 4),
35 }
36 }
37}
38
39impl TryFrom<RequirementDefinition> for WSLVersionCapability {
40 type Error = RequirementDefinition;
41
42 #[inline]
43 fn try_from(value: RequirementDefinition) -> std::result::Result<Self, Self::Error> {
44 match value {
45 RequirementDefinition::Capabilities(capabilities) if capabilities.len() == 1 => {
46 capabilities
47 .into_iter()
48 .next()
49 .ok_or_else(|| RequirementDefinition::Capabilities(HashSet::new()))
50 }
51 requirement => Err(requirement),
52 }
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use super::*;
59 use proptest::prelude::*;
60 use strum::IntoEnumIterator as _;
61
62 fn arb_capability() -> impl Strategy<Value = WSLVersionCapability> {
63 prop::sample::select(WSLVersionCapability::iter().collect::<Vec<_>>())
64 }
65
66 #[test]
67 fn single_capability_requirement_can_be_recovered() {
68 let capability = WSLVersionCapability::ExecuteBinaryInDistribution;
69 let requirement = RequirementDefinition::from(capability);
70
71 assert_eq!(WSLVersionCapability::try_from(requirement), Ok(capability));
72 }
73
74 #[test]
75 fn multi_capability_requirement_cannot_be_recovered_as_single_capability() {
76 let requirement = RequirementDefinition::from([
77 WSLVersionCapability::DistributionRegisteredHook,
78 WSLVersionCapability::DistributionUnregisteredHook,
79 ]);
80
81 assert!(WSLVersionCapability::try_from(requirement).is_err());
82 }
83
84 proptest! {
85 #[test]
86 fn single_capability_requirement_roundtrips(capability in arb_capability()) {
87 let requirement = RequirementDefinition::from(capability);
88
89 prop_assert_eq!(WSLVersionCapability::try_from(requirement), Ok(capability));
90 }
91 }
92}