Refactor, optimization, and cleanup of code (#71)

This commit is contained in:
Finn Bear 2022-08-28 18:47:33 -07:00 committed by GitHub
parent 42d8260966
commit b18b3cef3e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 66 additions and 84 deletions

View file

@ -6,6 +6,7 @@ use crate::sql::uuid::Uuid;
use crate::sql::value::Value; use crate::sql::value::Value;
use nanoid::nanoid; use nanoid::nanoid;
use rand::distributions::Alphanumeric; use rand::distributions::Alphanumeric;
use rand::prelude::IteratorRandom;
use rand::Rng; use rand::Rng;
pub fn rand(_: &Context, _: Vec<Value>) -> Result<Value, Error> { pub fn rand(_: &Context, _: Vec<Value>) -> Result<Value, Error> {
@ -17,23 +18,14 @@ pub fn bool(_: &Context, _: Vec<Value>) -> Result<Value, Error> {
} }
pub fn r#enum(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn r#enum(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
match args.len() { Ok(match args.len() {
0 => Ok(Value::None), 0 => Value::None,
1 => match args.remove(0) { 1 => match args.remove(0) {
Value::Array(mut v) => match v.len() { Value::Array(v) => v.into_iter().choose(&mut rand::thread_rng()).unwrap_or(Value::None),
0 => Ok(Value::None), v => v,
n => {
let i = rand::thread_rng().gen_range(0..n);
Ok(v.remove(i))
}
},
v => Ok(v),
}, },
n => { _ => args.into_iter().choose(&mut rand::thread_rng()).unwrap(),
let i = rand::thread_rng().gen_range(0..n); })
Ok(args.remove(i))
}
}
} }
pub fn float(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn float(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {

View file

@ -7,16 +7,18 @@ pub fn concat(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
Ok(args.into_iter().map(|x| x.as_string()).collect::<Vec<_>>().concat().into()) Ok(args.into_iter().map(|x| x.as_string()).collect::<Vec<_>>().concat().into())
} }
pub fn ends_with(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn ends_with(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let args: [Value; 2] = args.try_into().unwrap();
let chr = args.remove(0).as_string(); let [val, chr] = args.map(Value::as_string);
Ok(val.ends_with(&chr).into()) Ok(val.ends_with(&chr).into())
} }
pub fn join(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn join(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let chr = args.remove(0).as_string(); let mut args = args.into_iter().map(Value::as_string);
let val = args.into_iter().map(|x| x.as_string()); let chr = args.next().unwrap();
let val = val.collect::<Vec<_>>().join(&chr); // FIXME: Use intersperse to avoid intermediate allocation once stable
// https://github.com/rust-lang/rust/issues/79524
let val = args.collect::<Vec<_>>().join(&chr);
Ok(val.into()) Ok(val.into())
} }
@ -30,16 +32,16 @@ pub fn lowercase(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
Ok(args.remove(0).as_string().to_lowercase().into()) Ok(args.remove(0).as_string().to_lowercase().into())
} }
pub fn repeat(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn repeat(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let [val_arg, num_arg]: [Value; 2] = args.try_into().unwrap();
let num = args.remove(0).as_int() as usize; let val = val_arg.as_string();
let num = num_arg.as_int() as usize;
Ok(val.repeat(num).into()) Ok(val.repeat(num).into())
} }
pub fn replace(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn replace(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let args: [Value; 3] = args.try_into().unwrap();
let old = args.remove(0).as_string(); let [val, old, new] = args.map(Value::as_string);
let new = args.remove(0).as_string();
Ok(val.replace(&old, &new).into()) Ok(val.replace(&old, &new).into())
} }
@ -47,10 +49,11 @@ pub fn reverse(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
Ok(args.remove(0).as_string().chars().rev().collect::<String>().into()) Ok(args.remove(0).as_string().chars().rev().collect::<String>().into())
} }
pub fn slice(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn slice(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let [val_arg, beg_arg, lim_arg]: [Value; 3] = args.try_into().unwrap();
let beg = args.remove(0).as_int() as usize; let val = val_arg.as_string();
let lim = args.remove(0).as_int() as usize; let beg = beg_arg.as_int() as usize;
let lim = lim_arg.as_int() as usize;
let val = val.chars().skip(beg).take(lim).collect::<String>(); let val = val.chars().skip(beg).take(lim).collect::<String>();
Ok(val.into()) Ok(val.into())
} }
@ -59,16 +62,16 @@ pub fn slug(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> {
Ok(string::slug(&args.remove(0).as_string()).into()) Ok(string::slug(&args.remove(0).as_string()).into())
} }
pub fn split(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn split(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let args: [Value; 2] = args.try_into().unwrap();
let chr = args.remove(0).as_string(); let [val, chr] = args.map(Value::as_string);
let val = val.split(&chr).collect::<Vec<&str>>(); let val = val.split(&chr).collect::<Vec<&str>>();
Ok(val.into()) Ok(val.into())
} }
pub fn starts_with(_: &Context, mut args: Vec<Value>) -> Result<Value, Error> { pub fn starts_with(_: &Context, args: Vec<Value>) -> Result<Value, Error> {
let val = args.remove(0).as_string(); let args: [Value; 2] = args.try_into().unwrap();
let chr = args.remove(0).as_string(); let [val, chr] = args.map(Value::as_string);
Ok(val.starts_with(&chr).into()) Ok(val.starts_with(&chr).into())
} }

View file

@ -9,9 +9,9 @@ pub fn slug<S: AsRef<str>>(s: S) -> String {
// Get a reference // Get a reference
let s = s.as_ref(); let s = s.as_ref();
// Convert unicode to ascii // Convert unicode to ascii
let s = deunicode(s); let mut s = deunicode(s);
// Convert string to lowercase // Convert string to lowercase
let s = s.to_ascii_lowercase(); s.make_ascii_lowercase();
// Replace any non-simple characters // Replace any non-simple characters
let s = SIMPLES.replace_all(s.as_ref(), "-"); let s = SIMPLES.replace_all(s.as_ref(), "-");
// Replace any duplicated hyphens // Replace any duplicated hyphens

View file

@ -206,22 +206,14 @@ impl<T> Abolish<T> for Vec<T> {
where where
F: FnMut(usize) -> bool, F: FnMut(usize) -> bool,
{ {
let len = self.len(); let mut i = 0;
let mut del = 0; // FIXME: use drain_filter once stabilized (https://github.com/rust-lang/rust/issues/43244)
{ // to avoid negation of the predicate return value.
let v = &mut **self; self.retain(|_| {
let retain = !f(i);
for i in 0..len { i += 1;
if f(i) { retain
del += 1; });
} else if del > 0 {
v.swap(i - del, i);
}
}
}
if del > 0 {
self.truncate(len - del);
}
} }
} }

View file

@ -30,10 +30,7 @@ impl From<time::Duration> for Duration {
impl From<String> for Duration { impl From<String> for Duration {
fn from(s: String) -> Self { fn from(s: String) -> Self {
match duration(s.as_ref()) { s.as_str().into()
Ok((_, v)) => v,
Err(_) => Duration::default(),
}
} }
} }
@ -64,6 +61,12 @@ impl fmt::Display for Duration {
// Split up the duration // Split up the duration
let secs = self.0.as_secs(); let secs = self.0.as_secs();
let nano = self.0.subsec_nanos(); let nano = self.0.subsec_nanos();
// Ensure no empty output
if secs == 0 && nano == 0 {
return write!(f, "0ns");
}
// Calculate the total years // Calculate the total years
let year = secs / SECONDS_PER_YEAR; let year = secs / SECONDS_PER_YEAR;
let secs = secs % SECONDS_PER_YEAR; let secs = secs % SECONDS_PER_YEAR;
@ -79,36 +82,29 @@ impl fmt::Display for Duration {
// Calculate the total mins // Calculate the total mins
let mins = secs / SECONDS_PER_MINUTE; let mins = secs / SECONDS_PER_MINUTE;
let secs = secs % SECONDS_PER_MINUTE; let secs = secs % SECONDS_PER_MINUTE;
// Prepare the outpit
let mut o = Vec::with_capacity(7);
// Write the different parts // Write the different parts
if year > 0 { if year > 0 {
o.push(format!("{year}y")); write!(f, "{year}y")?;
} }
if week > 0 { if week > 0 {
o.push(format!("{week}w")); write!(f, "{week}w")?;
} }
if days > 0 { if days > 0 {
o.push(format!("{days}d")); write!(f, "{days}d")?;
} }
if hour > 0 { if hour > 0 {
o.push(format!("{hour}h")); write!(f, "{hour}h")?;
} }
if mins > 0 { if mins > 0 {
o.push(format!("{mins}m")); write!(f, "{mins}m")?;
} }
if secs > 0 { if secs > 0 {
o.push(format!("{secs}s")); write!(f, "{secs}s")?;
} }
if nano > 0 { if nano > 0 {
o.push(format!("{nano}ns")); write!(f, "{nano}ns")?;
} }
// Ensure no empty output Ok(())
if o.is_empty() {
o.push("0ns".to_string());
}
// Concatenate together
write!(f, "{}", o.concat())
} }
} }

View file

@ -32,10 +32,7 @@ impl fmt::Display for Regex {
impl Regex { impl Regex {
pub fn regex(&self) -> Option<regex::Regex> { pub fn regex(&self) -> Option<regex::Regex> {
match regex::Regex::new(&self.0) { regex::Regex::new(&self.0).ok()
Ok(v) => Some(v),
Err(_) => None,
}
} }
} }

View file

@ -8,7 +8,7 @@ use crate::sql::part::Part;
use crate::sql::value::Value; use crate::sql::value::Value;
use async_recursion::async_recursion; use async_recursion::async_recursion;
use futures::future::try_join_all; use futures::future::try_join_all;
use std::collections::HashMap; use std::collections::HashSet;
impl Value { impl Value {
#[cfg_attr(feature = "parallel", async_recursion)] #[cfg_attr(feature = "parallel", async_recursion)]
@ -91,13 +91,15 @@ impl Value {
}, },
Part::Where(w) => match path.len() { Part::Where(w) => match path.len() {
1 => { 1 => {
let mut m = HashMap::new(); // TODO: If further optimization is desired, push indices to a vec,
// iterate in reverse, and call swap_remove
let mut m = HashSet::new();
for (i, v) in v.iter().enumerate() { for (i, v) in v.iter().enumerate() {
if w.compute(ctx, opt, txn, Some(v)).await?.is_truthy() { if w.compute(ctx, opt, txn, Some(v)).await?.is_truthy() {
m.insert(i, ()); m.insert(i);
}; };
} }
v.abolish(|i| m.contains_key(&i)); v.abolish(|i| m.contains(&i));
Ok(()) Ok(())
} }
_ => { _ => {