use crate::jsonpath::ast::comparison::Comparable;
use crate::jsonpath::ast::comparison::ComparisonExpr;
use crate::jsonpath::ast::comparison::ComparisonOp;
use crate::jsonpath::parser::ParseResult;
use crate::jsonpath::parser::function::functions::try_value_type_function;
use crate::jsonpath::parser::literal;
use crate::jsonpath::parser::primitives::{match_str, skip_whitespace};
use crate::jsonpath::parser::singular_query::try_parse as try_singular_query;
use crate::jsonpath::parser::{ParseError, ParseErrorKind};
use hurl_core::reader::Reader;
pub fn try_parse(reader: &mut Reader) -> ParseResult<Option<ComparisonExpr>> {
let save = reader.cursor();
let left = if let Some(value) = try_comparable(reader)? {
value
} else {
return Ok(None);
};
skip_whitespace(reader);
let operator = if let Some(value) = try_comparison_op(reader) {
value
} else {
reader.seek(save);
return Ok(None);
};
skip_whitespace(reader);
let right = comparable(reader)?;
Ok(Some(ComparisonExpr::new(left, right, operator)))
}
fn comparable(reader: &mut Reader) -> ParseResult<Comparable> {
if let Some(value) = try_comparable(reader)? {
Ok(value)
} else {
Err(ParseError::new(
reader.cursor().pos,
ParseErrorKind::Expecting("comparable".to_string()),
))
}
}
fn try_comparable(reader: &mut Reader) -> ParseResult<Option<Comparable>> {
if let Ok(literal) = literal::parse(reader) {
Ok(Some(Comparable::Literal(literal)))
} else if let Some(singular_query) = try_singular_query(reader)? {
Ok(Some(Comparable::SingularQuery(singular_query)))
} else if let Some(function) = try_value_type_function(reader)? {
Ok(Some(Comparable::Function(function)))
} else {
Ok(None)
}
}
fn try_comparison_op(reader: &mut Reader) -> Option<ComparisonOp> {
if match_str("==", reader) {
Some(ComparisonOp::Equal)
} else if match_str("!=", reader) {
Some(ComparisonOp::NotEqual)
} else if match_str("<=", reader) {
Some(ComparisonOp::LessOrEqual)
} else if match_str("<", reader) {
Some(ComparisonOp::Less)
} else if match_str(">=", reader) {
Some(ComparisonOp::GreaterOrEqual)
} else if match_str(">", reader) {
Some(ComparisonOp::Greater)
} else {
None
}
}
#[cfg(test)]
mod tests {
use crate::jsonpath::ast::literal::{Literal, Number};
use crate::jsonpath::ast::selector::NameSelector;
use crate::jsonpath::ast::singular_query::{RelativeSingularQuery, SingularQuerySegment};
use crate::jsonpath::ast::{comparison::ComparisonOp, singular_query::SingularQuery};
use hurl_core::reader::{CharPos, Reader};
use super::*;
#[test]
pub fn test_comparison_expr() {
let mut reader = Reader::new("1<=2");
assert_eq!(
try_parse(&mut reader).unwrap().unwrap(),
ComparisonExpr::new(
Comparable::Literal(Literal::Number(Number::Integer(1))),
Comparable::Literal(Literal::Number(Number::Integer(2))),
ComparisonOp::LessOrEqual
)
);
assert_eq!(reader.cursor().index, CharPos(4));
let mut reader = Reader::new("@.a == 1");
assert_eq!(
try_parse(&mut reader).unwrap().unwrap(),
ComparisonExpr::new(
Comparable::SingularQuery(SingularQuery::Relative(RelativeSingularQuery::new(
vec![SingularQuerySegment::Name(NameSelector::new(
"a".to_string()
))]
))),
Comparable::Literal(Literal::Number(Number::Integer(1))),
ComparisonOp::Equal
)
);
assert_eq!(reader.cursor().index, CharPos(8));
}
#[test]
pub fn test_comparison_expr_none() {
let mut reader = Reader::new("@.b]");
assert!(try_parse(&mut reader).unwrap().is_none());
assert_eq!(reader.cursor().index, CharPos(0));
let mut reader = Reader::new("$.*.a]");
assert!(try_parse(&mut reader).unwrap().is_none());
assert_eq!(reader.cursor().index, CharPos(0));
}
#[test]
pub fn test_comparable() {
let mut reader = Reader::new("1");
assert_eq!(
comparable(&mut reader).unwrap(),
Comparable::Literal(Literal::Number(Number::Integer(1)))
);
assert_eq!(reader.cursor().index, CharPos(1));
}
#[test]
pub fn test_comparaison_op() {
let mut reader = Reader::new("==");
assert_eq!(try_comparison_op(&mut reader).unwrap(), ComparisonOp::Equal);
assert_eq!(reader.cursor().index, CharPos(2));
}
#[test]
pub fn test_comparaison_op_none() {
let mut reader = Reader::new("]");
assert!(try_comparison_op(&mut reader).is_none());
assert_eq!(reader.cursor().index, CharPos(0));
}
}