Created
January 23, 2015 12:01
-
-
Save Inari-Whitebear/b361c1c4aaf7697df904 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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