// // imag - the personal information management suite for the commandline // Copyright (C) 2015-2019 Matthias Beyer 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 regex::Regex; use std::convert::Into; use std::convert::From; use std::option::Option; #[derive(Clone, Copy, Debug, PartialEq)] pub struct KeyValue { k: K, v: V, } impl KeyValue { pub fn new(k: K, v: V) -> KeyValue { KeyValue { k, v } } pub fn key(&self) -> &K { &self.k } pub fn value(&self) -> &V { &self.v } } impl Into<(K, V)> for KeyValue { fn into(self) -> (K, V) { (self.k, self.v) } } pub trait IntoKeyValue { fn into_kv(self) -> Option>; } impl IntoKeyValue for String { fn into_kv(self) -> Option> { let key = { lazy_static! { static ref R: Regex = Regex::new("^(?P([^=]*))=(.*)$").unwrap(); } R.captures(&self[..]) .and_then(|caps| caps.name("KEY")) }; let value = { lazy_static! { static ref R: Regex = Regex::new("(.*)=(\"(?P([^\"]*))\"|(?P(.*)))$") .unwrap(); } R.captures(&self[..]) .map(|c| { c.name("VALUE") .or_else(|| c.name("QVALUE")) .map(|m| m.as_str()) .unwrap_or("") }) }; key.and_then(|k| { value.and_then(|v| Some(KeyValue::new(String::from(k.as_str()), String::from(v)))) }) } } #[cfg(test)] mod test { use super::{KeyValue, IntoKeyValue}; #[test] fn test_single_quoted() { let s = String::from("foo='bar'").into_kv().unwrap(); assert_eq!(KeyValue::new(String::from("foo"), String::from("\'bar\'")), s); } #[test] fn test_double_quoted() { let s = String::from("foo=\"bar\"").into_kv().unwrap(); assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s); } #[test] fn test_double_and_single_quoted() { let s = String::from("foo=\"bar\'").into_kv().unwrap(); assert_eq!(KeyValue::new(String::from("foo"), String::from("\"bar\'")), s); } #[test] fn test_single_and_double_quoted() { let s = String::from("foo=\'bar\"").into_kv().unwrap(); assert_eq!(KeyValue::new(String::from("foo"), String::from("\'bar\"")), s); } #[test] fn test_not_quoted() { let s = String::from("foo=bar").into_kv().unwrap(); assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s); } }