changeset 21:eae478565a9f draft

Add method for directly parsing a configuration file and a manual test (i.e., read/parse/write a configuration)
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 03 Dec 2016 16:09:31 +0100
parents 4914bd1e162f
children 226f1c607612
files prototype.toml src/config.rs
diffstat 2 files changed, 46 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/prototype.toml	Sat Dec 03 15:45:27 2016 +0100
+++ b/prototype.toml	Sat Dec 03 16:09:31 2016 +0100
@@ -12,6 +12,10 @@
 addr = "10.0.0.2"
 port = 538
 
+[remotes.example]
+addr = "example.com"
+port = 11023
+
 [files]
 [files.messages]
 # All possible options are described here
--- a/src/config.rs	Sat Dec 03 15:45:27 2016 +0100
+++ b/src/config.rs	Sat Dec 03 16:09:31 2016 +0100
@@ -4,7 +4,10 @@
 use std::collections::HashMap;
 use std::collections::btree_map::Entry;
 use std::default::Default;
+use std::fs;
+use std::io::{self, Read};
 use std::net::SocketAddr;
+use std::path::Path;
 use std::str::FromStr;
 
 use dns_lookup;
@@ -15,6 +18,10 @@
 /// Parses strings like 0/1s/2m/3h/4d/5w and returns seconds. If no unit is there, seconds is
 /// assumed.
 fn parse_duration(s: &str) -> Option<u64> {
+    if s.len() == 0 {
+        return None;
+    }
+
     let s = s.trim();
     let suffix = &s[s.len() - 1..];
     let num_part = &s[0..s.len() - 1];
@@ -133,7 +140,7 @@
 
 // config structs
 
-#[derive(Clone,Default)]
+#[derive(Clone, Debug, Default)]
 pub struct General {
     pub bind_path: String,
     pub max_msg_len: usize,
@@ -152,7 +159,7 @@
     Ok(g)
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub struct Remote {
     addr: SocketAddr,
 }
@@ -174,7 +181,7 @@
     Err(toml::Error::Custom(format!("Couldn't parse/resolve host {} for {}", addr, name)))
 }
 
-#[derive(Clone)]
+#[derive(Clone, Debug)]
 pub enum CompressType {
     NoCompression,
     // TODO: implement flate2 for compression.
@@ -200,7 +207,7 @@
     }
 }
 
-#[derive(Clone,Default)]
+#[derive(Clone, Debug, Default)]
 pub struct File {
     name: String,
     location: String,
@@ -368,7 +375,7 @@
     }
 }
 
-#[derive(Clone,Default)]
+#[derive(Clone, Debug, Default)]
 pub struct Rule {
     pattern: Matcher,
     // refers to the file entry name, not the file name.
@@ -395,7 +402,7 @@
     })
 }
 
-#[derive(Clone,Default)]
+#[derive(Clone, Debug, Default)]
 pub struct Config {
     pub general: General,
     remotes: HashMap<String, Remote>,
@@ -453,9 +460,30 @@
             }
         }
 
-        unimplemented!()
+        Ok(cfg)
     } else {
-        return Err(toml::Error::Custom("Couldn't parse configuration".to_string()));
+        Err(toml::Error::Custom("Couldn't parse configuration".to_string()))
+    }
+}
+
+pub fn open_and_read_config<P>(p: P) -> io::Result<Config>
+    where P: AsRef<Path>
+{
+    let f = try!(fs::OpenOptions::new().read(true).open(p));
+    let contents: Vec<u8> = f.bytes().map(|b| b.unwrap_or(' ' as u8)).collect();
+
+    match String::from_utf8(contents) {
+        Ok(s) => {
+            let cfg = decode_config(&s);
+
+            match cfg {
+                Ok(cfg) => Ok(cfg),
+                Err(e) => {
+                    Err(io::Error::new(io::ErrorKind::InvalidData, format!("bad config: {}", e)))
+                }
+            }
+        }
+        Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "UTF8 decoding failed")),
     }
 }
 
@@ -499,4 +527,10 @@
             assert_eq!(parse_duration(test), Some(result));
         }
     }
+
+    #[test]
+    fn test_config_parse_prototype() {
+        let config = open_and_read_config("./prototype.toml");
+        println!("{:?}", config);
+    }
 }