Refactor and optimize functions and Value operators (#80)

This commit is contained in:
Finn Bear 2022-08-31 17:27:52 -07:00 committed by GitHub
parent 5ca3b74e59
commit 8f6d21c1fc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 55 additions and 160 deletions

View file

@ -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

View file

@ -18,10 +18,7 @@ pub fn run(_: &Context, name: &str, val: Value) -> Result<Value, Error> {
}
pub fn bool(val: Value) -> Result<Value, Error> {
match val.is_truthy() {
true => Ok(Value::True),
false => Ok(Value::False),
}
Ok(val.is_truthy().into())
}
pub fn int(val: Value) -> Result<Value, Error> {

View file

@ -6,10 +6,7 @@ pub fn count(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
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!(),

View file

@ -22,7 +22,7 @@ pub fn alpha(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
}
pub fn ascii(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
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<Value>) -> Result<Value, Error> {
@ -30,30 +30,13 @@ pub fn domain(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
}
pub fn email(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
// 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<Value>) -> Result<Value, Error> {

View file

@ -6,17 +6,17 @@ use std::ops::Mul;
use std::ops::Sub;
pub fn or(a: Value, b: Value) -> Result<Value, Error> {
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<Value, Error> {
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<Value, Error> {
@ -40,171 +40,99 @@ pub fn exact(a: &Value, b: &Value) -> Result<Value, Error> {
}
pub fn equal(a: &Value, b: &Value) -> Result<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
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<Value, Error> {
match a.intersects(b) {
true => Ok(Value::True),
false => Ok(Value::False),
}
Ok(a.intersects(b).into())
}
#[cfg(test)]

View file

@ -49,7 +49,7 @@ impl From<i32> for Number {
impl From<i64> for Number {
fn from(i: i64) -> Self {
Number::Int(i as i64)
Number::Int(i)
}
}

View file

@ -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,
}
}

View file

@ -137,6 +137,7 @@ impl Default for Value {
}
impl From<bool> 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,
}