rhai/src/packages/array_basic.rs

177 lines
4.9 KiB
Rust
Raw Normal View History

#![cfg(not(feature = "no_index"))]
use crate::any::{Dynamic, Variant};
use crate::def_package;
use crate::engine::{Array, Engine};
2020-08-03 17:11:08 +02:00
use crate::fn_native::FnPtr;
use crate::module::{FuncReturn, Module};
2020-05-25 07:44:28 +02:00
use crate::parser::{ImmutableString, INT};
2020-07-26 09:53:22 +02:00
#[cfg(not(feature = "unchecked"))]
use crate::{result::EvalAltResult, token::Position};
use crate::stdlib::{any::TypeId, boxed::Box};
#[cfg(not(feature = "unchecked"))]
use crate::stdlib::string::ToString;
// Register array utility functions
2020-05-13 13:21:42 +02:00
fn push<T: Variant + Clone>(list: &mut Array, item: T) -> FuncReturn<()> {
list.push(Dynamic::from(item));
2020-05-13 13:21:42 +02:00
Ok(())
}
2020-05-13 13:21:42 +02:00
fn ins<T: Variant + Clone>(list: &mut Array, position: INT, item: T) -> FuncReturn<()> {
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-05-13 13:21:42 +02:00
Ok(())
}
fn pad<T: Variant + Clone>(
2020-07-26 09:53:22 +02:00
_engine: &Engine,
_: &Module,
args: &mut [&mut Dynamic],
) -> FuncReturn<()> {
let len = *args[1].read_lock::<INT>().unwrap();
// Check if array will be over max size limit
#[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-07-04 16:53:00 +02:00
return Err(Box::new(EvalAltResult::ErrorDataTooLarge(
"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-06-30 12:34:32 +02:00
if len > 0 {
2020-06-29 17:55:28 +02:00
let item = args[2].clone();
let mut list = args[0].write_lock::<Array>().unwrap();
2020-06-30 12:34:32 +02:00
if len as usize > list.len() {
list.resize(len as usize, item);
}
}
Ok(())
}
2020-05-13 13:21:42 +02:00
macro_rules! reg_op {
($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
$( $lib.set_fn_2_mut($op, $func::<$par>); )*
};
}
2020-05-13 13:21:42 +02:00
macro_rules! reg_tri {
($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
$( $lib.set_fn_3_mut($op, $func::<$par>); )*
};
}
macro_rules! reg_pad {
($lib:expr, $op:expr, $func:ident, $($par:ty),*) => {
$({
2020-07-07 16:59:23 +02:00
$lib.set_raw_fn($op,
&[TypeId::of::<Array>(), TypeId::of::<INT>(), TypeId::of::<$par>()],
$func::<$par>
);
})*
};
}
2020-04-22 08:55:40 +02:00
def_package!(crate:BasicArrayPackage:"Basic array utilities.", lib, {
2020-08-03 17:11:08 +02:00
reg_op!(lib, "push", push, INT, bool, char, ImmutableString, FnPtr, Array, ());
reg_pad!(lib, "pad", pad, INT, bool, char, ImmutableString, FnPtr, Array, ());
reg_tri!(lib, "insert", ins, INT, bool, char, ImmutableString, FnPtr, Array, ());
2020-05-13 13:21:42 +02:00
lib.set_fn_2_mut("append", |x: &mut Array, y: Array| {
x.extend(y);
Ok(())
});
2020-05-25 14:14:31 +02:00
lib.set_fn_2_mut("+=", |x: &mut Array, y: Array| {
x.extend(y);
Ok(())
});
2020-05-13 13:21:42 +02:00
lib.set_fn_2(
2020-04-21 17:01:10 +02:00
"+",
|mut x: Array, y: Array| {
x.extend(y);
2020-05-13 13:21:42 +02:00
Ok(x)
2020-04-21 17:01:10 +02:00
},
);
2020-07-31 16:30:23 +02:00
if cfg!(not(feature = "only_i32")) && cfg!(not(feature = "only_i64")) {
2020-06-17 10:50:46 +02:00
reg_op!(lib, "push", push, i8, u8, i16, u16, i32, i64, u32, u64);
reg_pad!(lib, "pad", pad, i8, u8, i16, u16, i32, u32, i64, u64);
reg_tri!(lib, "insert", ins, i8, u8, i16, u16, i32, i64, u32, u64);
2020-07-31 16:30:23 +02:00
if cfg!(not(target_arch = "wasm32")) {
2020-06-17 10:50:46 +02:00
reg_op!(lib, "push", push, i128, u128);
reg_pad!(lib, "pad", pad, i128, u128);
reg_tri!(lib, "insert", ins, i128, u128);
}
2020-04-21 17:01:10 +02:00
}
2020-04-21 17:01:10 +02:00
#[cfg(not(feature = "no_float"))]
{
reg_op!(lib, "push", push, f32, f64);
reg_pad!(lib, "pad", pad, f32, f64);
2020-04-21 17:01:10 +02:00
reg_tri!(lib, "insert", ins, f32, f64);
}
2020-05-13 13:21:42 +02:00
lib.set_fn_1_mut(
2020-04-21 17:01:10 +02:00
"pop",
2020-05-13 13:21:42 +02:00
|list: &mut Array| Ok(list.pop().unwrap_or_else(|| ().into())),
2020-04-21 17:01:10 +02:00
);
2020-05-13 13:21:42 +02:00
lib.set_fn_1_mut(
2020-04-21 17:01:10 +02:00
"shift",
|list: &mut Array| {
2020-05-13 13:21:42 +02:00
Ok(if list.is_empty() {
2020-04-22 08:55:40 +02:00
().into()
2020-04-21 17:01:10 +02:00
} else {
list.remove(0)
2020-05-13 13:21:42 +02:00
})
2020-04-21 17:01:10 +02:00
},
);
2020-05-13 13:21:42 +02:00
lib.set_fn_2_mut(
2020-04-21 17:01:10 +02:00
"remove",
|list: &mut Array, len: INT| {
2020-05-13 13:21:42 +02:00
Ok(if len < 0 || (len as usize) >= list.len() {
2020-04-22 08:55:40 +02:00
().into()
2020-04-21 17:01:10 +02:00
} else {
list.remove(len as usize)
2020-05-13 13:21:42 +02:00
})
2020-04-21 17:01:10 +02:00
},
);
2020-05-13 13:21:42 +02:00
lib.set_fn_1_mut("len", |list: &mut Array| Ok(list.len() as INT));
#[cfg(not(feature = "no_object"))]
lib.set_getter_fn("len", |list: &mut Array| Ok(list.len() as INT));
2020-05-13 13:21:42 +02:00
lib.set_fn_1_mut("clear", |list: &mut Array| {
list.clear();
Ok(())
});
lib.set_fn_2_mut(
2020-04-21 17:01:10 +02:00
"truncate",
|list: &mut Array, len: INT| {
if len >= 0 {
list.truncate(len as usize);
2020-04-24 14:05:34 +02:00
} else {
list.clear();
}
2020-05-13 13:21:42 +02:00
Ok(())
2020-04-21 17:01:10 +02:00
},
);
2020-04-21 17:01:10 +02:00
// Register array iterator
2020-05-13 14:22:05 +02:00
lib.set_iter(
2020-04-21 17:01:10 +02:00
TypeId::of::<Array>(),
2020-05-20 13:27:23 +02:00
|arr| Box::new(arr.cast::<Array>().into_iter()) as Box<dyn Iterator<Item = Dynamic>>,
2020-04-21 17:01:10 +02:00
);
});