Avoid cloning in array methods as much as possible.
This commit is contained in:
parent
9d1ab2c8a1
commit
2334cd8f56
@ -4,6 +4,12 @@ Rhai Release Notes
|
|||||||
Version 1.2.0
|
Version 1.2.0
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
Enhancements
|
||||||
|
------------
|
||||||
|
|
||||||
|
* `NativeCallContext::call_fn_dynamic_raw` is deprecated and `NativeCallContext::call_fn_raw` is added.
|
||||||
|
* Array methods now avoid cloning as much as possible (although most predicates will involve cloning anyway if passed a closure).
|
||||||
|
|
||||||
|
|
||||||
Version 1.1.0
|
Version 1.1.0
|
||||||
=============
|
=============
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
//! Module containing all deprecated API that will be removed in the next major version.
|
//! Module containing all deprecated API that will be removed in the next major version.
|
||||||
|
|
||||||
use crate::{Dynamic, Engine, EvalAltResult, ImmutableString, Scope, AST};
|
use crate::{
|
||||||
|
Dynamic, Engine, EvalAltResult, ImmutableString, NativeCallContext, RhaiResult, Scope, AST,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "no_std")]
|
#[cfg(feature = "no_std")]
|
||||||
use std::prelude::v1::*;
|
use std::prelude::v1::*;
|
||||||
@ -141,3 +143,28 @@ impl Dynamic {
|
|||||||
self.into_immutable_string()
|
self.into_immutable_string()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl NativeCallContext<'_> {
|
||||||
|
/// Call a function inside the call context.
|
||||||
|
///
|
||||||
|
/// # WARNING
|
||||||
|
///
|
||||||
|
/// All arguments may be _consumed_, meaning that they may be replaced by `()`.
|
||||||
|
/// This is to avoid unnecessarily cloning the arguments.
|
||||||
|
///
|
||||||
|
/// Do not use the arguments after this call. If they are needed afterwards,
|
||||||
|
/// clone them _before_ calling this function.
|
||||||
|
///
|
||||||
|
/// If `is_method` is [`true`], the first argument is assumed to be passed
|
||||||
|
/// by reference and is not consumed.
|
||||||
|
#[deprecated(since = "1.2.0", note = "use `call_fn_raw` instead")]
|
||||||
|
#[inline(always)]
|
||||||
|
pub fn call_fn_dynamic_raw(
|
||||||
|
&self,
|
||||||
|
fn_name: impl AsRef<str>,
|
||||||
|
is_method_call: bool,
|
||||||
|
args: &mut [&mut Dynamic],
|
||||||
|
) -> RhaiResult {
|
||||||
|
self.call_fn_raw(fn_name.as_ref(), is_method_call, is_method_call, args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -191,48 +191,42 @@ impl<'a> NativeCallContext<'a> {
|
|||||||
/// Do not use the arguments after this call. If they are needed afterwards,
|
/// Do not use the arguments after this call. If they are needed afterwards,
|
||||||
/// clone them _before_ calling this function.
|
/// clone them _before_ calling this function.
|
||||||
///
|
///
|
||||||
/// If `is_method` is [`true`], the first argument is assumed to be passed
|
/// If `is_ref_mut` is [`true`], the first argument is assumed to be passed
|
||||||
/// by reference and is not consumed.
|
/// by reference and is not consumed.
|
||||||
#[inline(always)]
|
///
|
||||||
pub fn call_fn_dynamic_raw(
|
/// If `is_method_call` is [`true`], the first argument is assumed to be the
|
||||||
|
/// `this` pointer for a script-defined function (or the object of a method call).
|
||||||
|
pub fn call_fn_raw(
|
||||||
&self,
|
&self,
|
||||||
fn_name: impl AsRef<str>,
|
fn_name: &str,
|
||||||
|
is_ref_mut: bool,
|
||||||
is_method_call: bool,
|
is_method_call: bool,
|
||||||
args: &mut [&mut Dynamic],
|
args: &mut [&mut Dynamic],
|
||||||
) -> RhaiResult {
|
) -> Result<Dynamic, Box<EvalAltResult>> {
|
||||||
fn call_fn_dynamic_inner(
|
let hash = if is_method_call {
|
||||||
context: &NativeCallContext,
|
FnCallHashes::from_script_and_native(
|
||||||
is_method_call: bool,
|
calc_fn_hash(fn_name, args.len() - 1),
|
||||||
fn_name: &str,
|
calc_fn_hash(fn_name, args.len()),
|
||||||
args: &mut [&mut Dynamic],
|
)
|
||||||
) -> Result<Dynamic, Box<EvalAltResult>> {
|
} else {
|
||||||
let hash = if is_method_call {
|
FnCallHashes::from_script(calc_fn_hash(fn_name, args.len()))
|
||||||
FnCallHashes::from_script_and_native(
|
};
|
||||||
calc_fn_hash(fn_name, args.len() - 1),
|
|
||||||
calc_fn_hash(fn_name, args.len()),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
FnCallHashes::from_script(calc_fn_hash(fn_name, args.len()))
|
|
||||||
};
|
|
||||||
context
|
|
||||||
.engine()
|
|
||||||
.exec_fn_call(
|
|
||||||
&mut context.mods.cloned().unwrap_or_default(),
|
|
||||||
&mut Default::default(),
|
|
||||||
context.lib,
|
|
||||||
fn_name,
|
|
||||||
hash,
|
|
||||||
args,
|
|
||||||
is_method_call,
|
|
||||||
is_method_call,
|
|
||||||
Position::NONE,
|
|
||||||
None,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.map(|(r, _)| r)
|
|
||||||
}
|
|
||||||
|
|
||||||
call_fn_dynamic_inner(self, is_method_call, fn_name.as_ref(), args)
|
self.engine()
|
||||||
|
.exec_fn_call(
|
||||||
|
&mut self.mods.cloned().unwrap_or_default(),
|
||||||
|
&mut Default::default(),
|
||||||
|
self.lib,
|
||||||
|
fn_name,
|
||||||
|
hash,
|
||||||
|
args,
|
||||||
|
is_ref_mut,
|
||||||
|
is_method_call,
|
||||||
|
Position::NONE,
|
||||||
|
None,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
.map(|(r, _)| r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,7 +130,7 @@ impl FnPtr {
|
|||||||
}
|
}
|
||||||
args.extend(arg_values.iter_mut());
|
args.extend(arg_values.iter_mut());
|
||||||
|
|
||||||
ctx.call_fn_dynamic_raw(self.fn_name(), is_method, &mut args)
|
ctx.call_fn_raw(self.fn_name(), is_method, is_method, &mut args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,31 +246,37 @@ mod array_functions {
|
|||||||
mapper: FnPtr,
|
mapper: FnPtr,
|
||||||
) -> Result<Array, Box<EvalAltResult>> {
|
) -> Result<Array, Box<EvalAltResult>> {
|
||||||
if array.is_empty() {
|
if array.is_empty() {
|
||||||
return Ok(array.clone());
|
return Ok(Array::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fn_name = mapper.fn_name();
|
||||||
let mut ar = Array::with_capacity(array.len());
|
let mut ar = Array::with_capacity(array.len());
|
||||||
|
let mut index_val = Dynamic::UNIT;
|
||||||
|
|
||||||
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
|
||||||
ar.push(
|
ar.push(
|
||||||
mapper
|
match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
Ok(r) => r,
|
||||||
.or_else(|err| match *err {
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(mapper.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
mapper.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"map".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?,
|
},
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,31 +292,38 @@ mod array_functions {
|
|||||||
return Ok(array.clone());
|
return Ok(array.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let fn_name = filter.fn_name();
|
||||||
let mut ar = Array::new();
|
let mut ar = Array::new();
|
||||||
|
let mut index_val = Dynamic::UNIT;
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
if filter
|
let mut args = [item, &mut index_val];
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
let keep = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"filter".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
}
|
||||||
.unwrap_or(false)
|
.as_bool()
|
||||||
{
|
.unwrap_or(false);
|
||||||
ar.push(item.clone());
|
|
||||||
|
if keep {
|
||||||
|
ar.push(args[0].clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -328,7 +341,7 @@ mod array_functions {
|
|||||||
|
|
||||||
for item in array.iter_mut() {
|
for item in array.iter_mut() {
|
||||||
if ctx
|
if ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
.call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
||||||
if fn_sig.starts_with(OP_EQUALS) =>
|
if fn_sig.starts_with(OP_EQUALS) =>
|
||||||
@ -387,7 +400,7 @@ mod array_functions {
|
|||||||
|
|
||||||
for (i, item) in array.iter_mut().enumerate().skip(start) {
|
for (i, item) in array.iter_mut().enumerate().skip(start) {
|
||||||
if ctx
|
if ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [item, &mut value.clone()])
|
.call_fn_raw(OP_EQUALS, true, false, &mut [item, &mut value.clone()])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
||||||
if fn_sig.starts_with(OP_EQUALS) =>
|
if fn_sig.starts_with(OP_EQUALS) =>
|
||||||
@ -444,28 +457,36 @@ mod array_functions {
|
|||||||
start as usize
|
start as usize
|
||||||
};
|
};
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate().skip(start) {
|
let fn_name = filter.fn_name();
|
||||||
if filter
|
let mut index_val = Dynamic::UNIT;
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
for (i, item) in array.iter_mut().enumerate().skip(start) {
|
||||||
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
|
let found = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"index_of".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
}
|
||||||
.unwrap_or(false)
|
.as_bool()
|
||||||
{
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if found {
|
||||||
return Ok(i as INT);
|
return Ok(i as INT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -482,28 +503,36 @@ mod array_functions {
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
let fn_name = filter.fn_name();
|
||||||
if filter
|
let mut index_val = Dynamic::UNIT;
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
|
let found = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"some".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
}
|
||||||
.unwrap_or(false)
|
.as_bool()
|
||||||
{
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if found {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -520,28 +549,36 @@ mod array_functions {
|
|||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, item) in array.iter().enumerate() {
|
let fn_name = filter.fn_name();
|
||||||
if !filter
|
let mut index_val = Dynamic::UNIT;
|
||||||
.call_dynamic(&ctx, None, [item.clone()])
|
|
||||||
.or_else(|err| match *err {
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
|
let found = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
|
Ok(r) => r,
|
||||||
|
Err(err) => match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"all".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
}
|
||||||
.unwrap_or(false)
|
.as_bool()
|
||||||
{
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
if !found {
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,42 +763,62 @@ mod array_functions {
|
|||||||
return Ok(Array::new());
|
return Ok(Array::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut drained = Array::with_capacity(array.len());
|
let fn_name = filter.fn_name();
|
||||||
|
let mut index_val = Dynamic::UNIT;
|
||||||
|
let mut removed = Vec::with_capacity(array.len());
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
let mut i = 0;
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
let mut x = 0;
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
while x < array.len() {
|
let remove = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
if filter
|
Ok(r) => r,
|
||||||
.call_dynamic(&ctx, None, [array[x].clone()])
|
Err(err) => match *err {
|
||||||
.or_else(|err| match *err {
|
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"drain".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
drained.push(array.remove(x));
|
|
||||||
} else {
|
|
||||||
x += 1;
|
|
||||||
}
|
}
|
||||||
|
.as_bool()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
i += 1;
|
removed.push(remove);
|
||||||
|
|
||||||
|
if remove {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained)
|
if count == 0 {
|
||||||
|
return Ok(Array::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = Vec::with_capacity(count);
|
||||||
|
let mut x = 0;
|
||||||
|
let mut i = 0;
|
||||||
|
|
||||||
|
while i < array.len() {
|
||||||
|
if removed[x] {
|
||||||
|
result.push(array.remove(i));
|
||||||
|
} else {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "drain")]
|
#[rhai_fn(name = "drain")]
|
||||||
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
@ -800,42 +857,62 @@ mod array_functions {
|
|||||||
return Ok(Array::new());
|
return Ok(Array::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut drained = Array::new();
|
let fn_name = filter.fn_name();
|
||||||
|
let mut index_val = Dynamic::UNIT;
|
||||||
|
let mut removed = Vec::with_capacity(array.len());
|
||||||
|
let mut count = 0;
|
||||||
|
|
||||||
let mut i = 0;
|
for (i, item) in array.iter_mut().enumerate() {
|
||||||
let mut x = 0;
|
let mut args = [item, &mut index_val];
|
||||||
|
|
||||||
while x < array.len() {
|
let keep = match ctx.call_fn_raw(fn_name, true, false, &mut args[..1]) {
|
||||||
if !filter
|
Ok(r) => r,
|
||||||
.call_dynamic(&ctx, None, [array[x].clone()])
|
Err(err) => match *err {
|
||||||
.or_else(|err| match *err {
|
|
||||||
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(fn_sig, _)
|
||||||
if fn_sig.starts_with(filter.fn_name()) =>
|
if fn_sig.starts_with(fn_name) =>
|
||||||
{
|
{
|
||||||
filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()])
|
*args[1] = Dynamic::from(i as INT);
|
||||||
|
ctx.call_fn_raw(fn_name, true, false, &mut args)?
|
||||||
}
|
}
|
||||||
_ => Err(err),
|
_ => {
|
||||||
})
|
return EvalAltResult::ErrorInFunctionCall(
|
||||||
.map_err(|err| {
|
"drain".to_string(),
|
||||||
Box::new(EvalAltResult::ErrorInFunctionCall(
|
ctx.source().unwrap_or("").to_string(),
|
||||||
"retain".to_string(),
|
err,
|
||||||
ctx.source().unwrap_or("").to_string(),
|
Position::NONE,
|
||||||
err,
|
)
|
||||||
Position::NONE,
|
.into()
|
||||||
))
|
}
|
||||||
})?
|
},
|
||||||
.as_bool()
|
|
||||||
.unwrap_or(false)
|
|
||||||
{
|
|
||||||
drained.push(array.remove(x));
|
|
||||||
} else {
|
|
||||||
x += 1;
|
|
||||||
}
|
}
|
||||||
|
.as_bool()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
i += 1;
|
removed.push(!keep);
|
||||||
|
|
||||||
|
if !keep {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(drained)
|
if count == 0 {
|
||||||
|
return Ok(Array::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut result = Vec::with_capacity(count);
|
||||||
|
let mut x = 0;
|
||||||
|
let mut i = 0;
|
||||||
|
|
||||||
|
while i < array.len() {
|
||||||
|
if removed[x] {
|
||||||
|
result.push(array.remove(i));
|
||||||
|
} else {
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
x += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(result.into())
|
||||||
}
|
}
|
||||||
#[rhai_fn(name = "retain")]
|
#[rhai_fn(name = "retain")]
|
||||||
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {
|
||||||
@ -884,7 +961,7 @@ mod array_functions {
|
|||||||
|
|
||||||
for (a1, a2) in array1.iter_mut().zip(array2.iter_mut()) {
|
for (a1, a2) in array1.iter_mut().zip(array2.iter_mut()) {
|
||||||
if !ctx
|
if !ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [a1, a2])
|
.call_fn_raw(OP_EQUALS, true, false, &mut [a1, a2])
|
||||||
.or_else(|err| match *err {
|
.or_else(|err| match *err {
|
||||||
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
EvalAltResult::ErrorFunctionNotFound(ref fn_sig, _)
|
||||||
if fn_sig.starts_with(OP_EQUALS) =>
|
if fn_sig.starts_with(OP_EQUALS) =>
|
||||||
|
@ -84,7 +84,7 @@ mod map_functions {
|
|||||||
for (m1, v1) in map1.iter_mut() {
|
for (m1, v1) in map1.iter_mut() {
|
||||||
if let Some(v2) = map2.get_mut(m1) {
|
if let Some(v2) = map2.get_mut(m1) {
|
||||||
let equals = ctx
|
let equals = ctx
|
||||||
.call_fn_dynamic_raw(OP_EQUALS, true, &mut [v1, v2])
|
.call_fn_raw(OP_EQUALS, true, false, &mut [v1, v2])
|
||||||
.map(|v| v.as_bool().unwrap_or(false))?;
|
.map(|v| v.as_bool().unwrap_or(false))?;
|
||||||
|
|
||||||
if !equals {
|
if !equals {
|
||||||
|
@ -28,7 +28,7 @@ pub fn print_with_func(
|
|||||||
ctx: &NativeCallContext,
|
ctx: &NativeCallContext,
|
||||||
value: &mut Dynamic,
|
value: &mut Dynamic,
|
||||||
) -> crate::ImmutableString {
|
) -> crate::ImmutableString {
|
||||||
match ctx.call_fn_dynamic_raw(fn_name, true, &mut [value]) {
|
match ctx.call_fn_raw(fn_name, true, false, &mut [value]) {
|
||||||
Ok(result) if result.is::<crate::ImmutableString>() => result
|
Ok(result) if result.is::<crate::ImmutableString>() => result
|
||||||
.into_immutable_string()
|
.into_immutable_string()
|
||||||
.expect("result is `ImmutableString`"),
|
.expect("result is `ImmutableString`"),
|
||||||
|
Loading…
Reference in New Issue
Block a user