diff --git a/src/func/builtin.rs b/src/func/builtin.rs index 4ab2f938..be09add4 100644 --- a/src/func/builtin.rs +++ b/src/func/builtin.rs @@ -48,6 +48,8 @@ fn is_numeric(type_id: TypeId) -> bool { } /// Build in common binary operator implementations to avoid the cost of calling a registered function. +/// +/// The return function will be registered as a _method_, so the first parameter cannot be consumed. #[must_use] pub fn get_builtin_binary_op_fn( op: &str, @@ -291,28 +293,6 @@ pub fn get_builtin_binary_op_fn( } if type1 == type2 { return match op { - "+" => Some(|_, args| { - let blob1 = &*args[0].read_lock::().expect(BUILTIN); - let blob2 = &*args[1].read_lock::().expect(BUILTIN); - let result = if blob1.is_empty() { - if blob2.is_empty() { - Blob::new() - } else { - blob2.clone() - } - } else { - if blob2.is_empty() { - blob1.clone() - } else { - let mut blob = Blob::with_capacity(blob1.len() + blob2.len()); - blob.extend_from_slice(blob1); - blob.extend_from_slice(blob2); - blob - } - }; - - Ok(Dynamic::from_blob(result)) // do not use result.into() because it'll convert into an Array - }), "==" => Some(impl_op!(Blob == Blob)), "!=" => Some(impl_op!(Blob != Blob)), _ => None, @@ -533,6 +513,8 @@ pub fn get_builtin_binary_op_fn( } /// Build in common operator assignment implementations to avoid the cost of calling a registered function. +/// +/// The return function is registered as a _method_, so the first parameter cannot be consumed. #[must_use] pub fn get_builtin_op_assignment_fn( op: &str, @@ -770,22 +752,31 @@ pub fn get_builtin_op_assignment_fn( }; } + #[cfg(not(feature = "no_index"))] + if type1 == TypeId::of::() { + use crate::packages::array_basic::array_functions::*; + use crate::Array; + + return match op { + "+=" => Some(|_, args| { + let array2 = std::mem::take(args[1]).cast::(); + let array1 = &mut *args[0].write_lock::().expect(BUILTIN); + Ok(append(array1, array2).into()) + }), + _ => None, + }; + } + #[cfg(not(feature = "no_index"))] if type1 == TypeId::of::() { + use crate::packages::blob_basic::blob_functions::*; use crate::Blob; return match op { "+=" => Some(|_, args| { let blob2 = std::mem::take(args[1]).cast::(); - let mut blob1 = args[0].write_lock::().expect(BUILTIN); - if !blob2.is_empty() { - if blob1.is_empty() { - *blob1 = blob2; - } else { - blob1.extend_from_slice(&blob2); - } - } - Ok(Dynamic::UNIT) + let blob1 = &mut *args[0].write_lock::().expect(BUILTIN); + Ok(append(blob1, blob2).into()) }), _ => None, }; diff --git a/src/packages/array_basic.rs b/src/packages/array_basic.rs index 8b9476e8..10c5d7f9 100644 --- a/src/packages/array_basic.rs +++ b/src/packages/array_basic.rs @@ -24,7 +24,7 @@ def_package! { } #[export_module] -mod array_functions { +pub mod array_functions { #[rhai_fn(name = "len", get = "len", pure)] pub fn len(array: &mut Array) -> INT { array.len() as INT @@ -33,26 +33,29 @@ mod array_functions { pub fn push(array: &mut Array, item: Dynamic) { array.push(item); } - #[rhai_fn(name = "append", name = "+=")] - pub fn append(array: &mut Array, y: Array) { - if !y.is_empty() { - if array.is_empty() { - *array = y; + #[rhai_fn(name = "append")] + pub fn append(array1: &mut Array, array2: Array) { + if !array2.is_empty() { + if array1.is_empty() { + *array1 = array2; } else { - array.extend(y); + array1.extend(array2); } } } #[rhai_fn(name = "+")] - pub fn concat(mut array: Array, y: Array) -> Array { - if !y.is_empty() { - if array.is_empty() { - array = y; + pub fn concat(array1: Array, array2: Array) -> Array { + if !array2.is_empty() { + if array1.is_empty() { + array2 } else { - array.extend(y); + let mut array = array1; + array.extend(array2); + array } + } else { + array1 } - array } pub fn insert(array: &mut Array, position: INT, item: Dynamic) { if array.is_empty() { diff --git a/src/packages/blob_basic.rs b/src/packages/blob_basic.rs index bc4e06cd..048b1226 100644 --- a/src/packages/blob_basic.rs +++ b/src/packages/blob_basic.rs @@ -26,7 +26,7 @@ def_package! { } #[export_module] -mod blob_functions { +pub mod blob_functions { pub const fn blob() -> Blob { Blob::new() } @@ -64,12 +64,10 @@ mod blob_functions { pub fn len(blob: &mut Blob) -> INT { blob.len() as INT } - #[rhai_fn(name = "push")] pub fn push(blob: &mut Blob, item: INT) { let item = (item & 0x000000ff) as u8; blob.push(item); } - #[rhai_fn(name = "append")] pub fn append(blob: &mut Blob, y: Blob) { if !y.is_empty() { if blob.is_empty() { @@ -79,6 +77,20 @@ mod blob_functions { } } } + #[rhai_fn(name = "+")] + pub fn concat(blob1: Blob, blob2: Blob) -> Blob { + if !blob2.is_empty() { + if blob1.is_empty() { + blob2 + } else { + let mut blob = blob1; + blob.extend(blob2); + blob + } + } else { + blob1 + } + } pub fn insert(blob: &mut Blob, position: INT, item: INT) { let item = (item & 0x000000ff) as u8; diff --git a/src/packages/mod.rs b/src/packages/mod.rs index d1cd4d02..7f73e774 100644 --- a/src/packages/mod.rs +++ b/src/packages/mod.rs @@ -3,8 +3,8 @@ use crate::{Module, Shared}; pub(crate) mod arithmetic; -mod array_basic; -mod blob_basic; +pub(crate) mod array_basic; +pub(crate) mod blob_basic; mod fn_basic; mod iter_basic; mod lang_core;