Spaces:
Build error
Build error
File size: 3,148 Bytes
84d2a97 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
use std::str::FromStr;
use nom::branch::alt;
use nom::bytes::complete::tag;
use nom::character::complete::{char, digit1, none_of, satisfy};
use nom::combinator::{all_consuming, map_res, recognize};
use nom::multi::{many0, many1};
use nom::sequence::{delimited, preceded};
use nom::{IResult, Parser};
use super::{JsonPath, JsonPathItem};
impl FromStr for JsonPath {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match json_path(s) {
Ok(("", path)) => Ok(path),
_ => Err(()),
}
}
}
pub fn key_needs_quoting(s: &str) -> bool {
let mut parser = all_consuming(raw_str);
parser(s).is_err()
}
fn json_path(input: &str) -> IResult<&str, JsonPath> {
let (input, first_key) = alt((raw_str.map(str::to_string), quoted_str)).parse(input)?;
let (input, rest) = many0(alt((
(preceded(char('.'), raw_str).map(|s| JsonPathItem::Key(s.to_string()))),
(preceded(char('.'), quoted_str).map(JsonPathItem::Key)),
(delimited(char('['), number, char(']')).map(JsonPathItem::Index)),
(tag("[]").map(|_| JsonPathItem::WildcardIndex)),
)))(input)?;
Ok((input, JsonPath { first_key, rest }))
}
fn raw_str(input: &str) -> IResult<&str, &str> {
recognize(many1(
satisfy(|c: char| c.is_alphanumeric() || c == '_' || c == '-').map(|_: char| ()),
))
.parse(input)
}
fn quoted_str(input: &str) -> IResult<&str, String> {
let (input, _) = char('"')(input)?;
let (input, rest) = many0(none_of("\\\""))(input)?;
let (input, _) = char('"')(input)?;
Ok((input, rest.iter().collect()))
}
fn number(input: &str) -> IResult<&str, usize> {
map_res(recognize(digit1), str::parse)(input)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse() {
assert!("".parse::<JsonPath>().is_err());
assert_eq!(
"foo".parse(),
Ok(JsonPath {
first_key: "foo".to_string(),
rest: vec![],
})
);
assert_eq!(
"foo[1][50].bar-baz[].\"qux[.]quux\"".parse(),
Ok(JsonPath {
first_key: "foo".to_string(),
rest: vec![
JsonPathItem::Index(1),
JsonPathItem::Index(50),
JsonPathItem::Key("bar-baz".to_string()),
JsonPathItem::WildcardIndex,
JsonPathItem::Key("qux[.]quux".to_string()),
],
})
);
}
#[test]
fn test_key_needs_quoting() {
// Key needs no quoting
assert!(!key_needs_quoting("f"));
assert!(!key_needs_quoting("foo"));
assert!(!key_needs_quoting("foo_123-bar"));
// Key needs quoting
assert!(key_needs_quoting(""));
assert!(key_needs_quoting(" foo"));
assert!(key_needs_quoting("foo "));
assert!(key_needs_quoting("foo bar"));
assert!(key_needs_quoting("foo bar baz"));
assert!(key_needs_quoting("foo.bar.baz"));
assert!(key_needs_quoting("foo[]"));
assert!(key_needs_quoting("foo[0]"));
}
}
|