Skip to content

Instantly share code, notes, and snippets.

@Inari-Whitebear
Created January 23, 2015 12:01
Show Gist options
  • Save Inari-Whitebear/b361c1c4aaf7697df904 to your computer and use it in GitHub Desktop.
Save Inari-Whitebear/b361c1c4aaf7697df904 to your computer and use it in GitHub Desktop.
use std::fmt;
use std::io;
use std::cell::RefCell;
use std::collections::HashMap;
pub enum ConfigValue {
String(String),
Number(isize),
Null
}
pub struct Config {
config_values: RefCell<HashMap<String,ConfigValue>>,
pub path: Option<Path>,
}
impl fmt::String for Config {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let hashmap = self.config_values.borrow();
let mut fields = String::new();
for (field,value) in hashmap.iter() {
fields = fields + &*format!("\r\n{0} => {1}", field, format!("{}", value));
}
write!(f, "Fields:{}", fields)
}
}
impl Clone for ConfigValue {
fn clone(&self) -> ConfigValue {
match self {
&ConfigValue::String(ref str) => ConfigValue::String(str.clone()),
&ConfigValue::Number(is) => ConfigValue::Number(is),
&ConfigValue::Null => ConfigValue::Null
}
}
}
impl fmt::String for ConfigValue {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&ConfigValue::String(ref str) => write!(f, "{}", str),
&ConfigValue::Number(is) => write!(f, "{}", is),
&ConfigValue::Null => write!(f, "Null")
}
}
}
impl Config {
pub fn set_value(&self, field: String, value: ConfigValue) {
{
let mut config = self.config_values.borrow_mut();
(*config).insert(field, value);
}
self.save();
}
pub fn get_value(&self, field: &str) -> ConfigValue {
let config = self.config_values.borrow();
let opt = (*config).get(field);
match opt {
Some(c) => (*c).clone(),
None => ConfigValue::Null
}
}
pub fn unset(&self, field: &str) -> Result<ConfigValue, String> {
let removed;
{
let mut hashmap = self.config_values.borrow_mut();
removed = hashmap.remove(field);
}
self.save();
match removed {
Some(s) => Ok(s),
None => Err("Field not found".to_string())
}
}
pub fn new() -> Config {
let mut conf = Config { config_values: RefCell::new(HashMap::new()), path: None };
conf
}
pub fn save(&self) {
if self.path.is_some() {
self.save_to(self.path.as_ref().unwrap());
}
}
pub fn save_to(&self, path: &Path) -> io::IoResult<()> {
use std::io::{File, fs};
let mut file = try!(File::create(path));
let hashmap = self.config_values.borrow();
for (field, value) in hashmap.iter() {
let val_short = match value {
&ConfigValue::String(_) => "S:",
&ConfigValue::Number(_) => "N:",
_ => ""
};
let mut to_write = String::from_str(val_short);
to_write.push_str(&**field);
to_write.push_str("=");
to_write.push_str(&*format!("{}", value));
try!(file.write_line(&*to_write));
}
Ok(())
}
pub fn load(&self) -> io::IoResult<()> {
use std::io::{File, fs, BufferedReader};
fn parse_line<'a>(line: &'a str) -> io::IoResult<(&'a str, &'a str, &'a str)> {
let mut parts = line.split_str("=");
let left = parts.next();
let right = parts.next();
if left.is_none() || right.is_none() {
Err(io::IoError { kind: io::IoErrorKind::InvalidInput, desc: "Invalid input line", detail: None })
} else {
let mut left_parts = left.unwrap().split_str(":");
let conf_type = left_parts.next();
let field = left_parts.next();
if conf_type.is_none() || field.is_none() {
Err(io::IoError { kind: io::IoErrorKind::InvalidInput, desc: "Invalid input line", detail: None })
} else {
Ok((field.unwrap(), conf_type.unwrap(), right.unwrap()))
}
}
}
let mut hashmap = self.config_values.borrow_mut();
if self.path.is_none() {
return Err(io::IoError { kind: io::IoErrorKind::PathDoesntExist, desc: "No path set", detail: None });
}
let file = try!(File::open(self.path.as_ref().unwrap()));
let mut reader = BufferedReader::new(file);
loop {
let res = reader.read_line();
match res {
Ok(s) => {
let result = parse_line(&*s);
if result.is_ok() {
let (field, conf_type, value) = result.unwrap();
hashmap.insert(field.to_string(), match conf_type {
"N" => ConfigValue::Number(value.parse().unwrap()),
"S" => ConfigValue::String(String::from_str(value)),
_ => ConfigValue::Null
});
}
},
Err(e) => {
break;
}
}
}
Ok(())
}
pub fn load_from(path: &Path) -> Config {
let mut config = Config::new();
config.path = Some(path.clone());
config.load();
config
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment