diff options
Diffstat (limited to 'bin/core/imag-store/src/util.rs')
-rw-r--r-- | bin/core/imag-store/src/util.rs | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/bin/core/imag-store/src/util.rs b/bin/core/imag-store/src/util.rs new file mode 100644 index 00000000..5da04666 --- /dev/null +++ b/bin/core/imag-store/src/util.rs @@ -0,0 +1,121 @@ +// +// imag - the personal information management suite for the commandline +// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public +// License as published by the Free Software Foundation; version +// 2.1 of the License. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +// + +use std::borrow::Cow; +use std::collections::btree_map::{BTreeMap, Entry}; +use std::str::Split; + +use clap::ArgMatches; +use toml::Value; + +use libimagutil::key_value_split::IntoKeyValue; + +pub fn build_toml_header(matches: &ArgMatches, mut header: Value) -> Value { + debug!("Building header from cli spec"); + if let Some(headerspecs) = matches.values_of("header") { + let kvs = headerspecs.into_iter() + .filter_map(|hs| { + debug!("- Processing: '{}'", hs); + let kv = String::from(hs).into_kv(); + debug!("- got: '{:?}'", kv); + kv + }); + for tpl in kvs { + let (key, value) = tpl.into(); + debug!("Splitting: {:?}", key); + let mut split = key.split('.'); + match (split.next(), &mut header) { + (Some(cur), &mut Value::Table(ref mut hdr)) => + insert_key_into(String::from(cur), &mut split, Cow::Owned(value), hdr), + _ => { } + } + } + } + + debug!("Header = {:?}", header); + header +} + +fn insert_key_into<'a>(current: String, + rest_path: &mut Split<char>, + value: Cow<'a, str>, + map: &mut BTreeMap<String, Value>) { + let next = rest_path.next(); + + if next.is_none() { + debug!("Inserting into {:?} = {:?}", current, value); + map.insert(current, parse_value(value)); + } else { + debug!("Inserting into {:?} ... = {:?}", current, value); + match map.entry(current) { + Entry::Occupied(ref mut e) => { + match *e.get_mut() { + Value::Table(ref mut t) => { + insert_key_into(String::from(next.unwrap()), rest_path, value, t); + }, + _ => unreachable!(), + } + }, + Entry::Vacant(v) => { v.insert(Value::Table( { + let mut submap = BTreeMap::new(); + insert_key_into(String::from(next.unwrap()), rest_path, value, &mut submap); + debug!("Inserting submap = {:?}", submap); + submap })); + } + } + } +} + +fn parse_value(value: Cow<str>) -> Value { + use std::str::FromStr; + + fn is_ary(v: &str) -> bool { + v.starts_with('[') && v.ends_with(']') && v.len() >= 3 + } + + if value == "true" { + debug!("Building Boolean out of: {:?}...", value); + Value::Boolean(true) + } else if value == "false" { + debug!("Building Boolean out of: {:?}...", value); + Value::Boolean(false) + } else if is_ary(&value) { + debug!("Building Array out of: {:?}...", value); + let sub = &value[1..(value.len()-1)]; + Value::Array(sub.split(',').map(|x| parse_value(Cow::from(x))).collect()) + } else { + FromStr::from_str(&value[..]) + .map(|i: i64| { + debug!("Building Integer out of: {:?}...", value); + Value::Integer(i) + }) + .unwrap_or_else(|_| { + FromStr::from_str(&value[..]) + .map(|f: f64| { + debug!("Building Float out of: {:?}...", value); + Value::Float(f) + }) + .unwrap_or_else(|_| { + debug!("Building String out of: {:?}...", value); + Value::String(value.into_owned()) + }) + }) + } +} + |