From 8f6d21c1fcd07da15d785141a86b0acf9f1b818e Mon Sep 17 00:00:00 2001 From: Finn Bear Date: Wed, 31 Aug 2022 17:27:52 -0700 Subject: [PATCH] Refactor and optimize functions and Value operators (#80) --- lib/src/dbs/iterate.rs | 8 --- lib/src/fnc/cast.rs | 5 +- lib/src/fnc/count.rs | 5 +- lib/src/fnc/is.rs | 33 +++------ lib/src/fnc/operate.rs | 136 +++++++++--------------------------- lib/src/sql/number.rs | 2 +- lib/src/sql/value/single.rs | 5 +- lib/src/sql/value/value.rs | 21 +++--- 8 files changed, 55 insertions(+), 160 deletions(-) diff --git a/lib/src/dbs/iterate.rs b/lib/src/dbs/iterate.rs index 712c4469..39b12116 100644 --- a/lib/src/dbs/iterate.rs +++ b/lib/src/dbs/iterate.rs @@ -107,10 +107,6 @@ impl Iterable { if !res.is_empty() { // Get total results let n = res.len(); - // Exit when settled - if n == 0 { - break; - } // Loop over results for (i, (k, v)) in res.into_iter().enumerate() { // Check the context @@ -167,10 +163,6 @@ impl Iterable { if !res.is_empty() { // Get total results let n = res.len(); - // Exit when settled - if n == 0 { - break; - } // Loop over results for (i, (k, v)) in res.into_iter().enumerate() { // Check the context diff --git a/lib/src/fnc/cast.rs b/lib/src/fnc/cast.rs index d8322799..9422a6f1 100644 --- a/lib/src/fnc/cast.rs +++ b/lib/src/fnc/cast.rs @@ -18,10 +18,7 @@ pub fn run(_: &Context, name: &str, val: Value) -> Result { } pub fn bool(val: Value) -> Result { - match val.is_truthy() { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(val.is_truthy().into()) } pub fn int(val: Value) -> Result { diff --git a/lib/src/fnc/count.rs b/lib/src/fnc/count.rs index e3a597af..b90b9011 100644 --- a/lib/src/fnc/count.rs +++ b/lib/src/fnc/count.rs @@ -6,10 +6,7 @@ pub fn count(_: &Context, mut args: Vec) -> Result { match args.len() { 1 => match args.remove(0) { Value::Array(v) => Ok(v.iter().filter(|v| v.is_truthy()).count().into()), - v => match v.is_truthy() { - true => Ok(1.into()), - false => Ok(0.into()), - }, + v => Ok((v.is_truthy() as i64).into()), }, 0 => Ok(1.into()), _ => unreachable!(), diff --git a/lib/src/fnc/is.rs b/lib/src/fnc/is.rs index 8fc927b8..290fb238 100644 --- a/lib/src/fnc/is.rs +++ b/lib/src/fnc/is.rs @@ -22,7 +22,7 @@ pub fn alpha(_: &Context, mut args: Vec) -> Result { } pub fn ascii(_: &Context, mut args: Vec) -> Result { - Ok(args.remove(0).as_string().chars().all(|x| char::is_ascii(&x)).into()) + Ok(args.remove(0).as_string().is_ascii().into()) } pub fn domain(_: &Context, mut args: Vec) -> Result { @@ -30,30 +30,13 @@ pub fn domain(_: &Context, mut args: Vec) -> Result { } pub fn email(_: &Context, mut args: Vec) -> Result { - // Convert to a String - let val = args.remove(0).as_string(); - // Convert to a &str - let val = val.as_str(); - // Check if value is empty - if val.is_empty() { - return Ok(Value::False); - } - // Ensure the value contains @ - if !val.contains('@') { - return Ok(Value::False); - } - // Reverse split the value by @ - let parts: Vec<&str> = val.rsplitn(2, '@').collect(); - // Check the first part matches - if !USER_RE.is_match(parts[1]) { - return Ok(Value::False); - } - // Check the second part matches - if !HOST_RE.is_match(parts[0]) { - return Ok(Value::False); - } - // The email is valid - Ok(Value::True) + Ok(args + .remove(0) + .as_string() + .rsplit_once('@') + .map(|(user, host)| USER_RE.is_match(user) && HOST_RE.is_match(host)) + .unwrap_or(false) + .into()) } pub fn hexadecimal(_: &Context, mut args: Vec) -> Result { diff --git a/lib/src/fnc/operate.rs b/lib/src/fnc/operate.rs index f10871a4..d86e2740 100644 --- a/lib/src/fnc/operate.rs +++ b/lib/src/fnc/operate.rs @@ -6,17 +6,17 @@ use std::ops::Mul; use std::ops::Sub; pub fn or(a: Value, b: Value) -> Result { - match a.is_truthy() { - true => Ok(a), - false => Ok(b), - } + Ok(match a.is_truthy() { + true => a, + false => b, + }) } pub fn and(a: Value, b: Value) -> Result { - match a.is_truthy() { - true => Ok(b), - false => Ok(a), - } + Ok(match a.is_truthy() { + true => b, + false => a, + }) } pub fn add(a: Value, b: Value) -> Result { @@ -40,171 +40,99 @@ pub fn exact(a: &Value, b: &Value) -> Result { } pub fn equal(a: &Value, b: &Value) -> Result { - match a.equal(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.equal(b).into()) } pub fn not_equal(a: &Value, b: &Value) -> Result { - match a.equal(b) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!a.equal(b)).into()) } pub fn all_equal(a: &Value, b: &Value) -> Result { - match a.all_equal(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.all_equal(b).into()) } pub fn any_equal(a: &Value, b: &Value) -> Result { - match a.any_equal(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.any_equal(b).into()) } pub fn like(a: &Value, b: &Value) -> Result { - match a.fuzzy(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.fuzzy(b).into()) } pub fn not_like(a: &Value, b: &Value) -> Result { - match a.fuzzy(b) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!a.fuzzy(b)).into()) } pub fn all_like(a: &Value, b: &Value) -> Result { - match a.all_fuzzy(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.all_fuzzy(b).into()) } pub fn any_like(a: &Value, b: &Value) -> Result { - match a.any_fuzzy(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.any_fuzzy(b).into()) } pub fn less_than(a: &Value, b: &Value) -> Result { - match a.lt(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.lt(b).into()) } pub fn less_than_or_equal(a: &Value, b: &Value) -> Result { - match a.le(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.le(b).into()) } pub fn more_than(a: &Value, b: &Value) -> Result { - match a.gt(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.gt(b).into()) } pub fn more_than_or_equal(a: &Value, b: &Value) -> Result { - match a.ge(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.ge(b).into()) } pub fn contain(a: &Value, b: &Value) -> Result { - match a.contains(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.contains(b).into()) } pub fn not_contain(a: &Value, b: &Value) -> Result { - match a.contains(b) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!a.contains(b)).into()) } pub fn contain_all(a: &Value, b: &Value) -> Result { - match a.contains_all(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.contains_all(b).into()) } pub fn contain_any(a: &Value, b: &Value) -> Result { - match a.contains_any(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.contains_any(b).into()) } pub fn contain_none(a: &Value, b: &Value) -> Result { - match a.contains_any(b) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!a.contains_any(b)).into()) } pub fn inside(a: &Value, b: &Value) -> Result { - match b.contains(a) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(b.contains(a).into()) } pub fn not_inside(a: &Value, b: &Value) -> Result { - match b.contains(a) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!b.contains(a)).into()) } pub fn inside_all(a: &Value, b: &Value) -> Result { - match b.contains_all(a) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(b.contains_all(a).into()) } pub fn inside_any(a: &Value, b: &Value) -> Result { - match b.contains_any(a) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(b.contains_any(a).into()) } pub fn inside_none(a: &Value, b: &Value) -> Result { - match b.contains_any(a) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!b.contains_any(a)).into()) } pub fn outside(a: &Value, b: &Value) -> Result { - match a.intersects(b) { - true => Ok(Value::False), - false => Ok(Value::True), - } + Ok((!a.intersects(b)).into()) } pub fn intersects(a: &Value, b: &Value) -> Result { - match a.intersects(b) { - true => Ok(Value::True), - false => Ok(Value::False), - } + Ok(a.intersects(b).into()) } #[cfg(test)] diff --git a/lib/src/sql/number.rs b/lib/src/sql/number.rs index d070cfb6..eb622016 100644 --- a/lib/src/sql/number.rs +++ b/lib/src/sql/number.rs @@ -49,7 +49,7 @@ impl From for Number { impl From for Number { fn from(i: i64) -> Self { - Number::Int(i as i64) + Number::Int(i) } } diff --git a/lib/src/sql/value/single.rs b/lib/src/sql/value/single.rs index 6f1c4d61..637726cc 100644 --- a/lib/src/sql/value/single.rs +++ b/lib/src/sql/value/single.rs @@ -3,10 +3,7 @@ use crate::sql::value::Value; impl Value { pub fn single(&self) -> &Self { match self { - Value::Array(v) => match v.first() { - None => &Value::None, - Some(v) => v, - }, + Value::Array(v) => v.first().unwrap_or(&Value::None), v => v, } } diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 945876a1..47cd9c5f 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -137,6 +137,7 @@ impl Default for Value { } impl From for Value { + #[inline] fn from(v: bool) -> Self { match v { true => Value::True, @@ -497,7 +498,7 @@ impl Value { pub fn is_true(&self) -> bool { match self { Value::True => true, - Value::Strand(v) => v.to_ascii_lowercase() == "true", + Value::Strand(v) => v.eq_ignore_ascii_case("true"), _ => false, } } @@ -505,7 +506,7 @@ impl Value { pub fn is_false(&self) -> bool { match self { Value::False => true, - Value::Strand(v) => v.to_ascii_lowercase() == "false", + Value::Strand(v) => v.eq_ignore_ascii_case("false"), _ => false, } } @@ -518,7 +519,7 @@ impl Value { Value::Geometry(_) => true, Value::Array(v) => !v.is_empty(), Value::Object(v) => !v.is_empty(), - Value::Strand(v) => !v.is_empty() && v.to_ascii_lowercase() != "false", + Value::Strand(v) => !v.is_empty() && !v.eq_ignore_ascii_case("false"), Value::Number(v) => v.is_truthy(), Value::Duration(v) => v.as_nanos() > 0, Value::Datetime(v) => v.timestamp() > 0, @@ -556,25 +557,25 @@ impl Value { pub fn is_type_geometry(&self, types: &[String]) -> bool { match self { Value::Geometry(Geometry::Point(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "point") + types.iter().any(|t| matches!(t.as_str(), "feature" | "point")) } Value::Geometry(Geometry::Line(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "line") + types.iter().any(|t| matches!(t.as_str(), "feature" | "line")) } Value::Geometry(Geometry::Polygon(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "polygon") + types.iter().any(|t| matches!(t.as_str(), "feature" | "polygon")) } Value::Geometry(Geometry::MultiPoint(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "multipoint") + types.iter().any(|t| matches!(t.as_str(), "feature" | "multipoint")) } Value::Geometry(Geometry::MultiLine(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "multiline") + types.iter().any(|t| matches!(t.as_str(), "feature" | "multiline")) } Value::Geometry(Geometry::MultiPolygon(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "multipolygon") + types.iter().any(|t| matches!(t.as_str(), "feature" | "multipolygon")) } Value::Geometry(Geometry::Collection(_)) => { - types.iter().any(|t| &t[..] == "feature" || &t[..] == "collection") + types.iter().any(|t| matches!(t.as_str(), "feature" | "collection")) } _ => false, }