use std::collections::{BTreeMap, BTreeSet};
use std::fmt::Write as FWrite;
use std::io::{Read, Write};
use std::default::Default;
use semver::VersionReq;
use std::path::Path;
use std::fs::File;
use toml;
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum ConfigOperation {
SetToolchain(String),
RemoveToolchain,
DefaultFeatures(bool),
AddFeature(String),
RemoveFeature(String),
SetDebugMode(bool),
SetTargetVersion(VersionReq),
RemoveTargetVersion,
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct PackageConfig {
pub toolchain: Option<String>,
pub default_features: bool,
pub features: BTreeSet<String>,
pub debug: Option<bool>,
pub target_version: Option<VersionReq>,
}
impl PackageConfig {
pub fn from<'o, O: IntoIterator<Item = &'o ConfigOperation>>(ops: O) -> PackageConfig {
let mut def = PackageConfig::default();
def.execute_operations(ops);
def
}
pub fn cargo_args(&self) -> Vec<String> {
let mut res = vec![];
if let Some(ref t) = self.toolchain {
res.push(format!("+{}", t));
}
res.push("install".to_string());
res.push("-f".to_string());
if !self.default_features {
res.push("--no-default-features".to_string());
}
if !self.features.is_empty() {
res.push("--features".to_string());
let mut a = String::new();
for f in &self.features {
write!(a, "{} ", f).unwrap();
}
res.push(a);
}
if let Some(true) = self.debug {
res.push("--debug".to_string());
}
res
}
pub fn execute_operations<'o, O: IntoIterator<Item = &'o ConfigOperation>>(&mut self, ops: O) {
for op in ops {
match *op {
ConfigOperation::SetToolchain(ref tchn) => self.toolchain = Some(tchn.clone()),
ConfigOperation::RemoveToolchain => self.toolchain = None,
ConfigOperation::DefaultFeatures(f) => self.default_features = f,
ConfigOperation::AddFeature(ref feat) => {
self.features.insert(feat.clone());
}
ConfigOperation::RemoveFeature(ref feat) => {
self.features.remove(feat);
}
ConfigOperation::SetDebugMode(d) => self.debug = Some(d),
ConfigOperation::SetTargetVersion(ref vr) => self.target_version = Some(vr.clone()),
ConfigOperation::RemoveTargetVersion => self.target_version = None,
}
}
}
pub fn read(p: &Path) -> Result<BTreeMap<String, PackageConfig>, i32> {
if p.exists() {
let mut buf = String::new();
try!(try!(File::open(p).map_err(|_| 1))
.read_to_string(&mut buf)
.map_err(|_| 1));
toml::from_str(&buf).map_err(|_| 2)
} else {
Ok(BTreeMap::new())
}
}
pub fn write(configuration: &BTreeMap<String, PackageConfig>, p: &Path) -> Result<(), i32> {
try!(File::create(p).map_err(|_| 3))
.write_all(&try!(toml::to_vec(configuration).map_err(|_| 2)))
.map_err(|_| 3)
}
}
impl Default for PackageConfig {
fn default() -> PackageConfig {
PackageConfig {
toolchain: None,
default_features: true,
features: BTreeSet::new(),
debug: None,
target_version: None,
}
}
}