add NotEqual filter
This commit is contained in:
parent
8fcb2824de
commit
557d7c680e
@ -46,7 +46,7 @@ pub fn fallback_filter(query: &str) -> Result<RawCardFilter, String> {
|
||||
return Err(format!("Invalid query: {query}"));
|
||||
}
|
||||
let q = query.to_lowercase();
|
||||
Ok((Field::Name, Operator::Equals, Value::String(q)))
|
||||
Ok((Field::Name, Operator::Equal, Value::String(q)))
|
||||
}
|
||||
|
||||
pub fn build_filter(query: RawCardFilter) -> Result<CardFilter, String> {
|
||||
@ -60,11 +60,14 @@ pub fn build_filter(query: RawCardFilter) -> Result<CardFilter, String> {
|
||||
Box::new(move |card| card.def.is_none() && card.link_rating.is_none() && card.card_type.contains("monster"))
|
||||
}
|
||||
(Field::Level, op, Value::Numerical(n)) => Box::new(move |card| op.filter_number(card.level, n)),
|
||||
(Field::Type, Operator::Equals, Value::String(s)) => Box::new(move |card| card.r#type == s),
|
||||
(Field::Attribute, Operator::Equals, Value::String(s)) => Box::new(move |card| card.attribute.contains(&s)),
|
||||
(Field::Class, Operator::Equals, Value::String(s)) => Box::new(move |card| card.card_type.contains(&s)),
|
||||
(Field::Text, Operator::Equals, Value::String(s)) => Box::new(move |card| card.text.contains(&s)),
|
||||
(Field::Name, Operator::Equals, Value::String(s)) => Box::new(move |card| card.name.contains(&s)),
|
||||
(Field::Type, Operator::Equal, Value::String(s)) => Box::new(move |card| card.r#type == s),
|
||||
(Field::Type, Operator::NotEqual, Value::String(s)) => Box::new(move |card| card.r#type != s),
|
||||
(Field::Attribute, Operator::Equal, Value::String(s)) => Box::new(move |card| card.attribute.contains(&s)),
|
||||
(Field::Attribute, Operator::NotEqual, Value::String(s)) => Box::new(move |card| !card.attribute.contains(&s)),
|
||||
(Field::Class, Operator::Equal, Value::String(s)) => Box::new(move |card| card.card_type.contains(&s)),
|
||||
(Field::Class, Operator::NotEqual, Value::String(s)) => Box::new(move |card| !card.card_type.contains(&s)),
|
||||
(Field::Text, Operator::Equal, Value::String(s)) => Box::new(move |card| card.text.contains(&s)),
|
||||
(Field::Name, Operator::Equal, Value::String(s)) => Box::new(move |card| card.name.contains(&s)),
|
||||
q => Err(format!("unknown query: {q:?}"))?,
|
||||
})
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ fn field(input: &str) -> IResult<&str, Field> {
|
||||
map_res(take_while(char::is_alphabetic), str::parse)(input)
|
||||
}
|
||||
|
||||
pub const OPERATOR_CHARS: &[char] = &['=', '<', '>', ':'];
|
||||
pub const OPERATOR_CHARS: &[char] = &['=', '<', '>', ':', '!'];
|
||||
|
||||
fn operator(input: &str) -> IResult<&str, Operator> {
|
||||
map_res(take_while_m_n(1, 2, |c| OPERATOR_CHARS.contains(&c)), str::parse)(input)
|
||||
@ -84,7 +84,8 @@ impl FromStr for Field {
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum Operator {
|
||||
Equals,
|
||||
Equal,
|
||||
NotEqual,
|
||||
Less,
|
||||
LessEqual,
|
||||
Greater,
|
||||
@ -95,14 +96,15 @@ impl Operator {
|
||||
pub fn filter_number(&self, a: Option<i32>, b: i32) -> bool {
|
||||
if let Some(a) = a {
|
||||
match self {
|
||||
Self::Equals => a == b,
|
||||
Self::Equal => a == b,
|
||||
Self::Less => a < b,
|
||||
Self::LessEqual => a <= b,
|
||||
Self::Greater => a > b,
|
||||
Self::GreaterEqual => a >= b,
|
||||
Self::NotEqual => a != b,
|
||||
}
|
||||
} else {
|
||||
false
|
||||
self == &Self::NotEqual
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -111,11 +113,12 @@ impl FromStr for Operator {
|
||||
type Err = String;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
"=" | "==" | ":" => Self::Equals,
|
||||
"=" | "==" | ":" => Self::Equal,
|
||||
">=" | "=>" => Self::GreaterEqual,
|
||||
"<=" | "=<" => Self::LessEqual,
|
||||
">" => Self::Greater,
|
||||
"<" => Self::Less,
|
||||
"!=" => Self::NotEqual,
|
||||
_ => Err(s.to_owned())?,
|
||||
})
|
||||
}
|
||||
@ -132,13 +135,14 @@ mod tests {
|
||||
use super::*;
|
||||
use test_case::test_case;
|
||||
|
||||
#[test_case("t=pyro" => Ok(("", (Field::Type, Operator::Equals, Value::String("pyro".into())))))]
|
||||
#[test_case("t:PYro" => Ok(("", (Field::Type, Operator::Equals, Value::String("pyro".into())))); "input is lowercased")]
|
||||
#[test_case("t==warrior" => Ok(("", (Field::Type, Operator::Equals, Value::String("warrior".into())))))]
|
||||
#[test_case("t=pyro" => Ok(("", (Field::Type, Operator::Equal, Value::String("pyro".into())))))]
|
||||
#[test_case("t:PYro" => Ok(("", (Field::Type, Operator::Equal, Value::String("pyro".into())))); "input is lowercased")]
|
||||
#[test_case("t==warrior" => Ok(("", (Field::Type, Operator::Equal, Value::String("warrior".into())))))]
|
||||
#[test_case("atk>=100" => Ok(("", (Field::Atk, Operator::GreaterEqual, Value::Numerical(100)))))]
|
||||
#[test_case("Necrovalley" => Ok(("", (Field::Name, Operator::Equals, Value::String("necrovalley".into())))))]
|
||||
#[test_case("l=10" => Ok(("", (Field::Level, Operator::Equals, Value::Numerical(10)))))]
|
||||
#[test_case("Ib" => Ok(("", (Field::Name, Operator::Equals, Value::String("ib".to_owned())))))]
|
||||
#[test_case("Necrovalley" => Ok(("", (Field::Name, Operator::Equal, Value::String("necrovalley".into())))))]
|
||||
#[test_case("l=10" => Ok(("", (Field::Level, Operator::Equal, Value::Numerical(10)))))]
|
||||
#[test_case("Ib" => Ok(("", (Field::Name, Operator::Equal, Value::String("ib".to_owned())))))]
|
||||
#[test_case("c!=synchro" => Ok(("", (Field::Class, Operator::NotEqual, Value::String("synchro".to_owned())))))]
|
||||
fn successful_parsing_test(input: &str) -> IResult<&str, RawCardFilter> {
|
||||
parse_raw_filter(input)
|
||||
}
|
||||
@ -156,13 +160,13 @@ mod tests {
|
||||
fn sequential_parsing_test() {
|
||||
let (rest, filter) = parse_raw_filter("atk>=100 l:4").unwrap();
|
||||
assert_eq!(filter, (Field::Atk, Operator::GreaterEqual, Value::Numerical(100)));
|
||||
assert_eq!(parse_raw_filter(rest), Ok(("", (Field::Level, Operator::Equals, Value::Numerical(4)))));
|
||||
assert_eq!(parse_raw_filter(rest), Ok(("", (Field::Level, Operator::Equal, Value::Numerical(4)))));
|
||||
|
||||
assert_eq!(
|
||||
parse_raw_filters("atk>=100 l=4"),
|
||||
Ok((
|
||||
"",
|
||||
vec![(Field::Atk, Operator::GreaterEqual, Value::Numerical(100)), (Field::Level, Operator::Equals, Value::Numerical(4))]
|
||||
vec![(Field::Atk, Operator::GreaterEqual, Value::Numerical(100)), (Field::Level, Operator::Equal, Value::Numerical(4))]
|
||||
))
|
||||
);
|
||||
|
||||
@ -171,9 +175,9 @@ mod tests {
|
||||
Ok((
|
||||
"",
|
||||
vec![
|
||||
(Field::Type, Operator::Equals, Value::String("counter".into())),
|
||||
(Field::Class, Operator::Equals, Value::String("trap".into())),
|
||||
(Field::Text, Operator::Equals, Value::String("negate the summon".into())),
|
||||
(Field::Type, Operator::Equal, Value::String("counter".into())),
|
||||
(Field::Class, Operator::Equal, Value::String("trap".into())),
|
||||
(Field::Text, Operator::Equal, Value::String("negate the summon".into())),
|
||||
]
|
||||
))
|
||||
);
|
||||
@ -183,6 +187,6 @@ mod tests {
|
||||
fn quoted_value_test() {
|
||||
let (rest, filter) = parse_raw_filter(r#"o:"destroy that target""#).unwrap();
|
||||
assert_eq!(rest, "");
|
||||
assert_eq!(filter, (Field::Text, Operator::Equals, Value::String("destroy that target".into())));
|
||||
assert_eq!(filter, (Field::Text, Operator::Equal, Value::String("destroy that target".into())));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user