manifest.rs (11545B)
1 use core::fmt::{self, Formatter}; 2 use serde::de::{Deserialize, Deserializer, Error, IgnoredAny, MapAccess, SeqAccess, Visitor}; 3 use std::collections::{HashMap, HashSet}; 4 use toml::de::Error as TomlErr; 5 /// Features that are enabled by another feature. 6 struct ImpliedFeatures(HashSet<String>); 7 impl ImpliedFeatures { 8 /// Returns `true` iff any feature in the `ImpliedFeatures` graph is `feature`. 9 fn contains(&self, feature: &str, features: &Features) -> bool { 10 /// Recursively iterates the features in `left` and checks if one is `feature`. 11 fn recurse<'a: 'e, 'b, 'c: 'e, 'd, 'e>( 12 left: &'a ImpliedFeatures, 13 feature: &'b str, 14 features: &'c Features, 15 cycle_detection: &'d mut HashSet<&'e str>, 16 ) -> Result<(), ()> { 17 left.0.iter().try_fold((), |(), feat| { 18 if feat == feature || !cycle_detection.insert(feat) { 19 Err(()) 20 } else { 21 features 22 .0 23 .get(feat) 24 // This will be `None` iff `feat` is a dependency-related feature. 25 .map_or(Ok(()), |f| recurse(f, feature, features, cycle_detection)) 26 } 27 }) 28 } 29 let mut recursion_detection = HashSet::new(); 30 recurse(self, feature, features, &mut recursion_detection).is_err() 31 } 32 } 33 impl<'de> Deserialize<'de> for ImpliedFeatures { 34 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 35 where 36 D: Deserializer<'de>, 37 { 38 /// `Visitor` for `ImpliedFeatures`. 39 struct ImpliedFeaturesVisitor; 40 impl<'d> Visitor<'d> for ImpliedFeaturesVisitor { 41 type Value = ImpliedFeatures; 42 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { 43 formatter.write_str("ImpliedFeatures") 44 } 45 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error> 46 where 47 A: SeqAccess<'d>, 48 { 49 let mut feats = HashSet::with_capacity(seq.size_hint().unwrap_or_default()); 50 while let Some(val) = seq.next_element::<String>()? { 51 feats.insert(val); 52 } 53 Ok(ImpliedFeatures(feats)) 54 } 55 } 56 deserializer.deserialize_seq(ImpliedFeaturesVisitor) 57 } 58 } 59 /// Features with the features that are enabled. 60 struct Features(HashMap<String, ImpliedFeatures>); 61 impl Features { 62 #[expect( 63 clippy::arithmetic_side_effects, 64 clippy::as_conversions, 65 clippy::cast_possible_truncation, 66 clippy::indexing_slicing, 67 clippy::unreachable, 68 reason = "comments in code explain their correctness" 69 )] 70 /// Returns all possible combinations of features. 71 fn powerset(self) -> Vec<String> { 72 // In the event `self.0.len() as u32` causes truncation, a `panic` will occur later due to lack of memory. 73 let mut init = Vec::with_capacity(2usize.pow(self.0.len() as u32)); 74 init.push(Vec::new()); 75 let mut power = self.0.keys().fold(init, |mut power, feature| { 76 let features = power.clone().into_iter().map(|mut features| { 77 features.push(feature.clone()); 78 features 79 }); 80 power.extend(features); 81 power 82 }); 83 power.retain(|features| { 84 features 85 .iter() 86 .enumerate() 87 .try_fold((), |(), (idx, feature)| { 88 // `idx < features.len()`, so overflow is not possible and indexing is fine. 89 features[idx + 1..].iter().try_fold((), |(), feat| { 90 if feature == feat 91 || self 92 .0 93 .get(feature) 94 .unwrap_or_else(|| { 95 unreachable!("there is a bug in Features::powerset") 96 }) 97 .contains(feat, &self) 98 || self 99 .0 100 .get(feat) 101 .unwrap_or_else(|| { 102 unreachable!("there is a bug in Features::powerset") 103 }) 104 .contains(feature, &self) 105 { 106 Err(()) 107 } else { 108 Ok(()) 109 } 110 }) 111 }) 112 .is_ok() 113 }); 114 let len = power.len(); 115 power 116 .into_iter() 117 .fold(Vec::with_capacity(len), |mut feats, features| { 118 let mut feat_combo = features.into_iter().fold(String::new(), |mut f, feature| { 119 f.push_str(feature.as_str()); 120 f.push(','); 121 f 122 }); 123 // Remove the trailing comma. 124 // Note a trailing comma exist iff `feat_combo` is not empty. When empty, this does nothing. 125 feat_combo.pop(); 126 feats.push(feat_combo); 127 feats 128 }) 129 } 130 } 131 impl<'de> Deserialize<'de> for Features { 132 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 133 where 134 D: Deserializer<'de>, 135 { 136 /// `Visitor` for `Features`. 137 struct FeaturesVisitor; 138 impl<'d> Visitor<'d> for FeaturesVisitor { 139 type Value = Features; 140 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { 141 formatter.write_str("Features") 142 } 143 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> 144 where 145 A: MapAccess<'d>, 146 { 147 /// Feature names. 148 enum Field { 149 /// `default` feature. 150 Default, 151 /// Feature with a different name. 152 Other(String), 153 } 154 impl<'d> Deserialize<'d> for Field { 155 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 156 where 157 D: Deserializer<'d>, 158 { 159 /// `Visitor` for `Field`. 160 struct FieldVisitor; 161 impl<'e> Visitor<'e> for FieldVisitor { 162 type Value = Field; 163 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { 164 formatter.write_str("unique feature names") 165 } 166 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> 167 where 168 E: Error, 169 { 170 Ok(match v { 171 "default" => Field::Default, 172 _ => Field::Other(v.to_owned()), 173 }) 174 } 175 } 176 deserializer.deserialize_identifier(FieldVisitor) 177 } 178 } 179 let mut dflt = false; 180 let mut features = HashMap::new(); 181 while let Some(key) = map.next_key()? { 182 match key { 183 Field::Default => { 184 if dflt { 185 return Err(Error::duplicate_field("default")); 186 } 187 dflt = map.next_value::<ImpliedFeatures>().map(|_| true)?; 188 } 189 Field::Other(val) => { 190 map.next_value().and_then(|implied| { 191 if features.insert(val, implied).is_none() { 192 Ok(()) 193 } else { 194 Err(Error::custom("duplicate features")) 195 } 196 })?; 197 } 198 } 199 } 200 Ok(Features(features)) 201 } 202 } 203 deserializer.deserialize_map(FeaturesVisitor) 204 } 205 } 206 /// `Cargo.toml`. 207 struct Manifest(Features); 208 impl<'de> Deserialize<'de> for Manifest { 209 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 210 where 211 D: Deserializer<'de>, 212 { 213 /// `Visitor` for `Manifest`. 214 struct ManifestVisitor; 215 impl<'d> Visitor<'d> for ManifestVisitor { 216 type Value = Manifest; 217 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { 218 formatter.write_str("Manifest") 219 } 220 fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error> 221 where 222 A: MapAccess<'d>, 223 { 224 /// `Cargo.toml` field. 225 enum Field { 226 /// `features`. 227 Features, 228 /// All other fields. 229 Other, 230 } 231 impl<'e> Deserialize<'e> for Field { 232 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> 233 where 234 D: Deserializer<'e>, 235 { 236 /// `Visitor` for `Field`. 237 struct FieldVisitor; 238 impl<'f> Visitor<'f> for FieldVisitor { 239 type Value = Field; 240 fn expecting(&self, formatter: &mut Formatter<'_>) -> fmt::Result { 241 write!(formatter, "'{FEATURES}'") 242 } 243 fn visit_str<E>(self, v: &str) -> Result<Self::Value, E> 244 where 245 E: Error, 246 { 247 Ok(match v { 248 FEATURES => Field::Features, 249 _ => Field::Other, 250 }) 251 } 252 } 253 deserializer.deserialize_identifier(FieldVisitor) 254 } 255 } 256 let mut features = None; 257 while let Some(key) = map.next_key()? { 258 match key { 259 Field::Features => { 260 if features.is_some() { 261 return Err(Error::duplicate_field(FEATURES)); 262 } 263 features = Some(map.next_value()?); 264 } 265 Field::Other => map.next_value::<IgnoredAny>().map(|_| ())?, 266 } 267 } 268 Ok(Manifest( 269 features.unwrap_or_else(|| Features(HashMap::new())), 270 )) 271 } 272 } 273 /// `features`. 274 const FEATURES: &str = "features"; 275 deserializer.deserialize_map(ManifestVisitor) 276 } 277 } 278 /// Returns possible combinations of features. 279 pub fn from_toml(val: &str) -> Result<Vec<String>, TomlErr> { 280 toml::from_str::<Manifest>(val).map(|man| man.0.powerset()) 281 }