2016-01-20 08:42:48 +00:00
|
|
|
use regex::Regex;
|
|
|
|
|
2016-01-20 09:37:24 +00:00
|
|
|
use std::convert::Into;
|
|
|
|
use std::convert::From;
|
|
|
|
|
|
|
|
use std::option::Option;
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
|
|
|
pub struct KeyValue<K, V> {
|
|
|
|
k: K,
|
|
|
|
v: V,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<K, V> KeyValue<K, V> {
|
|
|
|
|
|
|
|
pub fn new(k: K, v: V) -> KeyValue<K, V> {
|
|
|
|
KeyValue { k: k, v: v }
|
|
|
|
}
|
|
|
|
|
2016-01-20 09:45:13 +00:00
|
|
|
pub fn key(&self) -> &K {
|
|
|
|
&self.k
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn value(&self) -> &V {
|
|
|
|
&self.v
|
|
|
|
}
|
|
|
|
|
2016-01-20 09:37:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<K, V> Into<(K, V)> for KeyValue<K, V> {
|
|
|
|
|
|
|
|
fn into(self) -> (K, V) {
|
|
|
|
(self.k, self.v)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait IntoKeyValue<K, V> {
|
|
|
|
fn into_kv(self) -> Option<KeyValue<K, V>>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl IntoKeyValue<String, String> for String {
|
|
|
|
|
|
|
|
fn into_kv(self) -> Option<KeyValue<String, String>> {
|
2016-01-29 19:03:43 +00:00
|
|
|
let key = {
|
2016-02-20 20:10:22 +00:00
|
|
|
lazy_static! {
|
|
|
|
static ref R: Regex = Regex::new("^(?P<KEY>([^=]*))=(.*)$").unwrap();
|
|
|
|
}
|
|
|
|
R.captures(&self[..])
|
2016-01-29 19:03:43 +00:00
|
|
|
.and_then(|caps| caps.name("KEY"))
|
|
|
|
};
|
|
|
|
|
|
|
|
let value = {
|
2016-02-20 20:10:22 +00:00
|
|
|
lazy_static! {
|
|
|
|
static ref R: Regex = Regex::new("(.*)=(\"(?P<QVALUE>([^\"]*))\"|(?P<VALUE>(.*)))$")
|
|
|
|
.unwrap();
|
|
|
|
}
|
|
|
|
R.captures(&self[..])
|
2016-01-29 19:03:43 +00:00
|
|
|
.map(|caps| {
|
|
|
|
caps.name("VALUE")
|
|
|
|
.or(caps.name("QVALUE"))
|
|
|
|
.unwrap_or("")
|
|
|
|
})
|
|
|
|
};
|
|
|
|
|
|
|
|
key.and_then(|k| {
|
|
|
|
value.and_then(|v| {
|
|
|
|
Some(KeyValue::new(String::from(k), String::from(v)))
|
|
|
|
})
|
2016-01-20 09:37:24 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
2016-01-20 09:42:40 +00:00
|
|
|
use super::{KeyValue, IntoKeyValue};
|
2016-01-20 08:42:48 +00:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_single_quoted() {
|
2016-01-29 21:11:59 +00:00
|
|
|
let s = String::from("foo='bar'").into_kv().unwrap();
|
|
|
|
assert_eq!(KeyValue::new(String::from("foo"), String::from("\'bar\'")), s);
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_double_quoted() {
|
2016-01-20 09:42:40 +00:00
|
|
|
let s = String::from("foo=\"bar\"").into_kv().unwrap();
|
|
|
|
assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_double_and_single_quoted() {
|
2016-01-29 21:11:59 +00:00
|
|
|
let s = String::from("foo=\"bar\'").into_kv().unwrap();
|
|
|
|
assert_eq!(KeyValue::new(String::from("foo"), String::from("\"bar\'")), s);
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_single_and_double_quoted() {
|
2016-01-29 21:11:59 +00:00
|
|
|
let s = String::from("foo=\'bar\"").into_kv().unwrap();
|
|
|
|
assert_eq!(KeyValue::new(String::from("foo"), String::from("\'bar\"")), s);
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_not_quoted() {
|
2016-01-20 09:42:40 +00:00
|
|
|
let s = String::from("foo=bar").into_kv().unwrap();
|
|
|
|
assert_eq!(KeyValue::new(String::from("foo"), String::from("bar")), s);
|
2016-01-20 08:42:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|