2020-05-06 13:45:17 +02:00
|
|
|
#![cfg(not(feature = "no_index"))]
|
2020-08-14 12:58:34 +02:00
|
|
|
#![allow(non_snake_case)]
|
2020-05-06 13:45:17 +02:00
|
|
|
|
2021-03-23 05:13:53 +01:00
|
|
|
use crate::engine::OP_EQUALS;
|
2020-08-14 12:58:34 +02:00
|
|
|
use crate::plugin::*;
|
2021-02-23 09:06:36 +01:00
|
|
|
use crate::{def_package, Array, Dynamic, EvalAltResult, FnPtr, NativeCallContext, Position, INT};
|
2021-04-17 09:15:54 +02:00
|
|
|
#[cfg(feature = "no_std")]
|
|
|
|
use std::prelude::v1::*;
|
|
|
|
use std::{any::TypeId, cmp::Ordering, mem};
|
2020-08-14 12:58:34 +02:00
|
|
|
|
|
|
|
def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
2021-11-05 16:22:05 +01:00
|
|
|
lib.standard = true;
|
|
|
|
|
2020-09-21 10:15:52 +02:00
|
|
|
combine_with_exported_module!(lib, "array", array_functions);
|
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
// Register array iterator
|
2020-10-15 16:11:18 +02:00
|
|
|
lib.set_iterable::<Array>();
|
2020-08-14 12:58:34 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
#[export_module]
|
|
|
|
mod array_functions {
|
2021-02-19 16:13:53 +01:00
|
|
|
#[rhai_fn(name = "len", get = "len", pure)]
|
|
|
|
pub fn len(array: &mut Array) -> INT {
|
|
|
|
array.len() as INT
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
2021-02-23 09:06:36 +01:00
|
|
|
#[rhai_fn(name = "push", name = "+=")]
|
|
|
|
pub fn push(array: &mut Array, item: Dynamic) {
|
|
|
|
array.push(item);
|
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "append", name = "+=")]
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn append(array: &mut Array, y: Array) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !y.is_empty() {
|
|
|
|
if array.is_empty() {
|
|
|
|
*array = y;
|
|
|
|
} else {
|
|
|
|
array.extend(y);
|
|
|
|
}
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
2020-08-16 17:41:59 +02:00
|
|
|
#[rhai_fn(name = "+")]
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn concat(mut array: Array, y: Array) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !y.is_empty() {
|
|
|
|
if array.is_empty() {
|
|
|
|
array = y;
|
|
|
|
} else {
|
|
|
|
array.extend(y);
|
|
|
|
}
|
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
array
|
2020-08-16 17:41:59 +02:00
|
|
|
}
|
2021-02-23 09:06:36 +01:00
|
|
|
pub fn insert(array: &mut Array, position: INT, item: Dynamic) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
array.push(item);
|
|
|
|
} else if position < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
if let Some(n) = position.checked_abs() {
|
|
|
|
if n as usize > array.len() {
|
|
|
|
array.insert(0, item);
|
|
|
|
} else {
|
|
|
|
array.insert(array.len() - n as usize, item);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
array.insert(0, item);
|
|
|
|
}
|
2021-02-23 09:06:36 +01:00
|
|
|
} else if (position as usize) >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
array.push(item);
|
2021-02-23 09:06:36 +01:00
|
|
|
} else {
|
|
|
|
array.insert(position as usize, item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw)]
|
|
|
|
pub fn pad(
|
|
|
|
_ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
len: INT,
|
|
|
|
item: Dynamic,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if len <= 0 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2021-02-23 09:06:36 +01:00
|
|
|
// Check if array will be over max size limit
|
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2021-09-20 12:35:23 +02:00
|
|
|
if _ctx.engine().max_array_size() > 0 && (len as usize) > _ctx.engine().max_array_size() {
|
2021-10-19 17:52:58 +02:00
|
|
|
return Err(EvalAltResult::ErrorDataTooLarge(
|
|
|
|
"Size of array".to_string(),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into());
|
2021-02-23 09:06:36 +01:00
|
|
|
}
|
|
|
|
|
2021-09-20 12:35:23 +02:00
|
|
|
if len as usize > array.len() {
|
2021-02-23 09:06:36 +01:00
|
|
|
array.resize(len as usize, item);
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(())
|
2021-02-23 09:06:36 +01:00
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn pop(array: &mut Array) -> Dynamic {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
Dynamic::UNIT
|
|
|
|
} else {
|
|
|
|
array.pop().unwrap_or_else(|| Dynamic::UNIT)
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn shift(array: &mut Array) -> Dynamic {
|
|
|
|
if array.is_empty() {
|
2021-09-20 12:35:23 +02:00
|
|
|
Dynamic::UNIT
|
2020-08-14 12:58:34 +02:00
|
|
|
} else {
|
2021-02-19 16:13:53 +01:00
|
|
|
array.remove(0)
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn remove(array: &mut Array, len: INT) -> Dynamic {
|
|
|
|
if len < 0 || (len as usize) >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
Dynamic::UNIT
|
2020-08-14 12:58:34 +02:00
|
|
|
} else {
|
2021-02-19 16:13:53 +01:00
|
|
|
array.remove(len as usize)
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn clear(array: &mut Array) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !array.is_empty() {
|
|
|
|
array.clear();
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn truncate(array: &mut Array, len: INT) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !array.is_empty() {
|
|
|
|
if len >= 0 {
|
|
|
|
array.truncate(len as usize);
|
|
|
|
} else {
|
|
|
|
array.clear();
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn chop(array: &mut Array, len: INT) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !array.is_empty() && len as usize >= array.len() {
|
|
|
|
if len >= 0 {
|
|
|
|
array.drain(0..array.len() - len as usize);
|
|
|
|
} else {
|
|
|
|
array.clear();
|
|
|
|
}
|
2020-10-13 08:39:49 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn reverse(array: &mut Array) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if !array.is_empty() {
|
|
|
|
array.reverse();
|
|
|
|
}
|
2020-09-24 04:51:21 +02:00
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn splice(array: &mut Array, start: INT, len: INT, replace: Array) {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
*array = replace;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-10-13 04:57:29 +02:00
|
|
|
let start = if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-04-10 09:00:03 +02:00
|
|
|
array.extend(replace.into_iter());
|
|
|
|
return;
|
2020-10-13 04:57:29 +02:00
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
let len = if len < 0 {
|
|
|
|
0
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if len as usize > array.len() - start {
|
|
|
|
array.len() - start
|
2020-10-13 04:57:29 +02:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
2021-02-19 16:13:53 +01:00
|
|
|
array.splice(start..start + len, replace.into_iter());
|
2020-10-13 04:57:29 +02:00
|
|
|
}
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn extract(array: &mut Array, start: INT, len: INT) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() || len <= 0 {
|
|
|
|
return Array::new();
|
|
|
|
}
|
|
|
|
|
2020-10-13 08:39:49 +02:00
|
|
|
let start = if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
return Array::new();
|
2020-10-13 08:39:49 +02:00
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-09-20 12:35:23 +02:00
|
|
|
let len = if len <= 0 {
|
2020-10-13 08:39:49 +02:00
|
|
|
0
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if len as usize > array.len() - start {
|
|
|
|
array.len() - start
|
2020-10-13 08:39:49 +02:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
|
|
|
|
2021-09-20 12:35:23 +02:00
|
|
|
if len == 0 {
|
|
|
|
Array::new()
|
|
|
|
} else {
|
|
|
|
array[start..start + len].to_vec()
|
|
|
|
}
|
2020-10-13 08:39:49 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "extract")]
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn extract_tail(array: &mut Array, start: INT) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Array::new();
|
|
|
|
}
|
|
|
|
|
2020-10-13 08:39:49 +02:00
|
|
|
let start = if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
return Array::new();
|
2020-10-13 08:39:49 +02:00
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-07-24 08:11:16 +02:00
|
|
|
array[start..].to_vec()
|
2020-10-13 08:39:49 +02:00
|
|
|
}
|
2021-02-23 04:57:50 +01:00
|
|
|
#[rhai_fn(name = "split")]
|
|
|
|
pub fn split_at(array: &mut Array, start: INT) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
Array::new()
|
|
|
|
} else if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
if let Some(n) = start.checked_abs() {
|
|
|
|
if n as usize > array.len() {
|
|
|
|
mem::take(array)
|
|
|
|
} else {
|
2021-09-11 13:40:40 +02:00
|
|
|
let mut result = Array::new();
|
2021-04-10 09:00:03 +02:00
|
|
|
result.extend(array.drain(array.len() - n as usize..));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
mem::take(array)
|
|
|
|
}
|
2021-02-23 04:57:50 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
Array::new()
|
2021-02-23 04:57:50 +01:00
|
|
|
} else {
|
2021-09-11 13:40:40 +02:00
|
|
|
let mut result = Array::new();
|
2021-02-23 04:57:50 +01:00
|
|
|
result.extend(array.drain(start as usize..));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
2021-10-21 13:04:53 +02:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
|
|
|
pub fn map(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-10-21 13:04:53 +02:00
|
|
|
mapper: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
2021-11-23 15:37:18 +01:00
|
|
|
return Ok(array.clone());
|
2021-09-20 12:35:23 +02:00
|
|
|
}
|
|
|
|
|
2021-03-23 05:13:53 +01:00
|
|
|
let mut ar = Array::with_capacity(array.len());
|
2020-10-18 15:47:34 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate() {
|
|
|
|
ar.push(
|
|
|
|
mapper
|
|
|
|
.call_dynamic(&ctx, None, [item.clone()])
|
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
|
|
|
if fn_sig.starts_with(mapper.fn_name()) =>
|
|
|
|
{
|
|
|
|
mapper.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
2021-10-21 13:04:53 +02:00
|
|
|
"map".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
2021-11-23 15:37:18 +01:00
|
|
|
))
|
|
|
|
})?,
|
|
|
|
);
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(ar)
|
2020-10-18 07:18:12 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "map", return_raw, pure)]
|
|
|
|
pub fn map_with_fn_name(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
mapper: &str,
|
2021-10-20 05:06:38 +02:00
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
map(ctx, array, FnPtr::new(mapper)?)
|
2021-10-20 05:06:38 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
|
|
|
|
#[rhai_fn(return_raw, pure)]
|
|
|
|
pub fn filter(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(array.clone());
|
|
|
|
}
|
|
|
|
|
2021-03-23 05:13:53 +01:00
|
|
|
let mut ar = Array::new();
|
2021-10-19 13:57:15 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate() {
|
|
|
|
if filter
|
|
|
|
.call_dynamic(&ctx, None, [item.clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-10-18 15:47:34 +02:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"filter".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
|
|
|
ar.push(item.clone());
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(ar)
|
2020-06-15 16:04:14 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "filter", return_raw, pure)]
|
|
|
|
pub fn filter_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
filter_func: &str,
|
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
|
|
|
filter(ctx, array, FnPtr::new(filter_func)?)
|
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
|
|
|
pub fn contains(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-03-09 06:44:54 +01:00
|
|
|
value: Dynamic,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
|
2021-03-09 06:44:54 +01:00
|
|
|
for item in array.iter_mut() {
|
2021-03-09 06:16:05 +01:00
|
|
|
if ctx
|
2021-10-19 13:57:15 +02:00
|
|
|
.call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()])
|
2021-03-09 06:16:05 +01:00
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
|
|
|
if fn_sig.starts_with(OP_EQUALS) =>
|
|
|
|
{
|
|
|
|
if item.type_id() == value.type_id() {
|
|
|
|
// No default when comparing same type
|
|
|
|
Err(err)
|
|
|
|
} else {
|
|
|
|
Ok(Dynamic::FALSE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(true);
|
2021-03-09 06:16:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(false)
|
2021-03-09 06:16:05 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(return_raw, pure)]
|
2020-11-08 16:00:37 +01:00
|
|
|
pub fn index_of(
|
2021-03-09 06:16:05 +01:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-03-09 06:44:54 +01:00
|
|
|
value: Dynamic,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
Ok(-1)
|
|
|
|
} else {
|
|
|
|
index_of_starting_from(ctx, array, value, 0)
|
|
|
|
}
|
2021-04-10 09:00:03 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
|
|
|
pub fn index_of_starting_from(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
value: Dynamic,
|
|
|
|
start: INT,
|
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(-1);
|
|
|
|
}
|
|
|
|
|
2021-04-10 09:00:03 +02:00
|
|
|
let start = if start < 0 {
|
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
|
|
|
} else if start as usize >= array.len() {
|
|
|
|
return Ok(-1);
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
|
|
|
for (i, item) in array.iter_mut().enumerate().skip(start) {
|
2021-03-09 06:16:05 +01:00
|
|
|
if ctx
|
2021-10-19 13:57:15 +02:00
|
|
|
.call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()])
|
2021-03-09 06:16:05 +01:00
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
|
|
|
if fn_sig.starts_with(OP_EQUALS) =>
|
|
|
|
{
|
|
|
|
if item.type_id() == value.type_id() {
|
|
|
|
// No default when comparing same type
|
|
|
|
Err(err)
|
|
|
|
} else {
|
|
|
|
Ok(Dynamic::FALSE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(i as INT);
|
2021-03-09 06:16:05 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(-1 as INT)
|
2021-03-09 06:16:05 +01:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
2021-10-20 05:06:38 +02:00
|
|
|
pub fn index_of_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
filter: &str,
|
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
|
|
|
index_of_filter(ctx, array, FnPtr::new(filter)?)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
2021-03-09 06:16:05 +01:00
|
|
|
pub fn index_of_filter(
|
2020-11-08 16:00:37 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-11-08 16:00:37 +01:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
Ok(-1)
|
|
|
|
} else {
|
|
|
|
index_of_filter_starting_from(ctx, array, filter, 0)
|
|
|
|
}
|
2021-04-10 09:00:03 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
2021-10-21 13:04:53 +02:00
|
|
|
pub fn index_of_filter_starting_from(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-10-21 13:04:53 +02:00
|
|
|
filter: FnPtr,
|
2021-10-20 05:06:38 +02:00
|
|
|
start: INT,
|
2021-04-10 09:00:03 +02:00
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(-1);
|
|
|
|
}
|
|
|
|
|
2021-04-10 09:00:03 +02:00
|
|
|
let start = if start < 0 {
|
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
|
|
|
} else if start as usize >= array.len() {
|
|
|
|
return Ok(-1);
|
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate().skip(start) {
|
|
|
|
if filter
|
|
|
|
.call_dynamic(&ctx, None, [item.clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-11-08 16:00:37 +01:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-11-08 16:00:37 +01:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"index_of".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(i as INT);
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(-1 as INT)
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "index_of", return_raw, pure)]
|
|
|
|
pub fn index_of_with_fn_name_filter_starting_from(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
filter: &str,
|
|
|
|
start: INT,
|
|
|
|
) -> Result<INT, Box<EvalAltResult>> {
|
|
|
|
index_of_filter_starting_from(ctx, array, FnPtr::new(filter)?, start)
|
2021-10-20 05:06:38 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
|
|
|
pub fn some(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(false);
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate() {
|
|
|
|
if filter
|
|
|
|
.call_dynamic(&ctx, None, [item.clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-10-18 15:47:34 +02:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"some".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(true);
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2020-06-30 12:34:32 +02:00
|
|
|
}
|
2020-10-12 16:49:51 +02:00
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(false)
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "some", return_raw, pure)]
|
|
|
|
pub fn some_with_fn_name(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
filter: &str,
|
2021-10-20 05:06:38 +02:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
some(ctx, array, FnPtr::new(filter)?)
|
2021-10-20 05:06:38 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
|
|
|
pub fn all(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2021-11-23 15:37:18 +01:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(true);
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate() {
|
|
|
|
if !filter
|
|
|
|
.call_dynamic(&ctx, None, [item.clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-10-18 15:47:34 +02:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"all".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(false);
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2020-10-12 16:49:51 +02:00
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(true)
|
2020-10-13 04:57:29 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "all", return_raw, pure)]
|
|
|
|
pub fn all_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
filter: &str,
|
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
|
|
|
all(ctx, array, FnPtr::new(filter)?)
|
|
|
|
}
|
2021-10-21 11:59:54 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
|
|
|
pub fn dedup(ctx: NativeCallContext, array: &mut Array) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
dedup_with_fn_name(ctx, array, OP_EQUALS)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "dedup", return_raw)]
|
|
|
|
pub fn dedup_by_comparer(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
comparer: FnPtr,
|
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
array.dedup_by(|x, y| {
|
2021-11-23 15:37:18 +01:00
|
|
|
comparer
|
|
|
|
.call_dynamic(&ctx, None, [x.clone(), y.clone()])
|
2021-10-21 11:59:54 +02:00
|
|
|
.unwrap_or_else(|_| Dynamic::FALSE)
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
});
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "dedup", return_raw)]
|
|
|
|
fn dedup_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
comparer: &str,
|
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
dedup_by_comparer(ctx, array, FnPtr::new(comparer)?)
|
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
2020-10-18 15:47:34 +02:00
|
|
|
pub fn reduce(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-10-18 15:47:34 +02:00
|
|
|
reducer: FnPtr,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
reduce_with_initial(ctx, array, reducer, Dynamic::UNIT)
|
2020-10-12 16:49:51 +02:00
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(name = "reduce", return_raw, pure)]
|
2021-10-21 13:04:53 +02:00
|
|
|
pub fn reduce_with_fn_name(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
reducer: &str,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
reduce(ctx, array, FnPtr::new(reducer)?)
|
2021-10-20 05:06:38 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "reduce", return_raw, pure)]
|
2020-10-18 15:47:34 +02:00
|
|
|
pub fn reduce_with_initial(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-10-18 15:47:34 +02:00
|
|
|
reducer: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
initial: Dynamic,
|
2020-10-18 15:47:34 +02:00
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(initial);
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
let mut result = initial;
|
2020-10-18 15:47:34 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate() {
|
|
|
|
let item = item.clone();
|
2021-10-21 13:04:53 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
result = reducer
|
|
|
|
.call_dynamic(&ctx, None, [result.clone(), item.clone()])
|
2020-10-18 15:47:34 +02:00
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(reducer.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
reducer.call_dynamic(&ctx, None, [result, item, (i as INT).into()])
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"reduce".to_string(),
|
2020-12-30 14:12:51 +01:00
|
|
|
ctx.source().unwrap_or("").to_string(),
|
2020-10-18 15:47:34 +02:00
|
|
|
err,
|
2020-11-20 09:52:28 +01:00
|
|
|
Position::NONE,
|
2020-10-18 15:47:34 +02:00
|
|
|
))
|
|
|
|
})?;
|
|
|
|
}
|
2020-10-12 16:49:51 +02:00
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
Ok(result)
|
2020-10-14 15:27:31 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "reduce", return_raw, pure)]
|
|
|
|
pub fn reduce_with_fn_name_with_initial(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
reducer: &str,
|
|
|
|
initial: Dynamic,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
|
|
reduce_with_initial(ctx, array, FnPtr::new(reducer)?, initial)
|
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(return_raw, pure)]
|
2020-10-18 15:47:34 +02:00
|
|
|
pub fn reduce_rev(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-10-18 15:47:34 +02:00
|
|
|
reducer: FnPtr,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
reduce_rev_with_initial(ctx, array, reducer, Dynamic::UNIT)
|
2020-10-14 15:27:31 +02:00
|
|
|
}
|
2021-10-21 13:04:53 +02:00
|
|
|
#[rhai_fn(name = "reduce_rev", return_raw, pure)]
|
|
|
|
pub fn reduce_rev_with_fn_name(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
reducer: &str,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-11-23 15:37:18 +01:00
|
|
|
reduce_rev(ctx, array, FnPtr::new(reducer)?)
|
2021-10-20 05:06:38 +02:00
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(name = "reduce_rev", return_raw, pure)]
|
2020-10-18 15:47:34 +02:00
|
|
|
pub fn reduce_rev_with_initial(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-10-18 15:47:34 +02:00
|
|
|
reducer: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
initial: Dynamic,
|
2020-10-18 15:47:34 +02:00
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(initial);
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
let mut result = initial;
|
2021-10-21 13:04:53 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
for (i, item) in array.iter().enumerate().rev() {
|
|
|
|
let item = item.clone();
|
2020-10-18 15:47:34 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
result = reducer
|
|
|
|
.call_dynamic(&ctx, None, [result.clone(), item.clone()])
|
2020-10-18 15:47:34 +02:00
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(reducer.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
reducer.call_dynamic(&ctx, None, [result, item, (i as INT).into()])
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
2020-11-11 06:25:45 +01:00
|
|
|
"reduce_rev".to_string(),
|
2020-12-30 14:12:51 +01:00
|
|
|
ctx.source().unwrap_or("").to_string(),
|
2020-10-18 15:47:34 +02:00
|
|
|
err,
|
2020-11-20 09:52:28 +01:00
|
|
|
Position::NONE,
|
2020-10-18 15:47:34 +02:00
|
|
|
))
|
|
|
|
})?;
|
|
|
|
}
|
2020-10-14 15:27:31 +02:00
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
Ok(result)
|
2020-10-13 04:57:29 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(name = "reduce_rev", return_raw, pure)]
|
|
|
|
pub fn reduce_rev_with_fn_name_with_initial(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
reducer: &str,
|
|
|
|
initial: Dynamic,
|
|
|
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
|
|
|
reduce_rev_with_initial(ctx, array, FnPtr::new(reducer)?, initial)
|
|
|
|
}
|
2021-10-20 05:06:38 +02:00
|
|
|
#[rhai_fn(name = "sort", return_raw)]
|
|
|
|
pub fn sort_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
comparer: &str,
|
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
sort(ctx, array, FnPtr::new(comparer)?)
|
|
|
|
}
|
2020-10-18 15:47:34 +02:00
|
|
|
#[rhai_fn(return_raw)]
|
|
|
|
pub fn sort(
|
2020-11-02 04:04:45 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-02-19 16:13:53 +01:00
|
|
|
array: &mut Array,
|
2020-10-18 15:47:34 +02:00
|
|
|
comparer: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
2021-10-23 05:51:48 +02:00
|
|
|
if array.len() <= 1 {
|
2021-09-20 12:35:23 +02:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
2021-02-19 16:13:53 +01:00
|
|
|
array.sort_by(|x, y| {
|
2020-10-18 15:47:34 +02:00
|
|
|
comparer
|
2021-03-15 04:36:30 +01:00
|
|
|
.call_dynamic(&ctx, None, [x.clone(), y.clone()])
|
2020-10-18 15:47:34 +02:00
|
|
|
.ok()
|
|
|
|
.and_then(|v| v.as_int().ok())
|
2021-05-25 04:54:48 +02:00
|
|
|
.map(|v| match v {
|
|
|
|
v if v > 0 => Ordering::Greater,
|
|
|
|
v if v < 0 => Ordering::Less,
|
|
|
|
0 => Ordering::Equal,
|
|
|
|
_ => unreachable!(),
|
2020-10-18 15:47:34 +02:00
|
|
|
})
|
2021-05-25 04:54:48 +02:00
|
|
|
.unwrap_or_else(|| x.type_id().cmp(&y.type_id()))
|
2020-10-18 15:47:34 +02:00
|
|
|
});
|
2020-10-13 04:57:29 +02:00
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(())
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
2021-10-23 05:51:48 +02:00
|
|
|
#[rhai_fn(name = "sort", return_raw)]
|
|
|
|
pub fn sort_with_builtin(array: &mut Array) -> Result<(), Box<EvalAltResult>> {
|
|
|
|
if array.len() <= 1 {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let type_id = array[0].type_id();
|
|
|
|
|
|
|
|
if array.iter().any(|a| a.type_id() != type_id) {
|
|
|
|
return Err(EvalAltResult::ErrorFunctionNotFound(
|
|
|
|
"sort() cannot be called with elements of different types".into(),
|
|
|
|
Position::NONE,
|
|
|
|
)
|
|
|
|
.into());
|
|
|
|
}
|
|
|
|
|
|
|
|
if type_id == TypeId::of::<INT>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.as_int().expect("`INT`");
|
|
|
|
let b = b.as_int().expect("`INT`");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.cmp(&b)
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<char>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.as_char().expect("char");
|
|
|
|
let b = b.as_char().expect("char");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.cmp(&b)
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
if type_id == TypeId::of::<crate::FLOAT>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.as_float().expect("`FLOAT`");
|
|
|
|
let b = b.as_float().expect("`FLOAT`");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.partial_cmp(&b).unwrap_or(Ordering::Equal)
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<ImmutableString>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.read_lock::<ImmutableString>().expect("`ImmutableString`");
|
|
|
|
let b = b.read_lock::<ImmutableString>().expect("`ImmutableString`");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.as_str().cmp(b.as_str())
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
#[cfg(feature = "decimal")]
|
|
|
|
if type_id == TypeId::of::<rust_decimal::Decimal>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.as_decimal().expect("`Decimal`");
|
|
|
|
let b = b.as_decimal().expect("`Decimal`");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.cmp(&b)
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<bool>() {
|
|
|
|
array.sort_by(|a, b| {
|
2021-11-13 05:23:35 +01:00
|
|
|
let a = a.as_bool().expect("`bool`");
|
|
|
|
let b = b.as_bool().expect("`bool`");
|
2021-10-23 05:51:48 +02:00
|
|
|
a.cmp(&b)
|
|
|
|
});
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
if type_id == TypeId::of::<()>() {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-10-21 13:04:53 +02:00
|
|
|
pub fn drain(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-10-21 13:04:53 +02:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(Array::new());
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
let mut drained = Array::with_capacity(array.len());
|
2020-10-13 04:57:29 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
let mut i = 0;
|
|
|
|
let mut x = 0;
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
while x < array.len() {
|
|
|
|
if filter
|
|
|
|
.call_dynamic(&ctx, None, [array[x].clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-10-18 15:47:34 +02:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()])
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"drain".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
|
|
|
drained.push(array.remove(x));
|
2021-10-19 13:57:15 +02:00
|
|
|
} else {
|
2021-11-23 15:37:18 +01:00
|
|
|
x += 1;
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
|
|
|
|
i += 1;
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
Ok(drained)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "drain", return_raw)]
|
|
|
|
pub fn drain_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
filter: &str,
|
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
|
|
|
drain(ctx, array, FnPtr::new(filter)?)
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "drain")]
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() || len <= 0 {
|
|
|
|
return Array::new();
|
|
|
|
}
|
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
let start = if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-09-20 12:35:23 +02:00
|
|
|
return Array::new();
|
2020-10-18 15:47:34 +02:00
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-09-20 12:35:23 +02:00
|
|
|
let len = if len <= 0 {
|
2020-10-18 15:47:34 +02:00
|
|
|
0
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if len as usize > array.len() - start {
|
|
|
|
array.len() - start
|
2020-10-18 15:47:34 +02:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-04-10 09:00:03 +02:00
|
|
|
array.drain(start..start + len).collect()
|
2020-10-18 07:18:12 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
#[rhai_fn(return_raw)]
|
2021-10-21 13:04:53 +02:00
|
|
|
pub fn retain(
|
2021-10-20 05:06:38 +02:00
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
2021-10-21 13:04:53 +02:00
|
|
|
filter: FnPtr,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() {
|
|
|
|
return Ok(Array::new());
|
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
let mut drained = Array::new();
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
let mut i = 0;
|
|
|
|
let mut x = 0;
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
while x < array.len() {
|
|
|
|
if !filter
|
|
|
|
.call_dynamic(&ctx, None, [array[x].clone()])
|
|
|
|
.or_else(|err| match *err {
|
2020-10-18 15:47:34 +02:00
|
|
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
2021-11-23 15:37:18 +01:00
|
|
|
if fn_sig.starts_with(filter.fn_name()) =>
|
2020-10-18 15:47:34 +02:00
|
|
|
{
|
2021-11-23 15:37:18 +01:00
|
|
|
filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()])
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
_ => Err(err),
|
|
|
|
})
|
|
|
|
.map_err(|err| {
|
|
|
|
Box::new(EvalAltResult::ErrorInFunctionCall(
|
|
|
|
"retain".to_string(),
|
|
|
|
ctx.source().unwrap_or("").to_string(),
|
|
|
|
err,
|
|
|
|
Position::NONE,
|
|
|
|
))
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
|
|
|
drained.push(array.remove(x));
|
2021-10-19 13:57:15 +02:00
|
|
|
} else {
|
2021-11-23 15:37:18 +01:00
|
|
|
x += 1;
|
2021-10-19 13:57:15 +02:00
|
|
|
}
|
2021-11-23 15:37:18 +01:00
|
|
|
|
|
|
|
i += 1;
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
2021-11-23 15:37:18 +01:00
|
|
|
Ok(drained)
|
|
|
|
}
|
|
|
|
#[rhai_fn(name = "retain", return_raw)]
|
|
|
|
pub fn retain_with_fn_name(
|
|
|
|
ctx: NativeCallContext,
|
|
|
|
array: &mut Array,
|
|
|
|
filter: &str,
|
|
|
|
) -> Result<Array, Box<EvalAltResult>> {
|
|
|
|
retain(ctx, array, FnPtr::new(filter)?)
|
2020-10-18 15:47:34 +02:00
|
|
|
}
|
|
|
|
#[rhai_fn(name = "retain")]
|
2021-02-19 16:13:53 +01:00
|
|
|
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
2021-09-20 12:35:23 +02:00
|
|
|
if array.is_empty() || len <= 0 {
|
|
|
|
return Array::new();
|
|
|
|
}
|
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
let start = if start < 0 {
|
2021-04-10 09:00:03 +02:00
|
|
|
let arr_len = array.len();
|
|
|
|
start
|
|
|
|
.checked_abs()
|
|
|
|
.map_or(0, |n| arr_len - (n as usize).min(arr_len))
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if start as usize >= array.len() {
|
2021-04-10 09:00:03 +02:00
|
|
|
return mem::take(array);
|
2020-10-18 15:47:34 +02:00
|
|
|
} else {
|
|
|
|
start as usize
|
|
|
|
};
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
let len = if len < 0 {
|
|
|
|
0
|
2021-02-19 16:13:53 +01:00
|
|
|
} else if len as usize > array.len() - start {
|
|
|
|
array.len() - start
|
2020-10-18 15:47:34 +02:00
|
|
|
} else {
|
|
|
|
len as usize
|
|
|
|
};
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2021-05-29 12:33:29 +02:00
|
|
|
let mut drained: Array = array.drain(..start).collect();
|
2021-04-10 09:00:03 +02:00
|
|
|
drained.extend(array.drain(len..));
|
2020-10-18 07:18:12 +02:00
|
|
|
|
2020-10-18 15:47:34 +02:00
|
|
|
drained
|
2020-10-18 07:18:12 +02:00
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(name = "==", return_raw, pure)]
|
2020-11-08 16:00:37 +01:00
|
|
|
pub fn equals(
|
2020-11-30 04:20:51 +01:00
|
|
|
ctx: NativeCallContext,
|
2021-08-13 07:42:39 +02:00
|
|
|
array1: &mut Array,
|
|
|
|
array2: Array,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-08-13 07:42:39 +02:00
|
|
|
if array1.len() != array2.len() {
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(false);
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2021-08-13 07:42:39 +02:00
|
|
|
if array1.is_empty() {
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(true);
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
|
|
|
|
2021-08-13 07:42:39 +02:00
|
|
|
let mut array2 = array2;
|
|
|
|
|
|
|
|
for (a1, a2) in array1.iter_mut().zip(array2.iter_mut()) {
|
2021-03-09 06:16:05 +01:00
|
|
|
if !ctx
|
2021-10-19 13:57:15 +02:00
|
|
|
.call_fn_raw(OP_EQUALS, true, false, &mut [a1, a2])
|
2021-03-09 06:16:05 +01:00
|
|
|
.or_else(|err| match *err {
|
|
|
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
|
|
|
if fn_sig.starts_with(OP_EQUALS) =>
|
|
|
|
{
|
|
|
|
if a1.type_id() == a2.type_id() {
|
|
|
|
// No default when comparing same type
|
|
|
|
Err(err)
|
|
|
|
} else {
|
|
|
|
Ok(Dynamic::FALSE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => Err(err),
|
|
|
|
})?
|
|
|
|
.as_bool()
|
|
|
|
.unwrap_or(false)
|
|
|
|
{
|
2021-03-22 04:18:09 +01:00
|
|
|
return Ok(false);
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-22 04:18:09 +01:00
|
|
|
Ok(true)
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2021-03-09 06:16:05 +01:00
|
|
|
#[rhai_fn(name = "!=", return_raw, pure)]
|
2020-11-08 16:00:37 +01:00
|
|
|
pub fn not_equals(
|
|
|
|
ctx: NativeCallContext,
|
2021-08-13 07:42:39 +02:00
|
|
|
array1: &mut Array,
|
2021-02-19 16:13:53 +01:00
|
|
|
array2: Array,
|
2021-03-22 04:18:09 +01:00
|
|
|
) -> Result<bool, Box<EvalAltResult>> {
|
2021-08-13 07:42:39 +02:00
|
|
|
equals(ctx, array1, array2).map(|r| !r)
|
2020-11-08 16:00:37 +01:00
|
|
|
}
|
2020-10-18 07:18:12 +02:00
|
|
|
}
|