Refactor, optimization, and cleanup of code (#71)
This commit is contained in:
parent
42d8260966
commit
b18b3cef3e
7 changed files with 66 additions and 84 deletions
|
@ -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),
|
_ => args.into_iter().choose(&mut rand::thread_rng()).unwrap(),
|
||||||
},
|
})
|
||||||
n => {
|
|
||||||
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> {
|
||||||
|
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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(())
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
Loading…
Reference in a new issue