1extern crate toml;
2
3pub use self::toml::*;
4
5use std::path::Path;
6use std::fs::File;
7use std::io;
8use std::io::prelude::*;
9
10#[derive(Debug)]
11pub enum LoadError {
12 Open(io::Error),
13 Read(io::Error),
14 Parse(de::Error)
15}
16
17pub trait ValueImpl {
18 fn new() -> Self;
19 fn load<P: AsRef<Path>>(p: P) -> Result<Value, LoadError>;
20 fn save<P: AsRef<Path>>(&self, p: P) -> io::Result<()>;
21 fn find(&self, name: &str) -> Option<&Value>;
22 fn find_mut(&mut self, name: &str) -> Option<&mut Value>;
23 fn set<V: Into<Value>>(&mut self, name: &str, v: V) -> bool;
24}
25
26impl ValueImpl for Value {
27 fn new() -> Value {
29 Value::from(value::Table::new())
30 }
31
32 fn load<P: AsRef<Path>>(p: P) -> Result<Value, LoadError> {
34 let mut f = match File::open(p) {
35 Ok(f) => f,
36 Err(e) => return Err(LoadError::Open(e)),
37 };
38
39 let mut s = String::new();
40 if let Err(e) = f.read_to_string(&mut s) {
41 return Err(LoadError::Read(e));
42 }
43
44 match s.parse::<Value>() {
45 Ok(s) => Ok(s),
46 Err(e) => Err(LoadError::Parse(e)),
47 }
48 }
49
50 fn save<P: AsRef<Path>>(&self, p: P) -> io::Result<()> {
51 let s = toml::ser::to_string_pretty(&self)
54 .expect("Failed to transform toml to string");
55 File::create(p)?.write_all(s.as_bytes())
56 }
57
58 fn find(&self, name: &str) -> Option<&Value> {
59 toml_find(self, name)
60 }
61
62 fn find_mut(&mut self, name: &str) -> Option<&mut Value> {
63 toml_find_mut(self, name)
64 }
65
66 fn set<V: Into<Value>>(&mut self, name: &str, v: V) -> bool {
67 toml_set(self, name, v.into())
68 }
69}
70
71pub fn toml_find<'a>(v: &'a Value, name: &str)
76 -> Option<&'a Value> {
77 let mut next = v;
78 for part in name.split('.') {
79 let cur = next;
80 match *cur {
81 Value::Table(ref table) =>
82 match table.get(part) {
83 Some(entry) => next = entry,
84 None => return None,
85 }, _ => return None,
86 };
87 }
88 Some(next)
89}
90
91pub fn toml_find_mut<'a>(v: &'a mut Value, name: &str)
92 -> Option<&'a mut Value> {
93 let mut next = v;
94 for part in name.split('.') {
95 let cur = next;
96 match *cur {
97 Value::Table(ref mut table) =>
98 match table.get_mut(part) {
99 Some(entry) => next = entry,
100 None => return None,
101 }, _ => return None,
102 };
103 }
104 Some(next)
105}
106
107pub fn toml_set(v: &mut Value, name: &str, val: Value) -> bool {
111 let mut next = v;
112 let mut it = name.split('.');
113 let last = it.next_back().expect("Invalid name given");
114
115 for part in it {
117 let cur = next;
118 match *cur {
119 Value::Table(ref mut table) => {
120 let e = table.entry(part.to_string());
121 next = e.or_insert(Value::new());
122 },
123 _ => return false,
124 };
125 }
126
127 match *next {
129 Value::Table(ref mut table) =>
130 table.insert(last.to_string(), val),
131 _ => return false,
132 };
133
134 true
135}