Merge pull request #89 from BourgondAries/master
Allow advanced lookups in lookup and lookup_mut
This commit is contained in:
commit
c53fceb42c
67
src/lib.rs
67
src/lib.rs
|
@ -181,12 +181,16 @@ impl Value {
|
||||||
/// assert_eq!(no_bar.is_none(), true);
|
/// assert_eq!(no_bar.is_none(), true);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
|
pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a Value> {
|
||||||
|
let ref path = match Parser::new(path).lookup() {
|
||||||
|
Some(path) => path,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
let mut cur_value = self;
|
let mut cur_value = self;
|
||||||
if path.len() == 0 {
|
if path.len() == 0 {
|
||||||
return Some(cur_value)
|
return Some(cur_value)
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in path.split('.') {
|
for key in path {
|
||||||
match *cur_value {
|
match *cur_value {
|
||||||
Value::Table(ref hm) => {
|
Value::Table(ref hm) => {
|
||||||
match hm.get(key) {
|
match hm.get(key) {
|
||||||
|
@ -205,8 +209,8 @@ impl Value {
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(cur_value)
|
Some(cur_value)
|
||||||
}
|
|
||||||
|
|
||||||
|
}
|
||||||
/// Lookups for mutable value at specified path.
|
/// Lookups for mutable value at specified path.
|
||||||
///
|
///
|
||||||
/// Uses '.' as a path separator.
|
/// Uses '.' as a path separator.
|
||||||
|
@ -237,12 +241,17 @@ impl Value {
|
||||||
/// assert_eq!(result.as_str().unwrap(), "foo");
|
/// assert_eq!(result.as_str().unwrap(), "foo");
|
||||||
/// ```
|
/// ```
|
||||||
pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
|
pub fn lookup_mut(&mut self, path: &str) -> Option<&mut Value> {
|
||||||
|
let ref path = match Parser::new(path).lookup() {
|
||||||
|
Some(path) => path,
|
||||||
|
None => return None,
|
||||||
|
};
|
||||||
|
|
||||||
let mut cur = self;
|
let mut cur = self;
|
||||||
if path.len() == 0 {
|
if path.len() == 0 {
|
||||||
return Some(cur)
|
return Some(cur)
|
||||||
}
|
}
|
||||||
|
|
||||||
for key in path.split('.') {
|
for key in path {
|
||||||
let tmp = cur;
|
let tmp = cur;
|
||||||
match *tmp {
|
match *tmp {
|
||||||
Value::Table(ref mut hm) => {
|
Value::Table(ref mut hm) => {
|
||||||
|
@ -428,4 +437,56 @@ mod tests {
|
||||||
let baz = foo.lookup("foo").unwrap();
|
let baz = foo.lookup("foo").unwrap();
|
||||||
assert_eq!(baz.as_str().unwrap(), "bar");
|
assert_eq!(baz.as_str().unwrap(), "bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_advanced() {
|
||||||
|
let value: Value = "[table]\n\"value\" = 0".parse().unwrap();
|
||||||
|
let looked = value.lookup("table.\"value\"").unwrap();
|
||||||
|
assert_eq!(*looked, Value::Integer(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_advanced_table() {
|
||||||
|
let value: Value = r#"[table."name.other"] value = "my value""#.parse().unwrap();
|
||||||
|
let looked = value.lookup(r#"table."name.other".value"#).unwrap();
|
||||||
|
assert_eq!(*looked, Value::String(String::from("my value")));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_mut_advanced() {
|
||||||
|
let mut value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
let looked = value.lookup_mut("table.\"value\".1").unwrap();
|
||||||
|
assert_eq!(*looked, Value::Integer(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_dot() {
|
||||||
|
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
assert_eq!(None, value.lookup("."));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn array_dot() {
|
||||||
|
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
assert_eq!(None, value.lookup("0."));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn dot_inside() {
|
||||||
|
let value: Value = "[table]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
assert_eq!(None, value.lookup("table.\"value.0\""));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table_with_quotes() {
|
||||||
|
let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
assert_eq!(None, value.lookup("\"table.element\".\"value\".0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn table_with_quotes_2() {
|
||||||
|
let value: Value = "[table.\"element\"]\n\"value\" = [0, 1, 2]".parse().unwrap();
|
||||||
|
assert_eq!(Value::Integer(0), *value.lookup("table.\"element\".\"value\".0").unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -290,6 +290,31 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse an array index as a natural number
|
||||||
|
fn array_index(&mut self) -> Option<String> {
|
||||||
|
self.integer(0, false, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse a path into a vector of paths
|
||||||
|
pub fn lookup(&mut self) -> Option<Vec<String>> {
|
||||||
|
if self.input.len() == 0 {
|
||||||
|
return Some(vec![]);
|
||||||
|
}
|
||||||
|
let mut keys = Vec::new();
|
||||||
|
loop {
|
||||||
|
self.ws();
|
||||||
|
if let Some(s) = self.key_name() {
|
||||||
|
keys.push(s);
|
||||||
|
} else if let Some(s) = self.array_index() {
|
||||||
|
keys.push(s);
|
||||||
|
} else {
|
||||||
|
return None
|
||||||
|
}
|
||||||
|
self.ws();
|
||||||
|
if !self.expect('.') { return Some(keys) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Parse a single key name starting at `start`
|
// Parse a single key name starting at `start`
|
||||||
fn key_name(&mut self) -> Option<String> {
|
fn key_name(&mut self) -> Option<String> {
|
||||||
let start = self.next_pos();
|
let start = self.next_pos();
|
||||||
|
@ -969,6 +994,42 @@ mod tests {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_internal() {
|
||||||
|
let mut parser = Parser::new(r#"hello."world\t".a.0.'escaped'.value"#);
|
||||||
|
let result = vec![
|
||||||
|
String::from("hello"),
|
||||||
|
String::from("world\t"),
|
||||||
|
String::from("a"),
|
||||||
|
String::from("0"),
|
||||||
|
String::from("escaped"),
|
||||||
|
String::from("value")
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(parser.lookup().unwrap(), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_internal_void() {
|
||||||
|
let mut parser = Parser::new("");
|
||||||
|
assert_eq!(parser.lookup().unwrap(), Vec::<String>::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lookup_internal_simple() {
|
||||||
|
let mut parser = Parser::new("value");
|
||||||
|
assert_eq!(parser.lookup().unwrap(), vec![String::from("value")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is due to key_name not parsing an empty "" correctly. Disabled for now.
|
||||||
|
#[test]
|
||||||
|
#[ignore]
|
||||||
|
fn lookup_internal_quoted_void() {
|
||||||
|
let mut parser = Parser::new("\"\"");
|
||||||
|
assert_eq!(parser.lookup().unwrap(), vec![String::from("")]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn crlf() {
|
fn crlf() {
|
||||||
let mut p = Parser::new("\
|
let mut p = Parser::new("\
|
||||||
|
@ -1246,10 +1307,10 @@ trimmed in raw strings.
|
||||||
assert!(table.lookup("foo_3").is_some());
|
assert!(table.lookup("foo_3").is_some());
|
||||||
assert!(table.lookup("foo_-2--3--r23f--4-f2-4").is_some());
|
assert!(table.lookup("foo_-2--3--r23f--4-f2-4").is_some());
|
||||||
assert!(table.lookup("a").is_some());
|
assert!(table.lookup("a").is_some());
|
||||||
assert!(table.lookup("!").is_some());
|
assert!(table.lookup("\"!\"").is_some());
|
||||||
assert!(table.lookup("\"").is_some());
|
assert!(table.lookup("\"\\\"\"").is_some());
|
||||||
assert!(table.lookup("character encoding").is_some());
|
assert!(table.lookup("\"character encoding\"").is_some());
|
||||||
assert!(table.lookup("ʎǝʞ").is_some());
|
assert!(table.lookup("'ʎǝʞ'").is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1293,9 +1354,9 @@ trimmed in raw strings.
|
||||||
");
|
");
|
||||||
let table = Table(p.parse().unwrap());
|
let table = Table(p.parse().unwrap());
|
||||||
assert!(table.lookup("a.b").is_some());
|
assert!(table.lookup("a.b").is_some());
|
||||||
assert!(table.lookup("f f").is_some());
|
assert!(table.lookup("\"f f\"").is_some());
|
||||||
assert!(table.lookup("\"").is_some());
|
assert!(table.lookup("\"\\\"\"").is_some());
|
||||||
assert!(table.lookup("\"\"").is_some());
|
assert!(table.lookup("'\"\"'").is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
Loading…
Reference in a new issue