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);
|
||||
/// ```
|
||||
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;
|
||||
if path.len() == 0 {
|
||||
return Some(cur_value)
|
||||
}
|
||||
|
||||
for key in path.split('.') {
|
||||
for key in path {
|
||||
match *cur_value {
|
||||
Value::Table(ref hm) => {
|
||||
match hm.get(key) {
|
||||
|
@ -205,8 +209,8 @@ impl Value {
|
|||
};
|
||||
|
||||
Some(cur_value)
|
||||
}
|
||||
|
||||
}
|
||||
/// Lookups for mutable value at specified path.
|
||||
///
|
||||
/// Uses '.' as a path separator.
|
||||
|
@ -237,12 +241,17 @@ impl Value {
|
|||
/// assert_eq!(result.as_str().unwrap(), "foo");
|
||||
/// ```
|
||||
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;
|
||||
if path.len() == 0 {
|
||||
return Some(cur)
|
||||
}
|
||||
|
||||
for key in path.split('.') {
|
||||
for key in path {
|
||||
let tmp = cur;
|
||||
match *tmp {
|
||||
Value::Table(ref mut hm) => {
|
||||
|
@ -428,4 +437,56 @@ mod tests {
|
|||
let baz = foo.lookup("foo").unwrap();
|
||||
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`
|
||||
fn key_name(&mut self) -> Option<String> {
|
||||
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]
|
||||
fn crlf() {
|
||||
let mut p = Parser::new("\
|
||||
|
@ -1246,10 +1307,10 @@ trimmed in raw strings.
|
|||
assert!(table.lookup("foo_3").is_some());
|
||||
assert!(table.lookup("foo_-2--3--r23f--4-f2-4").is_some());
|
||||
assert!(table.lookup("a").is_some());
|
||||
assert!(table.lookup("!").is_some());
|
||||
assert!(table.lookup("\"").is_some());
|
||||
assert!(table.lookup("character encoding").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("'ʎǝʞ'").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -1293,9 +1354,9 @@ trimmed in raw strings.
|
|||
");
|
||||
let table = Table(p.parse().unwrap());
|
||||
assert!(table.lookup("a.b").is_some());
|
||||
assert!(table.lookup("f f").is_some());
|
||||
assert!(table.lookup("\"").is_some());
|
||||
assert!(table.lookup("\"\"").is_some());
|
||||
assert!(table.lookup("\"f f\"").is_some());
|
||||
assert!(table.lookup("\"\\\"\"").is_some());
|
||||
assert!(table.lookup("'\"\"'").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Reference in a new issue