refactor
This commit is contained in:
parent
b28b4a4e04
commit
d1419a2198
1 changed files with 30 additions and 43 deletions
73
src/lib.rs
73
src/lib.rs
|
@ -37,7 +37,7 @@ fn greater_than_num(a: &serde_json::Value, b: &serde_json::Value) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
/// Represents errors that can occur while processing filters.
|
||||
pub enum FilterError {
|
||||
/// Indicates that the schema of the filter is invalid.
|
||||
|
@ -94,9 +94,8 @@ pub fn try_matches(
|
|||
.map(|sub_filter| matches(sub_filter, obj))
|
||||
.collect();
|
||||
return Ok(!and_list_bool.iter().any(|x| !x));
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
"$or" => {
|
||||
if let serde_json::Value::Array(or_list) = op_arg {
|
||||
|
@ -105,9 +104,8 @@ pub fn try_matches(
|
|||
.map(|sub_filter| matches(sub_filter, obj))
|
||||
.collect();
|
||||
return Ok(or_list_bool.iter().any(|x| *x));
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
_ => {
|
||||
if op.starts_with('$') {
|
||||
|
@ -117,34 +115,40 @@ pub fn try_matches(
|
|||
}
|
||||
}
|
||||
|
||||
let mut conditions = vec![];
|
||||
|
||||
for (key, val) in filter {
|
||||
if val.is_object() {
|
||||
let val_keys: Vec<_> = val.as_object().unwrap().keys().collect();
|
||||
if val_keys.first().unwrap().starts_with('$') {
|
||||
return match_operator(val, obj, key.as_str());
|
||||
conditions.push(match_operator(val, obj, key.as_str()));
|
||||
} else {
|
||||
// nested
|
||||
for (_, _) in val.as_object().unwrap() {
|
||||
let new_filter = filter.get(key).unwrap();
|
||||
if let Some(val) = obj_map.get(key) {
|
||||
return try_matches(new_filter, val);
|
||||
conditions.push(try_matches(new_filter, val));
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(valb) = obj_map.get(key) {
|
||||
if val != valb {
|
||||
return Ok(false);
|
||||
conditions.push(Ok(false));
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(true)
|
||||
conditions.iter().find(|x| x.is_err()).map_or_else(
|
||||
|| Ok(!conditions.iter().map(|x| x.unwrap()).any(|x| !x)),
|
||||
|possible_error| *possible_error,
|
||||
)
|
||||
}
|
||||
|
||||
fn match_operator(
|
||||
|
@ -162,30 +166,26 @@ fn match_operator(
|
|||
"$lt" => {
|
||||
if let Some(a) = obj.get(key) {
|
||||
return Ok(less_than_num(a, op_arg));
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$lte" => {
|
||||
if let Some(a) = obj.get(key) {
|
||||
return Ok(less_than_num(a, op_arg) || a == op_arg);
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$gt" => {
|
||||
if let Some(valb) = obj.get(key) {
|
||||
return Ok(greater_than_num(valb, op_arg));
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$gte" => {
|
||||
if let Some(a) = obj.get(key) {
|
||||
return Ok(greater_than_num(a, op_arg) || a == op_arg);
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$not" => {
|
||||
if let Some(serde_json::Value::Object(inner)) = val.get("$not") {
|
||||
|
@ -193,46 +193,39 @@ fn match_operator(
|
|||
key: inner
|
||||
});
|
||||
return Ok(!try_matches(&new_filter, raw_obj)?);
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
"$ne" => {
|
||||
if let Some(valb) = obj.get(key) {
|
||||
return Ok(valb != op_arg);
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$in" => {
|
||||
if let Some(valb) = obj.get(key) {
|
||||
if let serde_json::Value::Array(list) = valb {
|
||||
return Ok(list.iter().any(|x| x == op_arg));
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$nin" => {
|
||||
if let Some(valb) = obj.get(key) {
|
||||
if let serde_json::Value::Array(list) = valb {
|
||||
return Ok(!list.iter().any(|x| x == op_arg));
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$exists" => {
|
||||
if let serde_json::Value::Bool(exists) = op_arg {
|
||||
let valb = obj.get(key).is_some();
|
||||
return Ok(*exists == valb);
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
"$size" => {
|
||||
if let Some(serde_json::Value::Array(list)) = obj.get(key) {
|
||||
|
@ -240,24 +233,20 @@ fn match_operator(
|
|||
if let serde_json::Value::Number(pref_size) = op_arg {
|
||||
let pref_size = pref_size.as_u64().unwrap();
|
||||
return Ok(pref_size == val_size);
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
"$regex" => {
|
||||
if let serde_json::Value::String(regex_pattern) = op_arg {
|
||||
if let Some(serde_json::Value::String(valb)) = obj.get(key) {
|
||||
let pattern = regex::Regex::new(regex_pattern).unwrap();
|
||||
return Ok(pattern.is_match(valb));
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
"$type" => {
|
||||
if let Some(valb) = obj.get(key) {
|
||||
|
@ -271,12 +260,10 @@ fn match_operator(
|
|||
"boolean" => valb.is_boolean(),
|
||||
_ => false,
|
||||
});
|
||||
} else {
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
} else {
|
||||
return Err(FilterError::KeyNotFound);
|
||||
return Err(FilterError::InvalidFilter);
|
||||
}
|
||||
return Err(FilterError::KeyNotFound);
|
||||
}
|
||||
_ => {
|
||||
if op.starts_with('$') {
|
||||
|
|
Loading…
Add table
Reference in a new issue