1use crate::error::Error;
6use std::fmt;
7use std::str::FromStr;
8
9#[derive(Debug)]
12pub struct FeatureSet(Vec<Feature>);
13
14impl FeatureSet {
15 pub const fn empty() -> FeatureSet {
17 FeatureSet(Vec::new())
18 }
19
20 pub fn has(&self, feature: &Feature) -> bool {
22 self.0.iter().find(|f| *f == feature).is_some()
23 }
24
25 pub fn check(&self, feature: Feature) -> Result<(), Error> {
27 if self.has(&feature) {
28 Ok(())
29 } else {
30 Err(Error::RestrictedFeature(feature.to_string()))
31 }
32 }
33}
34
35impl From<Vec<Feature>> for FeatureSet {
36 fn from(features: Vec<Feature>) -> FeatureSet {
37 FeatureSet(features)
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43pub enum Feature {
44 Dictionaries,
47
48 DynamicDictionaries,
51
52 AllowLongNames,
54
55 AllowNonHermeticPackages,
58
59 EnableAllowNonHermeticPackagesFeature,
62
63 RestrictTestTypeInFacet,
65
66 DeliveryType,
69}
70
71impl FromStr for Feature {
72 type Err = String;
73 fn from_str(s: &str) -> Result<Self, Self::Err> {
74 match s {
75 "dictionaries" => Ok(Feature::Dictionaries),
76 "dynamic_dictionaries" => Ok(Feature::DynamicDictionaries),
77 "allow_long_names" => Ok(Feature::AllowLongNames),
78 "allow_non_hermetic_packages" => Ok(Feature::AllowNonHermeticPackages),
79 "enable_allow_non_hermetic_packages_feature" => {
80 Ok(Feature::EnableAllowNonHermeticPackagesFeature)
81 }
82 "restrict_test_type_in_facets" => Ok(Feature::RestrictTestTypeInFacet),
83 "delivery_type" => Ok(Feature::DeliveryType),
84 _ => Err(format!("unrecognized feature \"{}\"", s)),
85 }
86 }
87}
88
89impl fmt::Display for Feature {
90 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91 f.write_str(match self {
92 Feature::Dictionaries => "dictionaries",
93 Feature::DynamicDictionaries => "dynamic_dictionaries",
94 Feature::AllowLongNames => "allow_long_names",
95 Feature::AllowNonHermeticPackages => "allow_non_hermetic_packages",
96 Feature::EnableAllowNonHermeticPackagesFeature => {
97 "enable_allow_non_hermetic_packages_feature"
98 }
99 Feature::RestrictTestTypeInFacet => "restrict_test_type_in_facets",
100 Feature::DeliveryType => "delivery_type",
101 })
102 }
103}
104
105#[cfg(test)]
106mod tests {
107 use super::*;
108 use assert_matches::assert_matches;
109
110 #[test]
111 fn feature_is_parsed() {
112 assert_eq!(Feature::AllowLongNames, "allow_long_names".parse::<Feature>().unwrap());
113 assert_eq!(
114 Feature::AllowNonHermeticPackages,
115 "allow_non_hermetic_packages".parse::<Feature>().unwrap()
116 );
117 }
118
119 #[test]
120 fn feature_is_printed() {
121 assert_eq!("allow_long_names", Feature::AllowLongNames.to_string());
122 assert_eq!("allow_non_hermetic_packages", Feature::AllowNonHermeticPackages.to_string());
123 assert_eq!(
124 "enable_allow_non_hermetic_packages_feature",
125 Feature::EnableAllowNonHermeticPackagesFeature.to_string()
126 );
127 assert_eq!("restrict_test_type_in_facets", Feature::RestrictTestTypeInFacet.to_string());
128 }
129
130 #[test]
131 fn feature_set_has() {
132 let set = FeatureSet::empty();
133 assert!(!set.has(&Feature::AllowLongNames));
134
135 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
136 assert!(set.has(&Feature::AllowLongNames));
137 }
138
139 #[test]
140 fn feature_set_check() {
141 let set = FeatureSet::empty();
142 assert_matches!(
143 set.check(Feature::AllowLongNames),
144 Err(Error::RestrictedFeature(f)) if f == "allow_long_names"
145 );
146
147 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
148 assert_matches!(set.check(Feature::AllowLongNames), Ok(()));
149 }
150}