changeset 22:226f1c607612 draft

Fix file size parsing and general settings extraction
author Lewin Bormann <lbo@spheniscida.de>
date Sat, 03 Dec 2016 16:27:07 +0100
parents eae478565a9f
children 2b5e442c8bbb
files src/config.rs
diffstat 1 files changed, 70 insertions(+), 22 deletions(-) [+]
line wrap: on
line diff
--- a/src/config.rs	Sat Dec 03 16:09:31 2016 +0100
+++ b/src/config.rs	Sat Dec 03 16:27:07 2016 +0100
@@ -2,7 +2,6 @@
 //!
 
 use std::collections::HashMap;
-use std::collections::btree_map::Entry;
 use std::default::Default;
 use std::fs;
 use std::io::{self, Read};
@@ -68,6 +67,51 @@
     }
 }
 
+/// Parses expressions like 1/2B/3k/4M/5G
+fn parse_size(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];
+
+    if suffix == "B" {
+        if let Ok(s) = u64::from_str(num_part) {
+            Some(s)
+        } else {
+            None
+        }
+    } else if suffix == "k" {
+        if let Ok(k) = u64::from_str(num_part) {
+            Some(k * 1024)
+        } else {
+            None
+        }
+    } else if suffix == "M" || suffix == "m" {
+        if let Ok(m) = u64::from_str(num_part) {
+            Some(m * 1024 * 1024)
+        } else {
+            None
+        }
+    } else if suffix == "G" || suffix == "g" {
+        if let Ok(g) = u64::from_str(num_part) {
+            Some(g * 1024 * 1024 * 1024)
+        } else {
+            None
+        }
+    } else if let Ok(_) = u64::from_str(suffix) {
+        // no explicit unit
+        if let Ok(s) = u64::from_str(s) {
+            Some(s)
+        } else {
+            None
+        }
+    } else {
+        None
+    }
+}
 // helper functions for extracting values from TOML values
 fn get_string(tbl: &toml::Table, key: &str, default: String) -> String {
     if let Some(e) = tbl.get(key) {
@@ -108,15 +152,20 @@
 /// Extract an array of tables.
 fn get_tbl_arr(tbl: &toml::Table, key: &str) -> Option<Vec<toml::Table>> {
     if let Some(e) = tbl.get(key) {
+        println!("got tables");
         if let &toml::Value::Array(ref a) = e {
             let mut v = Vec::with_capacity(a.len());
 
             for elem in a {
                 match elem {
-                    &toml::Value::Table(ref t) => v.push(t.clone()),
+                    &toml::Value::Table(ref t) => {
+                        v.push(t.clone())
+                    },
                     _ => (),
                 }
             }
+
+            return Some(v)
         }
     }
     None
@@ -151,12 +200,10 @@
     let default_bind_path = "/dev/log".to_string();
     let default_max_msg_len = 8192;
 
-    let mut g = General {
+    Ok(General {
         bind_path: get_string(t, "bind_path", default_bind_path),
         max_msg_len: get_int(t, "max_msg_len", default_max_msg_len) as usize,
-    };
-
-    Ok(g)
+    })
 }
 
 #[derive(Clone, Debug)]
@@ -223,7 +270,7 @@
     let f = File {
         name: name.to_string(),
         location: get_string(tbl, "file", "".to_string()),
-        max_size: get_int(tbl, "max_size", 4 * 1024 * 1024) as usize,
+        max_size: parse_size(&get_string(tbl, "max_size", "4M".to_string())).unwrap_or(4 * 1024 * 1024) as usize,
         max_age: parse_duration(&get_string(tbl, "max_age", "".to_string())).unwrap_or(0),
         history: get_int(tbl, "history", 10) as i32,
         compress: assemble_compress_type(tbl.get("compress")
@@ -300,9 +347,6 @@
 
     if let Some(facilities) = parts.next() {
         if let Some(levels) = parts.next() {
-            let fac_pattern = parse_facility_pattern(facilities);
-            let lvl_pattern = parse_level_pattern(levels);
-
             return match (parse_facility_pattern(facilities), parse_level_pattern(levels)) {
                 (Ok(f), Ok(l)) => Ok((f, l)),
                 (Err(e), Err(f)) => tomlerr(format!("{} {}", e, f)),
@@ -315,25 +359,28 @@
 }
 
 fn parse_facility_pattern(s: &str) -> Result<FacPattern, toml::Error> {
-    let mut list: Vec<String> = s.trim().split(',').map(String::from).collect();
+    let list: Vec<String> = s.trim().split(',').map(String::from).collect();
 
     if list.len() > 1 {
-        let mut facilities = vec![priority::Facility::LOCAL0; list.len()];
-        let mut i = 0;
+        let mut facilities = Vec::with_capacity(list.len());
 
         for f in list {
             if let Some(fac) = priority::str_to_facility(f.trim()) {
-                facilities[i] = fac;
+                facilities.push(fac);
             } else {
                 return tomlerr(format!("Unrecognized facility: {}", f));
             }
         }
         Ok(FacPattern::MultiFacility(facilities))
     } else if list.len() == 1 {
-        if let Some(fac) = priority::str_to_facility(&list[0]) {
+        let l = &list[0];
+
+        if l == "*" {
+            Ok(FacPattern::Wildcard)
+        } else if let Some(fac) = priority::str_to_facility(l) {
             Ok(FacPattern::Facility(fac))
         } else {
-            tomlerr(format!("Unknown facility: {}", &list[0]))
+            tomlerr(format!("Unknown facility: {}", l))
         }
     } else {
         return tomlerr(format!("Level pattern can't be empty"));
@@ -341,15 +388,14 @@
 }
 
 fn parse_level_pattern(s: &str) -> Result<LvlPattern, toml::Error> {
-    let mut list: Vec<String> = s.trim().split(',').map(String::from).collect();
+    let list: Vec<String> = s.trim().split(',').map(String::from).collect();
 
     if list.len() > 1 {
-        let mut levels = vec![priority::Level::NONE; list.len()];
-        let mut i = 0;
+        let mut levels = Vec::with_capacity(list.len());
 
         for l in list {
             if let Some(lvl) = priority::str_to_level(l.trim()) {
-                levels[i] = lvl;
+                levels.push(lvl);
             } else {
                 return tomlerr(format!("Unrecognized facility: {}", l));
             }
@@ -365,6 +411,8 @@
             } else {
                 tomlerr(format!("Unknown exact facility: {}", l))
             }
+        } else if &l[..] == "*" {
+            Ok(LvlPattern::Wildcard)
         } else if let Some(lvl) = priority::str_to_level(l) {
             Ok(LvlPattern::Level(lvl))
         } else {
@@ -415,7 +463,7 @@
 
     if let Some(tbl) = toml::Parser::new(&text).parse() {
         if let Some(gen) = get_tbl(&tbl, "general") {
-            cfg.general = try!(assemble_general(&tbl));
+            cfg.general = try!(assemble_general(&gen));
         } else {
             return tomlerr("Could not find 'general' section".to_string());
         }
@@ -483,7 +531,7 @@
                 }
             }
         }
-        Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "UTF8 decoding failed")),
+        Err(_) => return Err(io::Error::new(io::ErrorKind::InvalidInput, "UTF8 decoding failed")),
     }
 }