use nom::branch::alt;
use nom::character::complete::char;
use nom::combinator::map;
use nom::error::context;
use serde_json_path_core::spec::selector::index::Index;
use serde_json_path_core::spec::selector::name::Name;
use serde_json_path_core::spec::selector::Selector;
use self::filter::parse_filter;
use self::slice::parse_array_slice;
use super::primitive::int::parse_int;
use super::primitive::string::parse_string_literal;
use super::PResult;
pub(crate) mod filter;
pub(crate) mod function;
pub(crate) mod slice;
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
pub(crate) fn parse_wildcard_selector(input: &str) -> PResult<Selector> {
map(char('*'), |_| Selector::Wildcard)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
pub(crate) fn parse_name(input: &str) -> PResult<Name> {
map(parse_string_literal, Name)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
fn parse_name_selector(input: &str) -> PResult<Selector> {
map(parse_name, Selector::Name)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
fn parse_index(input: &str) -> PResult<Index> {
map(parse_int, Index)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
fn parse_index_selector(input: &str) -> PResult<Selector> {
map(parse_index, Selector::Index)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
fn parse_array_slice_selector(input: &str) -> PResult<Selector> {
map(parse_array_slice, Selector::ArraySlice)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
fn parse_filter_selector(input: &str) -> PResult<Selector> {
map(parse_filter, Selector::Filter)(input)
}
#[cfg_attr(feature = "trace", tracing::instrument(level = "trace", parent = None, ret, err))]
pub(crate) fn parse_selector(input: &str) -> PResult<Selector> {
context(
"selector",
alt((
parse_wildcard_selector,
parse_name_selector,
parse_array_slice_selector,
parse_index_selector,
parse_filter_selector,
)),
)(input)
}
#[cfg(test)]
mod tests {
use serde_json_path_core::spec::{
integer::Integer,
selector::{name::Name, slice::Slice},
};
use super::{parse_selector, parse_wildcard_selector, Index, Selector};
#[test]
fn wildcard() {
assert!(matches!(
parse_wildcard_selector("*"),
Ok(("", Selector::Wildcard))
));
}
#[test]
fn all_selectors() {
{
let (_, s) = parse_selector("0").unwrap();
assert_eq!(s, Selector::Index(Index(Integer::from_i64_unchecked(0))));
}
{
let (_, s) = parse_selector("10").unwrap();
assert_eq!(s, Selector::Index(Index(Integer::from_i64_unchecked(10))));
}
{
let (_, s) = parse_selector("'name'").unwrap();
assert_eq!(s, Selector::Name(Name(String::from("name"))));
}
{
let (_, s) = parse_selector("\"name\"").unwrap();
assert_eq!(s, Selector::Name(Name(String::from("name"))));
}
{
let (_, s) = parse_selector("0:3").unwrap();
assert_eq!(
s,
Selector::ArraySlice(Slice::new().with_start(0).with_end(3))
);
}
}
}