#[derive(Debug, Clone, PartialEq)]
pub struct RawPredicate<'a> {
pub selector: &'a str,
pub operator: &'a str,
pub value: RawValue<'a>,
pub span: pest::Span<'a>,
pub selector_span: pest::Span<'a>,
pub operator_span: pest::Span<'a>,
pub value_span: pest::Span<'a>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RawValue<'a> {
Quoted(&'a str), Raw(&'a str), }
#[derive(Debug, Clone, PartialEq)]
pub enum RawExpr<'a> {
Not(Box<RawExpr<'a>>),
And(Box<RawExpr<'a>>, Box<RawExpr<'a>>),
Or(Box<RawExpr<'a>>, Box<RawExpr<'a>>),
Predicate(RawPredicate<'a>),
SingleWord(pest::Span<'a>),
}
impl<'a> RawExpr<'a> {
pub fn to_test_expr(&self) -> test_utils::RawTestExpr<'a> {
match self {
RawExpr::Not(expr) => test_utils::RawTestExpr::Not(Box::new(expr.to_test_expr())),
RawExpr::And(left, right) => test_utils::RawTestExpr::And(
Box::new(left.to_test_expr()),
Box::new(right.to_test_expr()),
),
RawExpr::Or(left, right) => test_utils::RawTestExpr::Or(
Box::new(left.to_test_expr()),
Box::new(right.to_test_expr()),
),
RawExpr::Predicate(pred) => {
test_utils::RawTestExpr::Predicate(pred.to_test_predicate())
}
RawExpr::SingleWord(span) => test_utils::RawTestExpr::SingleWord(span.as_str()),
}
}
}
impl<'a> RawPredicate<'a> {
pub fn to_test_predicate(&self) -> test_utils::RawTestPredicate<'a> {
test_utils::RawTestPredicate {
selector: self.selector,
operator: self.operator,
value: self.value.to_test_value(),
}
}
}
impl<'a> RawValue<'a> {
pub fn as_string(&self) -> &'a str {
match self {
RawValue::Quoted(s) | RawValue::Raw(s) => s,
}
}
pub fn is_quoted(&self) -> bool {
matches!(self, RawValue::Quoted(_))
}
pub fn to_test_value(&self) -> test_utils::RawTestValue<'a> {
match self {
RawValue::Quoted(s) => test_utils::RawTestValue::Quoted(s),
RawValue::Raw(s) => test_utils::RawTestValue::Raw(s),
}
}
}
pub mod test_utils {
#[derive(Debug, Clone, PartialEq)]
pub struct RawTestPredicate<'a> {
pub selector: &'a str,
pub operator: &'a str,
pub value: RawTestValue<'a>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum RawTestValue<'a> {
Quoted(&'a str), Raw(&'a str), }
impl std::fmt::Display for RawTestValue<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
RawTestValue::Quoted(s) | RawTestValue::Raw(s) => write!(f, "{s}"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum RawTestExpr<'a> {
Not(Box<RawTestExpr<'a>>),
And(Box<RawTestExpr<'a>>, Box<RawTestExpr<'a>>),
Or(Box<RawTestExpr<'a>>, Box<RawTestExpr<'a>>),
Predicate(RawTestPredicate<'a>),
SingleWord(&'a str),
}
impl<'a> RawTestExpr<'a> {
pub fn string_predicate(selector: &'a str, operator: &'a str, value: &'a str) -> Self {
RawTestExpr::Predicate(RawTestPredicate {
selector,
operator,
value: RawTestValue::Raw(value),
})
}
pub fn quoted_predicate(selector: &'a str, operator: &'a str, value: &'a str) -> Self {
RawTestExpr::Predicate(RawTestPredicate {
selector,
operator,
value: RawTestValue::Quoted(value),
})
}
pub fn set_predicate(selector: &'a str, operator: &'a str, values: Vec<&'a str>) -> Self {
let value = format!("[{}]", values.join(","));
RawTestExpr::Predicate(RawTestPredicate {
selector,
operator,
value: RawTestValue::Raw(Box::leak(value.into_boxed_str())),
})
}
pub fn single_word(word: &'a str) -> Self {
RawTestExpr::SingleWord(word)
}
pub fn and(left: RawTestExpr<'a>, right: RawTestExpr<'a>) -> Self {
RawTestExpr::And(Box::new(left), Box::new(right))
}
pub fn or(left: RawTestExpr<'a>, right: RawTestExpr<'a>) -> Self {
RawTestExpr::Or(Box::new(left), Box::new(right))
}
#[allow(clippy::should_implement_trait)]
pub fn not(expr: RawTestExpr<'a>) -> Self {
RawTestExpr::Not(Box::new(expr))
}
}
}