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 DeliveryType,
68}
69
70impl FromStr for Feature {
71 type Err = String;
72 fn from_str(s: &str) -> Result<Self, Self::Err> {
73 match s {
74 "dictionaries" => Ok(Feature::Dictionaries),
75 "dynamic_dictionaries" => Ok(Feature::DynamicDictionaries),
76 "use_dictionaries" => Ok(Feature::UseDictionaries),
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::UseDictionaries => "use_dictionaries",
95 Feature::AllowLongNames => "allow_long_names",
96 Feature::AllowNonHermeticPackages => "allow_non_hermetic_packages",
97 Feature::EnableAllowNonHermeticPackagesFeature => {
98 "enable_allow_non_hermetic_packages_feature"
99 }
100 Feature::RestrictTestTypeInFacet => "restrict_test_type_in_facets",
101 Feature::DeliveryType => "delivery_type",
102 })
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 use super::*;
109 use assert_matches::assert_matches;
110
111 #[test]
112 fn feature_is_parsed() {
113 assert_eq!(Feature::AllowLongNames, "allow_long_names".parse::<Feature>().unwrap());
114 assert_eq!(
115 Feature::AllowNonHermeticPackages,
116 "allow_non_hermetic_packages".parse::<Feature>().unwrap()
117 );
118 }
119
120 #[test]
121 fn feature_is_printed() {
122 assert_eq!("allow_long_names", Feature::AllowLongNames.to_string());
123 assert_eq!("allow_non_hermetic_packages", Feature::AllowNonHermeticPackages.to_string());
124 assert_eq!(
125 "enable_allow_non_hermetic_packages_feature",
126 Feature::EnableAllowNonHermeticPackagesFeature.to_string()
127 );
128 assert_eq!("restrict_test_type_in_facets", Feature::RestrictTestTypeInFacet.to_string());
129 }
130
131 #[test]
132 fn feature_set_has() {
133 let set = FeatureSet::empty();
134 assert!(!set.has(&Feature::AllowLongNames));
135
136 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
137 assert!(set.has(&Feature::AllowLongNames));
138 }
139
140 #[test]
141 fn feature_set_check() {
142 let set = FeatureSet::empty();
143 assert_matches!(
144 set.check(Feature::AllowLongNames),
145 Err(Error::RestrictedFeature(f)) if f == "allow_long_names"
146 );
147
148 let set = FeatureSet::from(vec![Feature::AllowLongNames]);
149 assert_matches!(set.check(Feature::AllowLongNames), Ok(()));
150 }
151}