From 81df36667f0026d46e282c98407ab83501046094 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 19 Nov 2021 15:07:29 +0800 Subject: [PATCH 1/3] Bump version. --- CHANGELOG.md | 4 ++++ Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2d239e2..754ffcb1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ Rhai Release Notes ================== +Version 1.2.1 +============= + + Version 1.2.0 ============= diff --git a/Cargo.toml b/Cargo.toml index 0b27d863..24c73cd8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ members = [".", "codegen"] [package] name = "rhai" -version = "1.2.0" +version = "1.2.1" edition = "2018" authors = ["Jonathan Turner", "Lukáš Hozda", "Stephen Chung", "jhwgh1968"] description = "Embedded scripting for Rust" From 20915572e8ef43125afd4942797eee5b5b7c56bf Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Fri, 19 Nov 2021 15:09:39 +0800 Subject: [PATCH 2/3] Update CI. --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 445f8946..a3359626 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -4,7 +4,7 @@ on: push: branches: - master - - v1.1-fixes + - v1.2-fixes pull_request: {} jobs: From 2b0b79870e88dad91afdec32b720a2d37edffc28 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 23 Nov 2021 22:37:18 +0800 Subject: [PATCH 3/3] Fix bug in array methods. --- CHANGELOG.md | 5 + src/packages/array_basic.rs | 634 ++++++++++++++++-------------------- 2 files changed, 285 insertions(+), 354 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 754ffcb1..bb1f352d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ Rhai Release Notes Version 1.2.1 ============= +Bug fixes +--------- + +* Array methods (such as `map`) taking a closure with captures as argument now works properly. + Version 1.2.0 ============= diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index 39665b99..ffb7ab94 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -250,7 +250,36 @@ mod array_functions { array: &mut Array, mapper: FnPtr, ) -> Result> { - map_with_fn_name(ctx, array, mapper.fn_name()) + if array.is_empty() { + return Ok(array.clone()); + } + + let mut ar = Array::with_capacity(array.len()); + + 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( + "map".to_string(), + ctx.source().unwrap_or("").to_string(), + err, + Position::NONE, + )) + })?, + ); + } + + Ok(ar) } #[rhai_fn(name = "map", return_raw, pure)] pub fn map_with_fn_name( @@ -258,94 +287,57 @@ mod array_functions { array: &mut Array, mapper: &str, ) -> Result> { - if array.is_empty() { - return Ok(Array::new()); - } - - 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]; - - ar.push(match ctx.call_fn_raw(mapper, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(mapper) => - { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(mapper, true, false, &mut args)? - } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "map".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - }); - } - - Ok(ar) + map(ctx, array, FnPtr::new(mapper)?) } + #[rhai_fn(return_raw, pure)] pub fn filter( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, - ) -> Result> { - filter_with_fn_name(ctx, array, filter.fn_name()) - } - #[rhai_fn(name = "filter", return_raw, pure)] - pub fn filter_with_fn_name( - ctx: NativeCallContext, - array: &mut Array, - filter: &str, ) -> Result> { if array.is_empty() { return Ok(array.clone()); } let mut ar = Array::new(); - let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter_mut().enumerate() { - let mut args = [item, &mut index_val]; - - let keep = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { + for (i, item) in array.iter().enumerate() { + if filter + .call_dynamic(&ctx, None, [item.clone()]) + .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => + if fn_sig.starts_with(filter.fn_name()) => { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "filter".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - if keep { - ar.push(args[0].clone()); + _ => 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()); } } Ok(ar) } + #[rhai_fn(name = "filter", return_raw, pure)] + pub fn filter_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + filter_func: &str, + ) -> Result> { + filter(ctx, array, FnPtr::new(filter_func)?) + } #[rhai_fn(return_raw, pure)] pub fn contains( ctx: NativeCallContext, @@ -466,15 +458,6 @@ mod array_functions { array: &mut Array, filter: FnPtr, start: INT, - ) -> Result> { - index_of_with_fn_name_filter_starting_from(ctx, array, filter.fn_name(), start) - } - #[rhai_fn(name = "index_of", return_raw, pure)] - pub fn index_of_with_fn_name_filter_starting_from( - ctx: NativeCallContext, - array: &mut Array, - filter: &str, - start: INT, ) -> Result> { if array.is_empty() { return Ok(-1); @@ -491,48 +474,80 @@ mod array_functions { start as usize }; - let mut index_val = Dynamic::UNIT; - - for (i, item) in array.iter_mut().enumerate().skip(start) { - let mut args = [item, &mut index_val]; - - let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { + for (i, item) in array.iter().enumerate().skip(start) { + if filter + .call_dynamic(&ctx, None, [item.clone()]) + .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => + if fn_sig.starts_with(filter.fn_name()) => { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "index_of".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - if found { + _ => 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) + { return Ok(i as INT); } } Ok(-1 as INT) } + #[rhai_fn(name = "index_of", return_raw, pure)] + pub fn index_of_with_fn_name_filter_starting_from( + ctx: NativeCallContext, + array: &mut Array, + filter: &str, + start: INT, + ) -> Result> { + index_of_filter_starting_from(ctx, array, FnPtr::new(filter)?, start) + } #[rhai_fn(return_raw, pure)] pub fn some( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, ) -> Result> { - some_with_fn_name(ctx, array, filter.fn_name()) + if array.is_empty() { + return Ok(false); + } + + for (i, item) in array.iter().enumerate() { + if filter + .call_dynamic(&ctx, None, [item.clone()]) + .or_else(|err| match *err { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.starts_with(filter.fn_name()) => + { + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + } + _ => 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) + { + return Ok(true); + } + } + + Ok(false) } #[rhai_fn(name = "some", return_raw, pure)] pub fn some_with_fn_name( @@ -540,44 +555,7 @@ mod array_functions { array: &mut Array, filter: &str, ) -> Result> { - if array.is_empty() { - return Ok(false); - } - - let mut index_val = Dynamic::UNIT; - - for (i, item) in array.iter_mut().enumerate() { - let mut args = [item, &mut index_val]; - - let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => - { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? - } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "some".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - if found { - return Ok(true); - } - } - - Ok(false) + some(ctx, array, FnPtr::new(filter)?) } #[rhai_fn(return_raw, pure)] pub fn all( @@ -585,7 +563,37 @@ mod array_functions { array: &mut Array, filter: FnPtr, ) -> Result> { - all_with_fn_name(ctx, array, filter.fn_name()) + if array.is_empty() { + return Ok(true); + } + + for (i, item) in array.iter().enumerate() { + if !filter + .call_dynamic(&ctx, None, [item.clone()]) + .or_else(|err| match *err { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.starts_with(filter.fn_name()) => + { + filter.call_dynamic(&ctx, None, [item.clone(), (i as INT).into()]) + } + _ => 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) + { + return Ok(false); + } + } + + Ok(true) } #[rhai_fn(name = "all", return_raw, pure)] pub fn all_with_fn_name( @@ -593,44 +601,7 @@ mod array_functions { array: &mut Array, filter: &str, ) -> Result> { - if array.is_empty() { - return Ok(true); - } - - let mut index_val = Dynamic::UNIT; - - for (i, item) in array.iter_mut().enumerate() { - let mut args = [item, &mut index_val]; - - let found = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => - { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? - } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "all".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - if !found { - return Ok(false); - } - } - - Ok(true) + all(ctx, array, FnPtr::new(filter)?) } #[rhai_fn(return_raw)] pub fn dedup(ctx: NativeCallContext, array: &mut Array) -> Result<(), Box> { @@ -641,23 +612,14 @@ mod array_functions { ctx: NativeCallContext, array: &mut Array, comparer: FnPtr, - ) -> Result<(), Box> { - dedup_with_fn_name(ctx, array, comparer.fn_name()) - } - #[rhai_fn(name = "dedup", return_raw)] - fn dedup_with_fn_name( - ctx: NativeCallContext, - array: &mut Array, - comparer: &str, ) -> Result<(), Box> { if array.is_empty() { return Ok(()); } array.dedup_by(|x, y| { - let mut args = [x, &mut y.clone()]; - - ctx.call_fn_raw(comparer, true, false, &mut args) + comparer + .call_dynamic(&ctx, None, [x.clone(), y.clone()]) .unwrap_or_else(|_| Dynamic::FALSE) .as_bool() .unwrap_or(false) @@ -665,13 +627,21 @@ mod array_functions { Ok(()) } + #[rhai_fn(name = "dedup", return_raw)] + fn dedup_with_fn_name( + ctx: NativeCallContext, + array: &mut Array, + comparer: &str, + ) -> Result<(), Box> { + dedup_by_comparer(ctx, array, FnPtr::new(comparer)?) + } #[rhai_fn(return_raw, pure)] pub fn reduce( ctx: NativeCallContext, array: &mut Array, reducer: FnPtr, ) -> Result> { - reduce_with_fn_name(ctx, array, reducer.fn_name()) + reduce_with_initial(ctx, array, reducer, Dynamic::UNIT) } #[rhai_fn(name = "reduce", return_raw, pure)] pub fn reduce_with_fn_name( @@ -679,7 +649,7 @@ mod array_functions { array: &mut Array, reducer: &str, ) -> Result> { - reduce_with_fn_name_with_initial(ctx, array, reducer, Dynamic::UNIT) + reduce(ctx, array, FnPtr::new(reducer)?) } #[rhai_fn(name = "reduce", return_raw, pure)] pub fn reduce_with_initial( @@ -687,35 +657,23 @@ mod array_functions { array: &mut Array, reducer: FnPtr, initial: Dynamic, - ) -> Result> { - reduce_with_fn_name_with_initial(ctx, array, reducer.fn_name(), initial) - } - #[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> { if array.is_empty() { return Ok(initial); } let mut result = initial; - let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter_mut().enumerate() { - let mut args = [&mut result, &mut item.clone(), &mut index_val]; + for (i, item) in array.iter().enumerate() { + let item = item.clone(); - result = ctx - .call_fn_raw(reducer, true, false, &mut args[..2]) + result = reducer + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer) => + if fn_sig.starts_with(reducer.fn_name()) => { - *args[1] = item.clone(); - *args[2] = Dynamic::from(i as INT); - ctx.call_fn_raw(reducer, true, false, &mut args) + reducer.call_dynamic(&ctx, None, [result, item, (i as INT).into()]) } _ => Err(err), }) @@ -731,13 +689,22 @@ mod array_functions { Ok(result) } + #[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> { + reduce_with_initial(ctx, array, FnPtr::new(reducer)?, initial) + } #[rhai_fn(return_raw, pure)] pub fn reduce_rev( ctx: NativeCallContext, array: &mut Array, reducer: FnPtr, ) -> Result> { - reduce_rev_with_fn_name(ctx, array, reducer.fn_name()) + reduce_rev_with_initial(ctx, array, reducer, Dynamic::UNIT) } #[rhai_fn(name = "reduce_rev", return_raw, pure)] pub fn reduce_rev_with_fn_name( @@ -745,7 +712,7 @@ mod array_functions { array: &mut Array, reducer: &str, ) -> Result> { - reduce_rev_with_fn_name_with_initial(ctx, array, reducer, Dynamic::UNIT) + reduce_rev(ctx, array, FnPtr::new(reducer)?) } #[rhai_fn(name = "reduce_rev", return_raw, pure)] pub fn reduce_rev_with_initial( @@ -753,35 +720,23 @@ mod array_functions { array: &mut Array, reducer: FnPtr, initial: Dynamic, - ) -> Result> { - reduce_rev_with_fn_name_with_initial(ctx, array, reducer.fn_name(), initial) - } - #[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> { if array.is_empty() { return Ok(initial); } let mut result = initial; - let mut index_val = Dynamic::UNIT; - for (i, item) in array.iter_mut().enumerate().rev() { - let mut args = [&mut result, &mut item.clone(), &mut index_val]; + for (i, item) in array.iter().enumerate().rev() { + let item = item.clone(); - result = ctx - .call_fn_raw(reducer, true, false, &mut args[..2]) + result = reducer + .call_dynamic(&ctx, None, [result.clone(), item.clone()]) .or_else(|err| match *err { EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(reducer) => + if fn_sig.starts_with(reducer.fn_name()) => { - *args[1] = item.clone(); - *args[2] = Dynamic::from(i as INT); - ctx.call_fn_raw(reducer, true, false, &mut args) + reducer.call_dynamic(&ctx, None, [result, item, (i as INT).into()]) } _ => Err(err), }) @@ -797,6 +752,15 @@ mod array_functions { Ok(result) } + #[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> { + reduce_rev_with_initial(ctx, array, FnPtr::new(reducer)?, initial) + } #[rhai_fn(name = "sort", return_raw)] pub fn sort_with_fn_name( ctx: NativeCallContext, @@ -903,13 +867,52 @@ mod array_functions { Ok(()) } - #[rhai_fn(return_raw, pure)] + #[rhai_fn(return_raw)] pub fn drain( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, ) -> Result> { - drain_with_fn_name(ctx, array, filter.fn_name()) + if array.is_empty() { + return Ok(Array::new()); + } + + let mut drained = Array::with_capacity(array.len()); + + let mut i = 0; + let mut x = 0; + + while x < array.len() { + if filter + .call_dynamic(&ctx, None, [array[x].clone()]) + .or_else(|err| match *err { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.starts_with(filter.fn_name()) => + { + filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()]) + } + _ => 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)); + } else { + x += 1; + } + + i += 1; + } + + Ok(drained) } #[rhai_fn(name = "drain", return_raw)] pub fn drain_with_fn_name( @@ -917,65 +920,7 @@ mod array_functions { array: &mut Array, filter: &str, ) -> Result> { - if array.is_empty() { - return Ok(Array::new()); - } - - let mut index_val = Dynamic::UNIT; - let mut removed = Vec::with_capacity(array.len()); - let mut count = 0; - - for (i, item) in array.iter_mut().enumerate() { - let mut args = [item, &mut index_val]; - - let remove = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => - { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? - } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "drain".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - removed.push(remove); - - if remove { - count += 1; - } - } - - 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()) + drain(ctx, array, FnPtr::new(filter)?) } #[rhai_fn(name = "drain")] pub fn drain_range(array: &mut Array, start: INT, len: INT) -> Array { @@ -1004,13 +949,52 @@ mod array_functions { array.drain(start..start + len).collect() } - #[rhai_fn(return_raw, pure)] + #[rhai_fn(return_raw)] pub fn retain( ctx: NativeCallContext, array: &mut Array, filter: FnPtr, ) -> Result> { - retain_with_fn_name(ctx, array, filter.fn_name()) + if array.is_empty() { + return Ok(Array::new()); + } + + let mut drained = Array::new(); + + let mut i = 0; + let mut x = 0; + + while x < array.len() { + if !filter + .call_dynamic(&ctx, None, [array[x].clone()]) + .or_else(|err| match *err { + EvalAltResult::ErrorFunctionNotFound(fn_sig, _) + if fn_sig.starts_with(filter.fn_name()) => + { + filter.call_dynamic(&ctx, None, [array[x].clone(), (i as INT).into()]) + } + _ => 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)); + } else { + x += 1; + } + + i += 1; + } + + Ok(drained) } #[rhai_fn(name = "retain", return_raw)] pub fn retain_with_fn_name( @@ -1018,65 +1002,7 @@ mod array_functions { array: &mut Array, filter: &str, ) -> Result> { - if array.is_empty() { - return Ok(Array::new()); - } - - let mut index_val = Dynamic::UNIT; - let mut removed = Vec::with_capacity(array.len()); - let mut count = 0; - - for (i, item) in array.iter_mut().enumerate() { - let mut args = [item, &mut index_val]; - - let keep = match ctx.call_fn_raw(filter, true, false, &mut args[..1]) { - Ok(r) => r, - Err(err) => match *err { - EvalAltResult::ErrorFunctionNotFound(fn_sig, _) - if fn_sig.starts_with(filter) => - { - *args[1] = Dynamic::from(i as INT); - ctx.call_fn_raw(filter, true, false, &mut args)? - } - _ => { - return Err(EvalAltResult::ErrorInFunctionCall( - "retain".to_string(), - ctx.source().unwrap_or("").to_string(), - err, - Position::NONE, - ) - .into()) - } - }, - } - .as_bool() - .unwrap_or(false); - - removed.push(!keep); - - if !keep { - count += 1; - } - } - - 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()) + retain(ctx, array, FnPtr::new(filter)?) } #[rhai_fn(name = "retain")] pub fn retain_range(array: &mut Array, start: INT, len: INT) -> Array {