use cargo_metadata::{camino::Utf8Path, Package};
pub trait PackageExt {
fn each_feature(&'_ self) -> EachFeature<'_>;
fn root_directory(&self) -> &Utf8Path;
}
impl PackageExt for Package {
fn each_feature(&'_ self) -> EachFeature<'_> {
let mut features = self.features.keys().collect::<Vec<_>>();
features.sort();
EachFeature {
all_features: true,
no_default_features: true,
features: features.into_iter(),
}
}
fn root_directory(&self) -> &Utf8Path {
self.manifest_path.parent().unwrap()
}
}
#[derive(Debug)]
pub struct EachFeature<'a> {
all_features: bool,
features: std::vec::IntoIter<&'a String>,
no_default_features: bool,
}
impl<'a> Iterator for EachFeature<'a> {
type Item = FeatureOption<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.all_features {
self.all_features = false;
return Some(FeatureOption::AllFeatures);
}
if self.no_default_features {
self.no_default_features = false;
return Some(FeatureOption::NoDefaultFeatures);
}
if let Some(feature) = self.features.next() {
return Some(FeatureOption::Features(vec![feature]));
}
None
}
}
#[derive(Debug, Clone)]
pub enum FeatureOption<'a> {
AllFeatures,
NoDefaultFeatures,
Features(Vec<&'a str>),
}
impl<'a> FeatureOption<'a> {
pub fn to_args(&self) -> Vec<&'a str> {
match self {
Self::AllFeatures => vec!["--all-features"],
Self::NoDefaultFeatures => vec!["--no-default-features"],
Self::Features(features) => {
let mut args = Vec::with_capacity(features.len() * 2 + 1);
for feature in features {
args.extend(["--features", feature]);
}
args.push("--no-default-features");
args
}
}
}
}