Add SQL array::slice function. (#1855)

This commit is contained in:
Finn Bear 2023-04-25 14:48:09 -07:00 committed by GitHub
parent e6b97ff8ff
commit 38016a0ee6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 0 deletions

View file

@ -143,6 +143,27 @@ pub fn reverse((mut array,): (Array,)) -> Result<Value, Error> {
Ok(array.into()) Ok(array.into())
} }
pub fn slice((array, beg, lim): (Array, Option<isize>, Option<isize>)) -> Result<Value, Error> {
let skip = match beg {
Some(v) if v < 0 => array.len().saturating_sub(v.unsigned_abs()),
Some(v) => v as usize,
None => 0,
};
let take = match lim {
Some(v) if v < 0 => array.len().saturating_sub(skip).saturating_sub(v.unsigned_abs()),
Some(v) => v as usize,
None => usize::MAX,
};
Ok(if skip > 0 || take < usize::MAX {
array.into_iter().skip(skip).take(take).collect::<Vec<_>>().into()
} else {
array
}
.into())
}
pub fn sort((mut array, order): (Array, Option<Value>)) -> Result<Value, Error> { pub fn sort((mut array, order): (Array, Option<Value>)) -> Result<Value, Error> {
match order { match order {
// If "asc", sort ascending // If "asc", sort ascending
@ -193,3 +214,29 @@ pub mod sort {
Ok(array.into()) Ok(array.into())
} }
} }
#[cfg(test)]
mod tests {
use super::slice;
use crate::sql::{Array, Value};
#[test]
fn array_slice() {
fn test(initial: &[u8], beg: Option<isize>, lim: Option<isize>, expected: &[u8]) {
let initial_values =
initial.iter().map(|n| Value::from(*n as i64)).collect::<Vec<_>>().into();
let expected_values: Array =
expected.iter().map(|n| Value::from(*n as i64)).collect::<Vec<_>>().into();
assert_eq!(slice((initial_values, beg, lim)).unwrap(), expected_values.into());
}
let array = &[b'a', b'b', b'c', b'd', b'e', b'f', b'g'];
test(array, None, None, array);
test(array, Some(2), None, &array[2..]);
test(array, Some(2), Some(3), &array[2..5]);
test(array, Some(2), Some(-1), &[b'c', b'd', b'e', b'f']);
test(array, Some(-2), None, &[b'f', b'g']);
test(array, Some(-4), Some(2), &[b'd', b'e']);
test(array, Some(-4), Some(-1), &[b'd', b'e', b'f']);
}
}

View file

@ -85,6 +85,7 @@ pub fn synchronous(ctx: &Context<'_>, name: &str, args: Vec<Value>) -> Result<Va
"array::push" => array::push, "array::push" => array::push,
"array::remove" => array::remove, "array::remove" => array::remove,
"array::reverse" => array::reverse, "array::reverse" => array::reverse,
"array::slice" => array::slice,
"array::sort" => array::sort, "array::sort" => array::sort,
"array::union" => array::union, "array::union" => array::union,
"array::sort::asc" => array::sort::asc, "array::sort::asc" => array::sort::asc,

View file

@ -358,6 +358,7 @@ fn function_array(i: &str) -> IResult<&str, &str> {
tag("push"), tag("push"),
tag("remove"), tag("remove"),
tag("reverse"), tag("reverse"),
tag("slice"),
tag("sort::asc"), tag("sort::asc"),
tag("sort::desc"), tag("sort::desc"),
tag("sort"), tag("sort"),