use std::collections::HashMap;
use std::ops::Deref;
use std::str::FromStr;
use std::fmt::Debug;
use serde::de::Deserialize;
use error::*;
use source::Source;
use value::{Value, ValueWithKey};
use path;
#[derive(Clone, Debug)]
enum ConfigKind {
Mutable {
defaults: HashMap<path::Expression, Value>,
overrides: HashMap<path::Expression, Value>,
sources: Vec<Box<Source + Send + Sync>>,
},
Frozen,
}
impl Default for ConfigKind {
fn default() -> Self {
ConfigKind::Mutable {
defaults: HashMap::new(),
overrides: HashMap::new(),
sources: Vec::new(),
}
}
}
#[derive(Default, Clone, Debug)]
pub struct Config {
kind: ConfigKind,
pub cache: Value,
}
impl Config {
pub fn new() -> Self {
Config::default()
}
pub fn merge<T>(&mut self, source: T) -> ConfigResult
where T: 'static,
T: Source + Send + Sync
{
match self.kind {
ConfigKind::Mutable { ref mut sources, .. } => {
sources.push(Box::new(source));
}
ConfigKind::Frozen => {
return ConfigResult(Err(ConfigError::Frozen));
}
}
self.refresh()
}
pub fn refresh(&mut self) -> ConfigResult {
self.cache = match self.kind {
ConfigKind::Mutable {
ref overrides,
ref sources,
ref defaults,
} => {
let mut cache: Value = HashMap::<String, Value>::new().into();
for (key, val) in defaults {
key.set(&mut cache, val.clone());
}
if let Err(error) = sources.collect_to(&mut cache) {
return ConfigResult(Err(error));
}
for (key, val) in overrides {
key.set(&mut cache, val.clone());
}
cache
}
ConfigKind::Frozen => {
return ConfigResult(Err(ConfigError::Frozen));
}
};
ConfigResult(Ok(self))
}
pub fn deserialize<'de, T: Deserialize<'de>>(&self) -> Result<T> {
T::deserialize(self.cache.clone())
}
pub fn set_default<T>(&mut self, key: &str, value: T) -> ConfigResult
where T: Into<Value>
{
match self.kind {
ConfigKind::Mutable { ref mut defaults, .. } => {
defaults.insert(match key.to_lowercase().parse() {
Ok(expr) => expr,
Err(error) => {
return ConfigResult(Err(error));
}
},
value.into());
}
ConfigKind::Frozen => return ConfigResult(Err(ConfigError::Frozen)),
};
self.refresh()
}
pub fn set<T>(&mut self, key: &str, value: T) -> ConfigResult
where T: Into<Value>
{
match self.kind {
ConfigKind::Mutable { ref mut overrides, .. } => {
overrides.insert(match key.to_lowercase().parse() {
Ok(expr) => expr,
Err(error) => {
return ConfigResult(Err(error));
}
},
value.into());
}
ConfigKind::Frozen => return ConfigResult(Err(ConfigError::Frozen)),
};
self.refresh()
}
pub fn get<'de, T: Deserialize<'de>>(&self, key: &'de str) -> Result<T> {
let expr: path::Expression = key.to_lowercase().parse()?;
let value = expr.get(&self.cache).cloned();
match value {
Some(value) => {
T::deserialize(ValueWithKey::new(value, key))
}
None => Err(ConfigError::NotFound(key.into())),
}
}
pub fn get_str(&self, key: &str) -> Result<String> {
self.get(key).and_then(Value::into_str)
}
pub fn get_int(&self, key: &str) -> Result<i64> {
self.get(key).and_then(Value::into_int)
}
pub fn get_float(&self, key: &str) -> Result<f64> {
self.get(key).and_then(Value::into_float)
}
pub fn get_bool(&self, key: &str) -> Result<bool> {
self.get(key).and_then(Value::into_bool)
}
pub fn get_table(&self, key: &str) -> Result<HashMap<String, Value>> {
self.get(key).and_then(Value::into_table)
}
pub fn get_array(&self, key: &str) -> Result<Vec<Value>> {
self.get(key).and_then(Value::into_array)
}
}
pub struct ConfigResult<'a>(Result<&'a mut Config>);
#[inline]
fn unwrap_failed<E: Debug>(msg: &str, error: E) -> ! {
panic!("{}: {:?}", msg, error)
}
impl<'a> ConfigResult<'a> {
pub fn merge<T>(self, source: T) -> ConfigResult<'a>
where T: 'static,
T: Source + Send + Sync
{
match self.0 {
Ok(instance) => instance.merge(source),
error => ConfigResult(error),
}
}
pub fn set_default<T>(self, key: &str, value: T) -> ConfigResult<'a>
where T: Into<Value>,
T: 'static
{
match self.0 {
Ok(instance) => instance.set_default(key, value),
error => ConfigResult(error),
}
}
pub fn set<T>(self, key: &str, value: T) -> ConfigResult<'a>
where T: Into<Value>,
T: 'static
{
match self.0 {
Ok(instance) => instance.set(key, value),
error => ConfigResult(error),
}
}
#[inline]
pub fn is_ok(&self) -> bool {
match self.0 {
Ok(_) => true,
Err(_) => false,
}
}
#[inline]
pub fn is_err(&self) -> bool {
!self.is_ok()
}
#[inline]
pub fn ok(self) -> Option<Config> {
match self.0 {
Ok(x) => Some(x.clone()),
Err(_) => None,
}
}
#[inline]
pub fn err(self) -> Option<ConfigError> {
match self.0 {
Ok(_) => None,
Err(x) => Some(x),
}
}
#[inline]
pub fn unwrap(self) -> Config {
match self.0 {
Ok(instance) => instance.clone(),
Err(error) => unwrap_failed("called `Result::unwrap()` on an `Err` value", error),
}
}
#[inline]
pub fn expect(self, msg: &str) -> Config {
match self.0 {
Ok(instance) => instance.clone(),
Err(error) => unwrap_failed(msg, error),
}
}
#[inline]
pub fn unwrap_err(self) -> ConfigError {
match self.0 {
Ok(t) => unwrap_failed("called `Result::unwrap_err()` on an `Ok` value", t),
Err(e) => e,
}
}
#[inline]
pub fn expect_err(self, msg: &str) -> ConfigError {
match self.0 {
Ok(t) => unwrap_failed(msg, t),
Err(e) => e,
}
}
}