use std::fs::File;
use std::io::{self, Read};
use std::result;
use rustc_serialize::hex::FromHex;
use toml;
#[derive(Debug)]
pub struct Configuration {
root: toml::Value,
}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug)]
pub enum Error {
IOError(io::Error),
TOMLParserError(Vec<toml::ParserError>),
}
impl Configuration {
pub fn read_file(path: &str) -> Result<Configuration> {
let mut configuration_file = try!(File::open(path));
let mut configuration = String::new();
try!(configuration_file.read_to_string(&mut configuration));
let mut parser = toml::Parser::new(&configuration);
let value = match parser.parse() {
Some(value) => toml::Value::Table(value),
None => {
return Err(Error::TOMLParserError(parser.errors));
}
};
Ok(Self::new(value))
}
fn new(root: toml::Value) -> Configuration {
Configuration { root: root }
}
pub fn i64_at(&self, path: &str) -> Option<i64> {
self.root.lookup(path).and_then(|value| value.as_integer())
}
pub fn string_at(&self, path: &str) -> Option<String> {
self.root.lookup(path).and_then(|value| value.as_str()).map(|value| value.to_string())
}
pub fn strings_at(&self, path: &str) -> Option<Vec<String>> {
self.root
.lookup(path)
.and_then(|value| value.as_slice())
.map(|values| {
values.to_vec()
.iter()
.map(|value| value.as_str().unwrap().to_string())
.collect::<Vec<String>>()
})
}
pub fn bytes_at(&self, path: &str) -> Option<Vec<u8>> {
self.string_at(path).and_then(|value| value.from_hex().ok())
}
pub fn configurations_at(&self, path: &str) -> Option<Vec<Configuration>> {
self.root.lookup(path).and_then(|value| {
value.as_slice().map(|slice| {
slice.iter()
.map(|value| Configuration::new(value.clone()))
.collect()
})
})
}
}
impl From<io::Error> for Error {
fn from(error: io::Error) -> Self {
Error::IOError(error)
}
}