summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Cargo.toml24
-rw-r--r--lib/src/config.rs100
-rw-r--r--lib/src/de.rs107
-rw-r--r--lib/src/error.rs155
-rw-r--r--lib/src/file/format/mod.rs60
-rw-r--r--lib/src/file/format/toml.rs64
-rw-r--r--lib/src/file/mod.rs75
-rw-r--r--lib/src/file/source/file.rs129
-rw-r--r--lib/src/file/source/mod.rs12
-rw-r--r--lib/src/file/source/string.rs21
-rw-r--r--lib/src/lib.rs25
-rw-r--r--lib/src/path/mod.rs43
-rw-r--r--lib/src/path/parser.rs120
-rw-r--r--lib/src/source.rs9
-rw-r--r--lib/src/value.rs249
15 files changed, 0 insertions, 1193 deletions
diff --git a/lib/Cargo.toml b/lib/Cargo.toml
deleted file mode 100644
index 6b04a8e..0000000
--- a/lib/Cargo.toml
+++ /dev/null
@@ -1,24 +0,0 @@
-[package]
-name = "config"
-version = "0.5.0-pre"
-description = "Layered configuration system for Rust applications."
-homepage = "https://github.com/mehcode/config-rs"
-repository = "https://github.com/mehcode/config-rs"
-readme = "README.md"
-keywords = ["config", "configuration", "settings", "env", "environment"]
-authors = ["Ryan Leckey <leckey.ryan@gmail.com>"]
-license = "MIT/Apache-2.0"
-workspace = "../"
-
-[features]
-default = ["toml", "json", "yaml"]
-json = ["serde_json"]
-yaml = ["yaml-rust"]
-
-[dependencies]
-serde = "^0.9"
-nom = "^2.1"
-
-toml = { version = "^0.3", optional = true }
-serde_json = { version = "^0.9", optional = true }
-yaml-rust = { version = "^0.3.5", optional = true }
diff --git a/lib/src/config.rs b/lib/src/config.rs
deleted file mode 100644
index 93d7fc0..0000000
--- a/lib/src/config.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-use std::collections::HashMap;
-use serde::de::Deserialize;
-
-use error::*;
-use source::Source;
-use value::Value;
-use path;
-
-enum ConfigKind {
- // A mutable configuration. This is the default.
- Mutable {
- defaults: HashMap<String, Value>,
- overrides: HashMap<String, Value>,
- sources: Vec<Box<Source + Send + Sync>>,
- },
-
- // A frozen configuration.
- // Configuration can no longer be mutated.
- Frozen,
-}
-
-impl Default for ConfigKind {
- fn default() -> Self {
- ConfigKind::Mutable {
- defaults: HashMap::new(),
- overrides: HashMap::new(),
- sources: Vec::new(),
- }
- }
-}
-
-/// A prioritized configuration repository. It maintains a set of
-/// configuration sources, fetches values to populate those, and provides
-/// them according to the source's priority.
-#[derive(Default)]
-pub struct Config {
- kind: ConfigKind,
-
- /// Root of the cached configuration.
- pub cache: Value,
-}
-
-impl Config {
- /// Merge in a configuration property source.
- pub fn merge<T>(&mut self, source: T) -> Result<()>
- where T: 'static,
- T: Source + Send + Sync
- {
- match self.kind {
- ConfigKind::Mutable { ref mut sources, .. } => {
- sources.push(Box::new(source));
- }
-
- ConfigKind::Frozen => {
- return Err(ConfigError::Frozen);
- }
- }
-
- self.refresh()
- }
-
- /// Refresh the configuration cache with fresh
- /// data from added sources.
- ///
- /// Configuration is automatically refreshed after a mutation
- /// operation (`set`, `merge`, `set_default`, etc.).
- pub fn refresh(&mut self) -> Result<()> {
- self.cache = match self.kind {
- // TODO: We need to actually merge in all the stuff
- ConfigKind::Mutable {
- ref overrides,
- ref sources,
- ref defaults,
- } => sources[0].collect()?,
-
- ConfigKind::Frozen => {
- return Err(ConfigError::Frozen);
- }
- };
-
- Ok(())
- }
-
- pub fn get<T: Deserialize>(&self, key: &str) -> Result<T> {
- // Parse the key into a path expression
- let expr: path::Expression = key.to_lowercase().parse()?;
-
- // Traverse the cache using the path to (possibly) retrieve a value
- let value = expr.get(&self.cache).cloned();
-
- match value {
- Some(value) => {
- // Deserialize the received value into the requested type
- T::deserialize(value)
- }
-
- None => Err(ConfigError::NotFound(key.into())),
- }
- }
-}
diff --git a/lib/src/de.rs b/lib/src/de.rs
deleted file mode 100644
index 89a3bcf..0000000
--- a/lib/src/de.rs
+++ /dev/null
@@ -1,107 +0,0 @@
-use serde::de;
-use value::{Value, ValueKind};
-use error::*;
-use std::borrow::Cow;
-use std::iter::Peekable;
-use std::collections::HashMap;
-use std::collections::hash_map::Drain;
-
-impl de::Deserializer for Value {
- type Error = ConfigError;
-
- #[inline]
- fn deserialize<V>(self, visitor: V) -> Result<V::Value>
- where V: de::Visitor
- {
- // Deserialize based on the underlying type
- match self.kind {
- ValueKind::Integer(i) => visitor.visit_i64(i),
- ValueKind::Boolean(b) => visitor.visit_bool(b),
- ValueKind::Float(f) => visitor.visit_f64(f),
- ValueKind::String(s) => visitor.visit_string(s),
- ValueKind::Array(values) => unimplemented!(),
- ValueKind::Table(map) => visitor.visit_map(MapVisitor::new(map)),
- _ => {
- unimplemented!();
- }
- }
- }
-
- #[inline]
- fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
- where V: de::Visitor
- {
- // Match an explicit nil as None and everything else as Some
- match self.kind {
- ValueKind::Nil => visitor.visit_none(),
- _ => visitor.visit_some(self),
- }
- }
-
- forward_to_deserialize! {
- bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
- seq_fixed_size bytes byte_buf map struct unit enum newtype_struct
- struct_field ignored_any unit_struct tuple_struct tuple
- }
-}
-
-struct StrDeserializer<'a>(&'a str);
-
-impl<'a> StrDeserializer<'a> {
- fn new(key: &'a str) -> Self {
- StrDeserializer(key)
- }
-}
-
-impl<'a> de::Deserializer for StrDeserializer<'a> {
- type Error = ConfigError;
-
- #[inline]
- fn deserialize<V: de::Visitor>(self, visitor: V) -> Result<V::Value> {
- visitor.visit_str(self.0)
- }
-
- forward_to_deserialize! {
- bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
- seq_fixed_size bytes byte_buf map struct unit enum newtype_struct
- struct_field ignored_any unit_struct tuple_struct tuple option
- }
-}
-
-struct MapVisitor {
- elements: Vec<(String, Value)>,
- index: usize,
-}
-
-impl MapVisitor {
- fn new(mut table: HashMap<String, Value>) -> Self {
- MapVisitor {
- elements: table.drain().collect(),
- index: 0,
- }
- }
-}
-
-impl de::MapVisitor for MapVisitor {
- type Error = ConfigError;
-
- fn visit_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
- where K: de::DeserializeSeed
- {
- if self.index >= self.elements.len() {
- return Ok(None);
- }
-
- let key_s = &self.elements[0].0;
- let key_de = StrDeserializer(key_s);
- let key = de::DeserializeSeed::deserialize(seed, key_de)?;
-
- Ok(Some(key))
- }
-
- fn visit_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
- where V: de::DeserializeSeed
- {
- de::DeserializeSeed::deserialize(seed, self.elements.remove(0).1)
- }
-}
diff --git a/lib/src/error.rs b/lib/src/error.rs
deleted file mode 100644
index b97ebac..0000000
--- a/lib/src/error.rs
+++ /dev/null
@@ -1,155 +0,0 @@
-use std::error::Error;
-use std::borrow::Cow;
-use std::result;
-use std::fmt;
-use serde::de;
-use nom;
-
-#[derive(Debug)]
-pub enum Unexpected {
- Bool(bool),
- Integer(i64),
- Float(f64),
- Str(String),
- Unit,
- Seq,
- Map
-}
-
-impl fmt::Display for Unexpected {
- fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
- match *self {
- Unexpected::Bool(b) => write!(f, "boolean `{}`", b),
- Unexpected::Integer(i) => write!(f, "integer `{}`", i),
- Unexpected::Float(v) => write!(f, "floating point `{}`", v),
- Unexpected::Str(ref s) => write!(f, "string {:?}", s),
- Unexpected::Unit => write!(f, "unit value"),
- Unexpected::Seq => write!(f, "sequence"),
- Unexpected::Map => write!(f, "map"),
- }
- }
-}
-
-/// Represents all possible errors that can occur when working with
-/// configuration.
-pub enum ConfigError {
- /// Configuration is frozen and no further mutations can be made.
- Frozen,
-
- /// Configuration property was not found
- NotFound(String),
-
- /// Configuration path could not be parsed.
- PathParse(nom::ErrorKind),
-
- /// Configuration could not be parsed from file.
- FileParse { uri: Option<String>, cause: Box<Error> },
-
- /// Value could not be converted into the requested type.
- Type {
- origin: Option<String>,
- unexpected: Unexpected,
- expected: &'static str,
- },
-
- /// Custom message
- Message(String),
-
- /// Unadorned error from a foreign source.
- Foreign(Box<Error>),
-}
-
-impl ConfigError {
- // FIXME: pub(crate)
- #[doc(hidden)]
- pub fn invalid_type(origin: Option<String>, unexpected: Unexpected, expected: &'static str) -> Self {
- ConfigError::Type {
- origin: origin,
- unexpected: unexpected,
- expected: expected
- }
- }
-}
-
-/// Alias for a `Result` with the error type set to `ConfigError`.
-pub type Result<T> = result::Result<T, ConfigError>;
-
-// Forward Debug to Display for readable panic! messages
-impl fmt::Debug for ConfigError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- write!(f, "{}", *self)
- }
-}
-
-impl fmt::Display for ConfigError {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- ConfigError::Frozen | ConfigError::PathParse(_) => {
- write!(f, "{}", self.description())
- }
-
- ConfigError::Message(ref s) => {
- write!(f, "{}", s)
- }
-
- ConfigError::Foreign(ref cause) => {
- write!(f, "{}", cause)
- }
-
- ConfigError::NotFound(ref key) => {
- write!(f, "configuration property {:?} not found", key)
- }
-
- ConfigError::Type { ref origin, ref unexpected, expected } => {
- write!(f, "invalid type: {}, expected {}",
- unexpected, expected)?;
-
- if let Some(ref origin) = *origin {
- write!(f, " in {}", origin)?;
- }
-
- Ok(())
- }
-
- ConfigError::FileParse { ref cause, ref uri } => {
- write!(f, "{}", cause)?;
-
- if let Some(ref uri) = *uri {
- write!(f, " in {}", uri)?;
- }
-
- Ok(())
- }
- }
- }
-}
-
-impl Error for ConfigError {
- fn description(&self) -> &str {
- match *self {
- ConfigError::Frozen => "configuration is frozen",
- ConfigError::NotFound(_) => "configuration property not found",
- ConfigError::Type { .. } => "invalid type",
- ConfigError::Foreign(ref cause) => cause.description(),
- ConfigError::FileParse { ref cause, .. } => cause.description(),
- ConfigError::PathParse(ref kind) => kind.description(),
-
- _ => "configuration error",
- }
- }
-
- fn cause(&self) -> Option<&Error> {
- match *self {
- ConfigError::Foreign(ref cause) => Some(cause.as_ref()),
- ConfigError::FileParse { ref cause, .. } => Some(cause.as_ref()),
-
- _ => None
- }
- }
-}
-
-impl de::Error for ConfigError {
- fn custom<T: fmt::Display>(msg: T) -> Self {
- ConfigError::Message(msg.to_string())
- }
-}
diff --git a/lib/src/file/format/mod.rs b/lib/src/file/format/mod.rs
deleted file mode 100644
index 5c97a7f..0000000
--- a/lib/src/file/format/mod.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-use source::Source;
-use value::Value;
-use std::error::Error;
-
-#[cfg(feature = "toml")]
-mod toml;
-
-// #[cfg(feature = "json")]
-// mod json;
-
-// #[cfg(feature = "yaml")]
-// mod yaml;
-
-#[derive(Debug, Clone, Copy)]
-pub enum FileFormat {
- /// TOML (parsed with toml)
- #[cfg(feature = "toml")]
- Toml,
-
- // /// JSON (parsed with serde_json)
- // #[cfg(feature = "json")]
- // Json,
-
- // /// YAML (parsed with yaml_rust)
- // #[cfg(feature = "yaml")]
- // Yaml,
-}
-
-impl FileFormat {
- // TODO: pub(crate)
- #[doc(hidden)]
- pub fn extensions(&self) -> Vec<&'static str> {
- match *self {
- #[cfg(feature = "toml")]
- FileFormat::Toml => vec!["toml"],
-
- // #[cfg(feature = "json")]
- // FileFormat::Json => vec!["json"],
-
- // #[cfg(feature = "yaml")]
- // FileFormat::Yaml => vec!["yaml", "yml"],
- }
- }
-
- // TODO: pub(crate)
- #[doc(hidden)]
- #[allow(unused_variables)]
- pub fn parse(&self, uri: Option<&String>, text: &str, namespace: Option<&String>) -> Result<Value, Box<Error>> {
- match *self {
- #[cfg(feature = "toml")]
- FileFormat::Toml => toml::parse(uri, text, namespace),
-
- // #[cfg(feature = "json")]
- // FileFormat::Json => json::Content::parse(text, namespace),
-
- // #[cfg(feature = "yaml")]
- // FileFormat::Yaml => yaml::Content::parse(text, namespace),
- }
- }
-}
diff --git a/lib/src/file/format/toml.rs b/lib/src/file/format/toml.rs
deleted file mode 100644
index bbe6aa6..0000000
--- a/lib/src/file/format/toml.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-use toml;
-use source::Source;
-use std::collections::{HashMap, BTreeMap};
-use std::error::Error;
-use value::Value;
-
-pub fn parse(uri: Option<&String>, text: &str, namespace: Option<&String>) -> Result<Value, Box<Error>> {
- // Parse a TOML value from the provided text
- let mut root: toml::Value = toml::from_str(text)?;
-
- // Limit to namespace
- if let Some(namespace) = namespace {
- root = toml::Value::Table(match root {
- toml::Value::Table(ref mut table) => {
- if let Some(toml::Value::Table(table)) = table.remove(namespace) {
- table
- } else {
- BTreeMap::new()
- }
- }
-
- _ => {
- BTreeMap::new()
- }
- });
- }
-
- Ok(from_toml_value(uri, &root))
-}
-
-// TODO: Extend value origin with line/column numbers when able
-fn from_toml_value(uri: Option<&String>, value: &toml::Value) -> Value {
- match *value {
- toml::Value::String(ref value) => Value::new(uri, value.to_string()),
- toml::Value::Float(value) => Value::new(uri, value),
- toml::Value::Integer(value) => Value::new(uri, value),
- toml::Value::Boolean(value) => Value::new(uri, value),
-
- toml::Value::Table(ref table) => {
- let mut m = HashMap::new();
-
- for (key, value) in table {
- m.insert(key.clone(), from_toml_value(uri, value));
- }
-
- Value::new(uri, m)
- }
-
- toml::Value::Array(ref array) => {
- let mut l = Vec::new();
-
- for value in array {
- l.push(from_toml_value(uri, value));
- }
-
- Value::new(uri, l)
- }
-
- _ => {
- // TODO: DateTime
- unimplemented!();
- }
- }
-}
diff --git a/lib/src/file/mod.rs b/lib/src/file/mod.rs
deleted file mode 100644
index 7534ddb..0000000
--- a/lib/src/file/mod.rs
+++ /dev/null
@@ -1,75 +0,0 @@
-mod format;
-pub mod source;
-
-use source::Source;
-use error::*;
-use value::Value;
-
-use self::source::FileSource;
-pub use self::format::FileFormat;
-
-pub struct File<T>
- where T: FileSource
-{
- source: T,
-
- /// Namespace to restrict configuration from the file
- namespace: Option<String>,
-
- /// Format of file (which dictates what driver to use).
- format: Option<FileFormat>,
-
- /// A required File will error if it cannot be found
- required: bool,
-}
-
-impl File<source::string::FileSourceString> {
- pub fn from_str(s: &str, format: FileFormat) -> Self {
- File {
- format: Some(format),
- required: true,
- namespace: None,
- source: s.into(),
- }
- }
-}
-
-impl File<source::file::FileSourceFile> {
- pub fn new(name: &str, format: FileFormat) -> Self {
- File {
- format: Some(format),
- required: true,
- namespace: None,
- source: source::file::FileSourceFile::new(name),
- }
- }
-}
-
-impl<T: FileSource> File<T> {
- pub fn required(&mut self, required: bool) -> &mut Self {
- self.required = required;
- self
- }
-
- pub fn namespace(&mut self, namespace: &str) -> &mut Self {
- self.namespace = Some(namespace.into());
- self
- }
-}
-
-impl<T: FileSource> Source for File<T> {
- fn collect(&self) -> Result<Value> {
- // Coerce the file contents to a string
- let (uri, contents) = self.source.resolve(self.format).map_err(|err| {
- ConfigError::Foreign(err)
- })?;
-
- // Parse the string using the given format
- self.format.unwrap().parse(uri.as_ref(), &contents, self.namespace.as_ref()).map_err(|cause| {
- ConfigError::FileParse {
- uri: uri,
- cause: cause
- }
- })
- }
-}
diff --git a/lib/src/file/source/file.rs b/lib/src/file/source/file.rs
deleted file mode 100644
index 124b7dd..0000000
--- a/lib/src/file/source/file.rs
+++ /dev/null
@@ -1,129 +0,0 @@
-use std::str::FromStr;
-use std::result;
-use std::error::Error;
-
-use std::path::{PathBuf, Path};
-use std::io::{self, Read};
-use std::fs;
-use std::env;
-
-use source::Source;
-use super::{FileFormat, FileSource};
-
-/// Describes a file sourced from a file
-pub struct FileSourceFile {
- /// Basename of configuration file
- name: String,
-
- /// Directory where configuration file is found
- /// When not specified, the current working directory (CWD) is considered
- path: Option<String>,
-}
-
-impl FileSourceFile {
- pub fn new(name: &str) -> FileSourceFile {
- FileSourceFile {
- name: name.into(),
- path: None,
- }
- }
-
- fn find_file(&self, format_hint: Option<FileFormat>) -> Result<PathBuf, Box<Error>> {
- // Build expected configuration file
- let mut basename = PathBuf::new();
- let extensions = format_hint.unwrap().extensions();
-
- if let Some(ref path) = self.path {
- basename.push(path.clone());
- }
-
- basename.push(self.name.clone());
-
- // Find configuration file (algorithm similar to .git detection by git)
- let mut dir = env::current_dir()?;
- let mut filename = dir.as_path().join(basename.clone());
-
- loop {
- for ext in &extensions {
- filename.set_extension(ext);
-
- if filename.is_file() {
- // File exists and is a file
- return Ok(filename);
- }
- }
-
- // Not found.. travse up via the dir
- if !dir.pop() {
- // Failed to find the configuration file
- return Err(Box::new(io::Error::new(io::ErrorKind::NotFound,
- format!("configuration file \"{}\" not found",
- basename.to_string_lossy()))
- ));
- }
- }
- }
-}
-
-impl FileSource for FileSourceFile {
- fn resolve(&self, format_hint: Option<FileFormat>) -> Result<(Option<String>, String), Box<Error>> {
- // Find file
- let filename = self.find_file(format_hint)?;
-
- // Attempt to use a relative path for the URI
- let base = env::current_dir()?;
- let uri = match path_relative_from(&filename, &base) {
- Some(value) => value,
- None => filename.clone(),
- };
-
- // Read contents from file
- let mut file = fs::File::open(filename.clone())?;
- let mut text = String::new();
- file.read_to_string(&mut text)?;
-
- Ok((Some(uri.to_string_lossy().into_owned()), text))
- }
-}
-
-// TODO: This should probably be a crate
-// https://github.com/rust-lang/rust/blob/master/src/librustc_trans/back/rpath.rs#L128
-fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
- use std::path::Component;
-
- if path.is_absolute() != base.is_absolute() {
- if path.is_absolute() {
- Some(PathBuf::from(path))
- } else {
- None
- }
- } else {
- let mut ita = path.components();
- let mut itb = base.components();
- let mut comps: Vec<Component> = vec![];
- loop {
- match (ita.next(), itb.next()) {
- (None, None) => break,
- (Some(a), None) => {
- comps.push(a);
- comps.extend(ita.by_ref());
- break;
- }
- (None, _) => comps.push(Component::ParentDir),
- (Some(a), Some(b)) if comps.is_empty() && a == b => (),
- (Some(a), Some(b)) if b == Component::CurDir => comps.push(a),
- (Some(_), Some(b)) if b == Component::ParentDir => return None,
- (Some(a), Some(_)) => {
- comps.push(Component::ParentDir);
- for _ in itb {
- comps.push(Component::ParentDir);
- }
- comps.push(a);
- comps.extend(ita.by_ref());
- break;
- }
- }
- }
- Some(comps.iter().map(|c| c.as_os_str()).collect())
- }
-}
diff --git a/lib/src/file/source/mod.rs b/lib/src/file/source/mod.rs
deleted file mode 100644
index 4aeafa5..0000000
--- a/lib/src/file/source/mod.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-pub mod file;
-pub mod string;
-
-use std::error::Error;
-
-use source::Source;
-use super::FileFormat;
-
-/// Describes where the file is sourced
-pub trait FileSource {
- fn resolve(&self, format_hint: Option<FileFormat>) -> Result<(Option<String>, String), Box<Error>>;
-}
diff --git a/lib/src/file/source/string.rs b/lib/src/file/source/string.rs
deleted file mode 100644
index e1d9f64..0000000
--- a/lib/src/file/source/string.rs
+++ /dev/null
@@ -1,21 +0,0 @@
-use std::str::FromStr;
-use std::result;
-use std::error::Error;
-
-use source::Source;
-use super::{FileSource, FileFormat};
-
-/// Describes a file sourced from a string
-pub struct FileSourceString(String);
-
-impl<'a> From<&'a str> for FileSourceString {
- fn from(s: &'a str) -> Self {
- FileSourceString(s.into())
- }
-}
-
-impl FileSource for FileSourceString {
- fn resolve(&self, _: Option<FileFormat>) -> Result<(Option<String>, String), Box<Error>> {
- Ok((None, self.0.clone()))
- }
-}
diff --git a/lib/src/lib.rs b/lib/src/lib.rs
deleted file mode 100644
index 212e621..0000000
--- a/lib/src/lib.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![allow(dead_code)]
-#![allow(unused_imports)]
-#![allow(unused_variables)]
-
-#[macro_use]
-extern crate serde;
-
-extern crate nom;
-
-#[cfg(feature = "toml")]
-extern crate toml;
-
-mod error;
-mod value;
-mod de;
-mod path;
-mod source;
-mod config;
-mod file;
-
-pub use config::Config;
-pub use error::ConfigError;
-pub use value::Value;
-pub use source::Source;
-pub use file::{File, FileFormat};
diff --git a/lib/src/path/mod.rs b/lib/src/path/mod.rs
deleted file mode 100644
index 46e2290..0000000
--- a/lib/src/path/mod.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-use std::str::FromStr;
-use nom::ErrorKind;
-use error::*;
-use value::{Value, ValueKind};
-
-mod parser;
-
-#[derive(Debug, Eq, PartialEq, Clone, Hash)]
-pub enum Expression {
- Identifier(String),
- Child(Box<Expression>, String),
- Subscript(Box<Expression>, i32),
-}
-
-impl FromStr for Expression {
- type Err = ConfigError;
-
- fn from_str(s: &str) -> Result<Expression> {
- parser::from_str(s.as_bytes()).to_result().map_err(|kind| {
- ConfigError::PathParse(kind)
- })
- }
-}
-
-impl Expression {
- pub fn get<'a>(self, root: &'a Value) -> Option<&'a Value> {
- match self {
- Expression::Identifier(id) => {
- match root.kind {
- // `x` access on a table is equivalent to: map[x]
- ValueKind::Table(ref map) => map.get(&id),
-
- // all other variants return None
- _ => None,
- }
- }
-
- _ => {
- unimplemented!();
- }
- }
- }
-}
diff --git a/lib/src/path/parser.rs b/lib/src/path/parser.rs
deleted file mode 100644
index ad7ab91..0000000
--- a/lib/src/path/parser.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-use nom::*;
-use std::str::{FromStr, from_utf8};
-use super::Expression;
-
-named!(ident_<String>,
- map!(
- map_res!(is_a!(
- "abcdefghijklmnopqrstuvwxyz \
- ABCDEFGHIJKLMNOPQRSTUVWXYZ \
- 0123456789 \
- _-"
- ), from_utf8),
- |s: &str| {
- s.to_string()
- }
- )
-);
-
-named!(integer <i32>,
- map_res!(
- map_res!(
- ws!(digit),
- from_utf8
- ),
- FromStr::from_str
- )
-);
-
-named!(ident<Expression>, map!(ident_, Expression::Identifier));
-
-fn postfix(expr: Expression) -> Box<Fn(&[u8]) -> IResult<&[u8], Expression>> {
- return Box::new(move |i: &[u8]| {
- alt!(i,
- do_parse!(
- tag!(".") >>
- id: ident_ >>
- (Expression::Child(Box::new(expr.clone()), id))
- ) |
- delimited!(
- char!('['),
- do_parse!(
- negative: opt!(tag!("-")) >>
- num: integer >>
- (Expression::Subscript(
- Box::new(expr.clone()),
- num * (if negative.is_none() { 1 } else { -1 })
- ))
- ),
- char!(']')
- )
- )
- });
-}
-
-pub fn from_str(input: &[u8]) -> IResult<&[u8], Expression> {
- match ident(input) {
- IResult::Done(mut rem, mut expr) => {
- while rem.len() > 0 {
- match postfix(expr)(rem) {
- IResult::Done(rem_, expr_) => {
- rem = rem_;
- expr = expr_;
- }
-
- // Forward Incomplete and Error
- result @ _ => {
- return result;
- }
- }
- }
-
- IResult::Done(&[], expr)
- }
-
- // Forward Incomplete and Error
- result @ _ => result,
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use super::Expression::*;
-
- #[test]
- fn test_id() {
- let parsed: Expression = from_str("abcd").unwrap();
- assert_eq!(parsed, Identifier("abcd".into()));
- }
-
- #[test]
- fn test_id_dash() {
- let parsed: Expression = from_str("abcd-efgh").unwrap();
- assert_eq!(parsed, Identifier("abcd-efgh".into()));
- }
-
- #[test]
- fn test_child() {
- let parsed: Expression = from_str("abcd.efgh").unwrap();
- let expected = Child(Box::new(Identifier("abcd".into())), "efgh".into());
-
- assert_eq!(parsed, expected);
- }
-
- #[test]
- fn test_subscript() {
- let parsed: Expression = from_str("abcd[12]").unwrap();
- let expected = Subscript(Box::new(Identifier("abcd".into())), 12);
-
- assert_eq!(parsed, expected);
- }
-
- #[test]
- fn test_subscript_neg() {
- let parsed: Expression = from_str("abcd[-1]").unwrap();
- let expected = Subscript(Box::new(Identifier("abcd".into())), -1);
-
- assert_eq!(parsed, expected);
- }
-}
diff --git a/lib/src/source.rs b/lib/src/source.rs
deleted file mode 100644
index 7519438..0000000
--- a/lib/src/source.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-use error::*;
-use value::Value;
-
-/// Describes a generic _source_ of configuration properties.
-pub trait Source {
- /// Collect all configuration properties available from this source and return
- /// a top-level Value (which we expected to be a Table).
- fn collect(&self) -> Result<Value>;
-}
diff --git a/lib/src/value.rs b/lib/src/value.rs
deleted file mode 100644
index 5b0014a..0000000
--- a/lib/src/value.rs
+++ /dev/null
@@ -1,249 +0,0 @@
-use std::collections::HashMap;
-use std::fmt::Display;
-use error::*;
-
-/// Underlying kind of the configuration value.
-#[derive(Debug, Clone)]
-pub enum ValueKind {
- Nil,
- Boolean(bool),
- Integer(i64),
- Float(f64),
- String(String),
- Table(Table),
- Array(Array),
-}
-
-pub type Array = Vec<Value>;
-pub type Table = HashMap<String, Value>;
-
-impl Default for ValueKind {
- fn default() -> Self {
- ValueKind::Nil
- }
-}
-
-impl<T> From<Option<T>> for ValueKind