diff --git a/doc/src/language/arrays.md b/doc/src/language/arrays.md
index 56706d86..1b654385 100644
--- a/doc/src/language/arrays.md
+++ b/doc/src/language/arrays.md
@@ -30,36 +30,36 @@ Built-in Functions
The following methods (mostly defined in the [`BasicArrayPackage`][packages] but excluded if using a [raw `Engine`]) operate on arrays:
-| Function | Parameter(s) | Description |
-| ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `push` | element to insert | inserts an element at the end |
-| `append` | array to append | concatenates the second array to the end of the first |
-| `+=` operator | 1) array
2) element to insert (not another array) | inserts an element at the end |
-| `+=` operator | 1) array
2) array to append | concatenates the second array to the end of the first |
-| `+` operator | 1) first array
2) second array | concatenates the first array with the second |
-| `insert` | 1) element to insert
2) position, beginning if < 0, end if > length | inserts an element at a certain index |
-| `pop` | _none_ | removes the last element and returns it ([`()`] if empty) |
-| `shift` | _none_ | removes the first element and returns it ([`()`] if empty) |
-| `extract` | 1) start position, beginning if < 0, end if > length,
2) _(optional)_ number of items to extract, none if < 0 | extracts a portion of the array into a new array |
-| `remove` | index | removes an element at a particular index and returns it ([`()`] if the index is not valid) |
-| `reverse` | _none_ | reverses the array |
-| `len` method and property | _none_ | returns the number of elements |
-| `pad` | 1) target length
2) element to pad | pads the array with an element to at least a specified length |
-| `clear` | _none_ | empties the array |
-| `truncate` | target length | cuts off the array at exactly a specified length (discarding all subsequent elements) |
-| `chop` | target length | cuts off the head of the array, leaving the tail at exactly a specified length |
-| `drain` | 1) [function pointer] to predicate (usually a [closure]),
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | removes all items (returning them) that return `true` when called with the predicate function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `drain` | 1) start position, beginning if < 0, end if > length,
2) number of items to remove, none if < 0 | removes a portion of the array, returning the removed items (not in original order) |
-| `retain` | 1) [function pointer] to predicate (usually a [closure]),
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | removes all items (returning them) that do not return `true` when called with the predicate function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `retain` | 1) start position, beginning if < 0, end if > length,
2) number of items to retain, none if < 0 | retains a portion of the array, removes all other items and returning them (not in original order) |
-| `splice` | 1) start position, beginning if < 0, end if > length,
2) number of items to remove, none if < 0,
3) array to insert | replaces a portion of the array with another (not necessarily of the same length as the replaced portion) |
-| `filter` | [function pointer] to predicate (usually a [closure]) | constructs a new array with all items that return `true` when called with the predicate function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `map` | [function pointer] to conversion function (usually a [closure]) | constructs a new array with all items mapped to the result of applying the conversion function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `reduce` | 1) [function pointer] to accumulator function (usually a [closure]),
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | reduces the array into a single value via the accumulator function:
1st parameter: accumulated value ([`()`] initially),
2nd parameter: array item,
3rd parameter: _(optional)_ offset index |
-| `reduce_rev` | 1) [function pointer] to accumulator function (usually a [closure]),
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | reduces the array (in reverse order) into a single value via the accumulator function:
1st parameter: accumulated value ([`()`] initially),
2nd parameter: array item,
3rd parameter: _(optional)_ offset index |
-| `some` | [function pointer] to predicate (usually a [closure]) | returns `true` if any item returns `true` when called with the predicate function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `all` | [function pointer] to predicate (usually a [closure]) | returns `true` if all items return `true` when called with the predicate function:
1st parameter: array item,
2nd parameter: _(optional)_ offset index |
-| `sort` | [function pointer] to a comparison function (usually a [closure]) | sorts the array with a comparison function:
1st parameter: first item,
2nd parameter: second item,
return value: `INT` < 0 if first < second, > 0 if first > second, 0 if first == second |
+| Function | Parameter(s) | Description |
+| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `push` | element to insert | inserts an element at the end |
+| `append` | array to append | concatenates the second array to the end of the first |
+| `+=` operator | 1) array
2) element to insert (not another array) | inserts an element at the end |
+| `+=` operator | 1) array
2) array to append | concatenates the second array to the end of the first |
+| `+` operator | 1) first array
2) second array | concatenates the first array with the second |
+| `insert` | 1) element to insert
2) position, beginning if < 0, end if > length | inserts an element at a certain index |
+| `pop` | _none_ | removes the last element and returns it ([`()`] if empty) |
+| `shift` | _none_ | removes the first element and returns it ([`()`] if empty) |
+| `extract` | 1) start position, beginning if < 0, end if > length
2) _(optional)_ number of items to extract, none if < 0 | extracts a portion of the array into a new array |
+| `remove` | index | removes an element at a particular index and returns it ([`()`] if the index is not valid) |
+| `reverse` | _none_ | reverses the array |
+| `len` method and property | _none_ | returns the number of elements |
+| `pad` | 1) target length
2) element to pad | pads the array with an element to at least a specified length |
+| `clear` | _none_ | empties the array |
+| `truncate` | target length | cuts off the array at exactly a specified length (discarding all subsequent elements) |
+| `chop` | target length | cuts off the head of the array, leaving the tail at exactly a specified length |
+| `drain` | 1) [function pointer] to predicate (usually a [closure])
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | removes all items (returning them) that return `true` when called with the predicate function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `drain` | 1) start position, beginning if < 0, end if > length
2) number of items to remove, none if < 0 | removes a portion of the array, returning the removed items (not in original order) |
+| `retain` | 1) [function pointer] to predicate (usually a [closure])
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | removes all items (returning them) that do not return `true` when called with the predicate function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `retain` | 1) start position, beginning if < 0, end if > length
2) number of items to retain, none if < 0 | retains a portion of the array, removes all other items and returning them (not in original order) |
+| `splice` | 1) start position, beginning if < 0, end if > length
2) number of items to remove, none if < 0
3) array to insert | replaces a portion of the array with another (not necessarily of the same length as the replaced portion) |
+| `filter` | [function pointer] to predicate (usually a [closure]) | constructs a new array with all items that return `true` when called with the predicate function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `map` | [function pointer] to conversion function (usually a [closure]) | constructs a new array with all items mapped to the result of applying the conversion function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `reduce` | 1) [function pointer] to accumulator function (usually a [closure])
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | reduces the array into a single value via the accumulator function:
1st parameter: accumulated value ([`()`] initially)
2nd parameter: array item
3rd parameter: _(optional)_ offset index |
+| `reduce_rev` | 1) [function pointer] to accumulator function (usually a [closure])
2) _(optional)_ [function pointer] to function (usually a [closure]) that provides the initial value | reduces the array (in reverse order) into a single value via the accumulator function:
1st parameter: accumulated value ([`()`] initially)
2nd parameter: array item
3rd parameter: _(optional)_ offset index |
+| `some` | [function pointer] to predicate (usually a [closure]) | returns `true` if any item returns `true` when called with the predicate function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `all` | [function pointer] to predicate (usually a [closure]) | returns `true` if all items return `true` when called with the predicate function:
1st parameter: array item
2nd parameter: _(optional)_ offset index |
+| `sort` | [function pointer] to a comparison function (usually a [closure]) | sorts the array with a comparison function:
1st parameter: first item
2nd parameter: second item
return value: `INT` < 0 if first < second, > 0 if first > second, 0 if first == second |
Use Custom Types With Arrays
diff --git a/doc/src/language/fn-ptr.md b/doc/src/language/fn-ptr.md
index acd301eb..00e9edac 100644
--- a/doc/src/language/fn-ptr.md
+++ b/doc/src/language/fn-ptr.md
@@ -226,7 +226,7 @@ engine.register_raw_fn("super_call",
`FnPtr::call_dynamic` takes a parameter of type `NativeCallContext` which holds the _native call context_
of the particular call to a registered Rust function.
-This type is normally provided by the [`Engine`] (e.g. when using `Engine::register_fn_raw`(../rust/register-raw.md)).
+This type is normally provided by the [`Engine`] (e.g. when using [`Engine::register_fn_raw`](../rust/register-raw.md)).
However, it may also be manually constructed from a tuple:
```rust
diff --git a/doc/src/language/string-fn.md b/doc/src/language/string-fn.md
index 00efd8e1..db3d8b88 100644
--- a/doc/src/language/string-fn.md
+++ b/doc/src/language/string-fn.md
@@ -9,7 +9,7 @@ using a [raw `Engine`]) operate on [strings]:
| Function | Parameter(s) | Description |
| ------------------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `len` method and property | _none_ | returns the number of characters (not number of bytes) in the string |
-| `pad` | 1) character to pad
2) target length | pads the string with an character to at least a specified length |
+| `pad` | 1) target length
2) character/string to pad | pads the string with a character or a string to at least a specified length |
| `+=` operator, `append` | character/string to append | Adds a character or a string to the end of another string |
| `clear` | _none_ | empties the string |
| `truncate` | target length | cuts off the string at exactly a specified number of characters |
diff --git a/doc/src/plugins/function.md b/doc/src/plugins/function.md
index 904d56be..bd31de0c 100644
--- a/doc/src/plugins/function.md
+++ b/doc/src/plugins/function.md
@@ -102,9 +102,10 @@ as a parameter to the function, thereby implementing a _callback_:
use rhai::{Dynamic, FnPtr, NativeCallContext, EvalAltResult};
use rhai::plugin::*; // a "prelude" import for macros
-#[export_fn(return_raw)]
+#[export_fn]
+#[rhai_fn(return_raw)]
pub fn greet(context: NativeCallContext, callback: FnPtr)
- -> Result>
+ -> Result>
{
// Call the callback closure with the current context
// to obtain the name to greet!
@@ -116,15 +117,16 @@ pub fn greet(context: NativeCallContext, callback: FnPtr)
The native call context is also useful in another scenario: protecting a function from malicious scripts.
```rust
-use rhai::{Dynamic, INT, Array, NativeCallContext, EvalAltResult, Position};
+use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, Position};
use rhai::plugin::*; // a "prelude" import for macros
// This function builds an array of arbitrary size, but is protected
// against attacks by first checking with the allowed limit set
// into the 'Engine'.
-#[export_fn(return_raw)]
-pub fn grow(context: NativeCallContext, size: INT)
- -> Result>
+#[export_fn]
+#[rhai_fn(return_raw)]
+pub fn grow(context: NativeCallContext, size: i64)
+ -> Result>
{
// Make sure the function does not generate a
// data structure larger than the allowed limit
diff --git a/doc/src/plugins/module.md b/doc/src/plugins/module.md
index aeaeeb58..81195d47 100644
--- a/doc/src/plugins/module.md
+++ b/doc/src/plugins/module.md
@@ -363,7 +363,7 @@ use rhai::plugin::*; // a "prelude" import for macros
mod my_module {
#[rhai_fn(return_raw)]
pub fn greet(context: NativeCallContext, callback: FnPtr)
- -> Result>
+ -> Result>
{
// Call the callback closure with the current context
// to obtain the name to greet!
@@ -376,7 +376,7 @@ mod my_module {
The native call context is also useful in another scenario: protecting a function from malicious scripts.
```rust
-use rhai::{Dynamic, INT, Array, NativeCallContext, EvalAltResult, Position};
+use rhai::{Dynamic, Array, NativeCallContext, EvalAltResult, Position};
use rhai::plugin::*; // a "prelude" import for macros
#[export_module]
@@ -385,8 +385,8 @@ mod my_module {
// against attacks by first checking with the allowed limit set
// into the 'Engine'.
#[rhai_fn(return_raw)]
- pub fn grow(context: NativeCallContext, size: INT)
- -> Result>
+ pub fn grow(context: NativeCallContext, size: i64)
+ -> Result>
{
// Make sure the function does not generate a
// data structure larger than the allowed limit
diff --git a/doc/src/rust/register-raw.md b/doc/src/rust/register-raw.md
index 78990e1c..dc4e3ca2 100644
--- a/doc/src/rust/register-raw.md
+++ b/doc/src/rust/register-raw.md
@@ -60,7 +60,8 @@ Function Signature
The function signature passed to `Engine::register_raw_fn` takes the following form:
-> `Fn(context: NativeCallContext, args: &mut [&mut Dynamic]) -> Result> + 'static`
+> `Fn(context: NativeCallContext, args: &mut [&mut Dynamic])`
+> `-> Result> + 'static`
where:
diff --git a/src/packages/string_more.rs b/src/packages/string_more.rs
index 1a311b5d..cd71fd41 100644
--- a/src/packages/string_more.rs
+++ b/src/packages/string_more.rs
@@ -58,54 +58,6 @@ def_package!(crate:MoreStringPackage:"Additional string utilities, including str
combine_with_exported_module!(lib, "string", string_functions);
- lib.set_raw_fn(
- "pad",
- &[TypeId::of::(), TypeId::of::(), TypeId::of::()],
- |_context, args| {
- let len = *args[1].read_lock::().unwrap();
-
- // Check if string will be over max size limit
- #[cfg(not(feature = "unchecked"))]
- if _context.engine().max_string_size() > 0 && len > 0
- && (len as usize) > _context.engine().max_string_size()
- {
- return EvalAltResult::ErrorDataTooLarge(
- "Length of string".to_string(),
- _context.engine().max_string_size(),
- len as usize,
- Position::none(),
- ).into();
- }
-
- if len > 0 {
- let ch = mem::take(args[2]).cast::();
- let mut s = args[0].write_lock::().unwrap();
-
- let orig_len = s.chars().count();
-
- if len as usize > orig_len {
- let p = s.make_mut();
-
- for _ in 0..(len as usize - orig_len) {
- p.push(ch);
- }
-
- #[cfg(not(feature = "unchecked"))]
- if _context.engine().max_string_size() > 0 && s.len() > _context.engine().max_string_size() {
- return EvalAltResult::ErrorDataTooLarge(
- "Length of string".to_string(),
- _context.engine().max_string_size(),
- s.len(),
- Position::none(),
- ).into();
- }
- }
- }
-
- Ok(())
- },
- );
-
// Register string iterator
lib.set_iter(
TypeId::of::(),
@@ -176,7 +128,7 @@ mod string_functions {
pub fn index_of_char_starting_from(s: &str, ch: char, start: INT) -> INT {
let start = if start < 0 {
0
- } else if (start as usize) >= s.chars().count() {
+ } else if start as usize >= s.chars().count() {
return -1 as INT;
} else {
s.chars().take(start as usize).collect::().len()
@@ -197,7 +149,7 @@ mod string_functions {
pub fn index_of_string_starting_from(s: &str, find: ImmutableString, start: INT) -> INT {
let start = if start < 0 {
0
- } else if (start as usize) >= s.chars().count() {
+ } else if start as usize >= s.chars().count() {
return -1 as INT;
} else {
s.chars().take(start as usize).collect::().len()
@@ -220,7 +172,7 @@ mod string_functions {
return "".to_string().into();
} else if start < 0 {
0
- } else if (start as usize) >= s.chars().count() {
+ } else if start as usize >= s.chars().count() {
return "".to_string().into();
} else {
start as usize
@@ -228,7 +180,7 @@ mod string_functions {
let chars: StaticVec<_> = s.chars().collect();
- let len = if offset + (len as usize) > chars.len() {
+ let len = if offset + len as usize > chars.len() {
chars.len() - offset
} else {
len as usize
@@ -255,7 +207,7 @@ mod string_functions {
return;
} else if start < 0 {
0
- } else if (start as usize) >= s.chars().count() {
+ } else if start as usize >= s.chars().count() {
s.make_mut().clear();
return;
} else {
@@ -264,7 +216,7 @@ mod string_functions {
let chars: StaticVec<_> = s.chars().collect();
- let len = if offset + (len as usize) > chars.len() {
+ let len = if offset + len as usize > chars.len() {
chars.len() - offset
} else {
len as usize
@@ -295,6 +247,104 @@ mod string_functions {
pub fn replace_char(s: &mut ImmutableString, find: char, sub: char) {
*s = s.replace(&find.to_string(), &sub.to_string()).into();
}
+ #[rhai_fn(return_raw)]
+ pub fn pad(
+ _context: NativeCallContext,
+ s: &mut ImmutableString,
+ len: INT,
+ ch: char,
+ ) -> Result> {
+ // Check if string will be over max size limit
+ #[cfg(not(feature = "unchecked"))]
+ if _context.engine().max_string_size() > 0
+ && len as usize > _context.engine().max_string_size()
+ {
+ return EvalAltResult::ErrorDataTooLarge(
+ "Length of string".to_string(),
+ _context.engine().max_string_size(),
+ len as usize,
+ Position::none(),
+ )
+ .into();
+ }
+
+ if len > 0 {
+ let orig_len = s.chars().count();
+
+ if len as usize > orig_len {
+ let p = s.make_mut();
+
+ for _ in 0..(len as usize - orig_len) {
+ p.push(ch);
+ }
+
+ #[cfg(not(feature = "unchecked"))]
+ if _context.engine().max_string_size() > 0
+ && s.len() > _context.engine().max_string_size()
+ {
+ return EvalAltResult::ErrorDataTooLarge(
+ "Length of string".to_string(),
+ _context.engine().max_string_size(),
+ s.len(),
+ Position::none(),
+ )
+ .into();
+ }
+ }
+ }
+
+ Ok(().into())
+ }
+ #[rhai_fn(name = "pad", return_raw)]
+ pub fn pad_with_string(
+ _context: NativeCallContext,
+ s: &mut ImmutableString,
+ len: INT,
+ padding: &str,
+ ) -> Result> {
+ // Check if string will be over max size limit
+ #[cfg(not(feature = "unchecked"))]
+ if _context.engine().max_string_size() > 0
+ && len as usize > _context.engine().max_string_size()
+ {
+ return EvalAltResult::ErrorDataTooLarge(
+ "Length of string".to_string(),
+ _context.engine().max_string_size(),
+ len as usize,
+ Position::none(),
+ )
+ .into();
+ }
+
+ if len > 0 {
+ let mut str_len = s.chars().count();
+ let padding_len = padding.chars().count();
+
+ if len as usize > str_len {
+ let p = s.make_mut();
+
+ while str_len < len as usize {
+ p.push_str(padding);
+ str_len += padding_len;
+ }
+
+ #[cfg(not(feature = "unchecked"))]
+ if _context.engine().max_string_size() > 0
+ && s.len() > _context.engine().max_string_size()
+ {
+ return EvalAltResult::ErrorDataTooLarge(
+ "Length of string".to_string(),
+ _context.engine().max_string_size(),
+ s.len(),
+ Position::none(),
+ )
+ .into();
+ }
+ }
+ }
+
+ Ok(().into())
+ }
#[cfg(not(feature = "no_index"))]
pub mod arrays {