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) { Ok(()) } else { Err(Error::RestrictedFeature(feature.to_string())) }
28 }
29}
30
31impl From<Vec<Feature>> for FeatureSet {
32 fn from(features: Vec<Feature>) -> FeatureSet {
33 FeatureSet(features)
34 }
35}
36
37#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum Feature {
40 Dictionaries,
43
44 DynamicDictionaries,
47
48 UseDictionaries,
50
51 AllowLongNames,
53
54 AllowNonHermeticPackages,
57
58 EnableAllowNonHermeticPackagesFeature,
61
62 RestrictTestTypeInFacet,
64}
65
66impl FromStr for Feature {
67 type Err = String;
68 fn from_str(s: &str) -> Result<Self, Self::Err> {
69 match s {
70 "dictionaries" => Ok(Feature::Dictionaries),
71 "dynamic_dictionaries" => Ok(Feature::DynamicDictionaries),
72 "use_dictionaries" => Ok(Feature::UseDictionaries),
73 "allow_long_names" => Ok(Feature::AllowLongNames),
74 "allow_non_hermetic_packages" => Ok(Feature::AllowNonHermeticPackages),
75 "enable_allow_non_hermetic_packages_feature" => {
76 Ok(Feature::EnableAllowNonHermeticPackagesFeature)
77 }
78 "restrict_test_type_in_facets" => Ok(Feature::RestrictTestTypeInFacet),
79 _ => Err(format!("unrecognized feature \"{}\"", s)),
80 }
81 }
82}
83
84impl fmt::Display for Feature {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.write_str(match self {
87 Feature::Dictionaries => "dictionaries",
88 Feature::DynamicDictionaries => "dynamic_dictionaries",
89 Feature::UseDictionaries => "use_dictionaries",
90 Feature::AllowLongNames => "allow_long_names",
91 Feature::AllowNonHermeticPackages => "allow_non_hermetic_packages",
92 Feature::EnableAllowNonHermeticPackagesFeature => {
93 "enable_allow_non_hermetic_packages_feature"
94 }
95 Feature::RestrictTestTypeInFacet => "restrict_test_type_in_facets",
96 })
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::*;
103 use assert_matches::assert_matches;
104
105 #[test]
106 fn feature_is_parsed() {
107 assert_eq!(Feature::AllowLongNames, "allow_long_names".parse::<Feature>().unwrap());
108 assert_eq!(
109 Feature::AllowNonHermeticPackages,
110 "allow_non_hermetic_packages".parse::<Feature>().unwrap()
111 );
112 }
113
114 #[test]
115 fn feature_is_printed() {
116 assert_eq!("allow_long_names", Feature::AllowLongNames.to_string());
117 assert_eq!("allow_non_hermetic_packages", Feature::AllowNonHermeticPackages.to_string());
118 assert_eq!(
119 "enable_allow_non_hermetic_packages_feature",
120 Feature::EnableAllowNonHermeticPackagesFeature.to_string()
121 );
122 assert_eq!("restrict_test_type_in_facets", Feature::RestrictTestTypeInFacet.to_string());
123 }
124
125 #[test]
126 fn feature_set_has() {
127 let set = FeatureSet::empty();
128 assert!(!set.has(&Feature::AllowLongNames));
129
130 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
131 assert!(set.has(&Feature::AllowLongNames));
132 }
133
134 #[test]
135 fn feature_set_check() {
136 let set = FeatureSet::empty();
137 assert_matches!(
138 set.check(Feature::AllowLongNames),
139 Err(Error::RestrictedFeature(f)) if f == "allow_long_names"
140 );
141
142 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
143 assert_matches!(set.check(Feature::AllowLongNames), Ok(()));
144 }
145}