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
|
|
|
|
2020-04-20 18:11:25 +02:00
|
|
|
use crate::any::{Dynamic, Variant};
|
2020-04-21 17:25:12 +02:00
|
|
|
use crate::def_package;
|
2020-08-15 02:37:16 +02:00
|
|
|
use crate::engine::{Array, Engine};
|
2020-08-03 17:11:08 +02:00
|
|
|
use crate::fn_native::FnPtr;
|
2020-05-25 07:44:28 +02:00
|
|
|
use crate::parser::{ImmutableString, INT};
|
2020-08-14 12:58:34 +02:00
|
|
|
use crate::plugin::*;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-07-26 09:53:22 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
use crate::{result::EvalAltResult, token::Position};
|
|
|
|
|
2020-08-24 16:37:44 +02:00
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
use crate::engine::Map;
|
|
|
|
|
2020-07-26 09:53:22 +02:00
|
|
|
use crate::stdlib::{any::TypeId, boxed::Box};
|
|
|
|
|
|
|
|
#[cfg(not(feature = "unchecked"))]
|
|
|
|
use crate::stdlib::string::ToString;
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
pub type Unit = ();
|
|
|
|
|
|
|
|
macro_rules! gen_array_functions {
|
|
|
|
($root:ident => $($arg_type:ident),+ ) => {
|
2020-08-28 17:13:38 +02:00
|
|
|
pub mod $root { $(pub mod $arg_type {
|
|
|
|
use super::super::*;
|
|
|
|
|
|
|
|
#[export_fn]
|
|
|
|
#[inline(always)]
|
|
|
|
pub fn push(list: &mut Array, item: $arg_type) {
|
|
|
|
list.push(Dynamic::from(item));
|
|
|
|
}
|
2020-08-14 12:58:34 +02:00
|
|
|
|
2020-08-28 17:13:38 +02:00
|
|
|
#[export_fn]
|
|
|
|
pub fn insert(list: &mut Array, position: INT, item: $arg_type) {
|
|
|
|
if position <= 0 {
|
|
|
|
list.insert(0, Dynamic::from(item));
|
|
|
|
} else if (position as usize) >= list.len() - 1 {
|
|
|
|
push(list, item);
|
|
|
|
} else {
|
|
|
|
list.insert(position as usize, Dynamic::from(item));
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
}
|
2020-08-28 17:13:38 +02:00
|
|
|
})* }
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! reg_functions {
|
2020-08-24 16:37:44 +02:00
|
|
|
($mod_name:ident += $root:ident ; $($arg_type:ident),+) => { $(
|
2020-08-28 17:13:38 +02:00
|
|
|
set_exported_fn!($mod_name, "push", $root::$arg_type::push);
|
2020-09-21 10:15:52 +02:00
|
|
|
set_exported_fn!($mod_name, "+=", $root::$arg_type::push);
|
2020-08-28 17:13:38 +02:00
|
|
|
set_exported_fn!($mod_name, "insert", $root::$arg_type::insert);
|
2020-08-24 16:37:44 +02:00
|
|
|
|
|
|
|
$mod_name.set_raw_fn("pad",
|
|
|
|
&[TypeId::of::<Array>(), TypeId::of::<INT>(), TypeId::of::<$arg_type>()],
|
|
|
|
pad::<$arg_type>);
|
|
|
|
)* }
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
|
|
|
|
reg_functions!(lib += basic; INT, bool, char, ImmutableString, FnPtr, Array, Unit);
|
|
|
|
|
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
{
|
|
|
|
reg_functions!(lib += numbers; i8, u8, i16, u16, i32, i64, u32, u64);
|
|
|
|
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
2020-08-24 16:37:44 +02:00
|
|
|
reg_functions!(lib += num_128; i128, u128);
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_float"))]
|
2020-08-24 16:37:44 +02:00
|
|
|
reg_functions!(lib += float; f32, f64);
|
|
|
|
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
reg_functions!(lib += map; Map);
|
2020-08-14 12:58:34 +02:00
|
|
|
|
2020-09-21 10:15:52 +02:00
|
|
|
// Merge in the module at the end to override `+=` for arrays
|
|
|
|
combine_with_exported_module!(lib, "array", array_functions);
|
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
// Register array iterator
|
|
|
|
lib.set_iter(
|
|
|
|
TypeId::of::<Array>(),
|
|
|
|
|arr| Box::new(arr.cast::<Array>().into_iter()) as Box<dyn Iterator<Item = Dynamic>>,
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
#[export_module]
|
|
|
|
mod array_functions {
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "len", get = "len")]
|
2020-08-20 16:11:41 +02:00
|
|
|
#[inline(always)]
|
2020-08-14 12:58:34 +02:00
|
|
|
pub fn len(list: &mut Array) -> INT {
|
2020-08-16 17:41:59 +02:00
|
|
|
list.len() as INT
|
2020-08-14 12:58:34 +02:00
|
|
|
}
|
2020-09-08 12:01:34 +02:00
|
|
|
#[rhai_fn(name = "append", name = "+=")]
|
2020-08-20 16:11:41 +02:00
|
|
|
#[inline(always)]
|
2020-08-14 12:58:34 +02:00
|
|
|
pub fn append(x: &mut Array, y: Array) {
|
|
|
|
x.extend(y);
|
|
|
|
}
|
2020-08-16 17:41:59 +02:00
|
|
|
#[rhai_fn(name = "+")]
|
2020-08-20 16:11:41 +02:00
|
|
|
#[inline]
|
2020-08-16 17:41:59 +02:00
|
|
|
pub fn concat(mut x: Array, y: Array) -> Array {
|
|
|
|
x.extend(y);
|
|
|
|
x
|
|
|
|
}
|
2020-08-20 16:11:41 +02:00
|
|
|
#[inline]
|
2020-08-14 12:58:34 +02:00
|
|
|
pub fn pop(list: &mut Array) -> Dynamic {
|
|
|
|
list.pop().unwrap_or_else(|| ().into())
|
|
|
|
}
|
|
|
|
pub fn shift(list: &mut Array) -> Dynamic {
|
|
|
|
if list.is_empty() {
|
|
|
|
().into()
|
|
|
|
} else {
|
|
|
|
list.remove(0)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
pub fn remove(list: &mut Array, len: INT) -> Dynamic {
|
|
|
|
if len < 0 || (len as usize) >= list.len() {
|
|
|
|
().into()
|
|
|
|
} else {
|
|
|
|
list.remove(len as usize)
|
|
|
|
}
|
|
|
|
}
|
2020-08-20 16:11:41 +02:00
|
|
|
#[inline(always)]
|
2020-08-14 12:58:34 +02:00
|
|
|
pub fn clear(list: &mut Array) {
|
|
|
|
list.clear();
|
|
|
|
}
|
|
|
|
pub fn truncate(list: &mut Array, len: INT) {
|
|
|
|
if len >= 0 {
|
|
|
|
list.truncate(len as usize);
|
|
|
|
} else {
|
|
|
|
list.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-06 06:04:02 +02:00
|
|
|
fn pad<T: Variant + Clone>(
|
2020-07-26 09:53:22 +02:00
|
|
|
_engine: &Engine,
|
2020-07-06 06:04:02 +02:00
|
|
|
_: &Module,
|
|
|
|
args: &mut [&mut Dynamic],
|
2020-08-14 12:58:34 +02:00
|
|
|
) -> Result<(), Box<EvalAltResult>> {
|
2020-07-27 06:30:09 +02:00
|
|
|
let len = *args[1].read_lock::<INT>().unwrap();
|
2020-06-15 15:49:02 +02:00
|
|
|
|
|
|
|
// Check if array will be over max size limit
|
2020-06-15 16:04:14 +02:00
|
|
|
#[cfg(not(feature = "unchecked"))]
|
2020-07-26 09:53:22 +02:00
|
|
|
if _engine.limits.max_array_size > 0
|
|
|
|
&& len > 0
|
|
|
|
&& (len as usize) > _engine.limits.max_array_size
|
|
|
|
{
|
2020-08-06 04:17:32 +02:00
|
|
|
return EvalAltResult::ErrorDataTooLarge(
|
2020-07-04 16:53:00 +02:00
|
|
|
"Size of array".to_string(),
|
2020-07-26 09:53:22 +02:00
|
|
|
_engine.limits.max_array_size,
|
2020-07-04 16:53:00 +02:00
|
|
|
len as usize,
|
|
|
|
Position::none(),
|
2020-08-06 04:17:32 +02:00
|
|
|
)
|
|
|
|
.into();
|
2020-06-15 16:04:14 +02:00
|
|
|
}
|
|
|
|
|
2020-06-30 12:34:32 +02:00
|
|
|
if len > 0 {
|
2020-06-29 17:55:28 +02:00
|
|
|
let item = args[2].clone();
|
2020-07-27 06:30:09 +02:00
|
|
|
let mut list = args[0].write_lock::<Array>().unwrap();
|
2020-06-15 15:49:02 +02:00
|
|
|
|
2020-06-30 12:34:32 +02:00
|
|
|
if len as usize > list.len() {
|
|
|
|
list.resize(len as usize, item);
|
|
|
|
}
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
2020-06-15 16:04:14 +02:00
|
|
|
Ok(())
|
2020-04-20 18:11:25 +02:00
|
|
|
}
|
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
gen_array_functions!(basic => INT, bool, char, ImmutableString, FnPtr, Array, Unit);
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
gen_array_functions!(numbers => i8, u8, i16, u16, i32, i64, u32, u64);
|
2020-04-20 18:11:25 +02:00
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
#[cfg(not(feature = "only_i32"))]
|
|
|
|
#[cfg(not(feature = "only_i64"))]
|
|
|
|
#[cfg(not(target_arch = "wasm32"))]
|
|
|
|
gen_array_functions!(num_128 => i128, u128);
|
2020-06-17 10:50:46 +02:00
|
|
|
|
2020-08-14 12:58:34 +02:00
|
|
|
#[cfg(not(feature = "no_float"))]
|
|
|
|
gen_array_functions!(float => f32, f64);
|
2020-08-24 16:37:44 +02:00
|
|
|
|
|
|
|
#[cfg(not(feature = "no_object"))]
|
|
|
|
gen_array_functions!(map => Map);
|