diff --git a/doc/book.toml b/doc/book.toml index 44097145..a48eadaf 100644 --- a/doc/book.toml +++ b/doc/book.toml @@ -7,10 +7,16 @@ language = "en" [output.html] no-section-label = true git-repository-url = "https://github.com/jonathandturner/rhai" +curly-quotes = true [output.html.fold] enable = true level = 4 +[outputX.linkcheck] +follow-web-links = false +traverse-parent-directories = false +warning-policy = "ignore" + [preprocessor.tera] command = "mdbook-tera --json ./src/context.json" diff --git a/doc/src/SUMMARY.md b/doc/src/SUMMARY.md index 756f642a..da62423b 100644 --- a/doc/src/SUMMARY.md +++ b/doc/src/SUMMARY.md @@ -4,7 +4,7 @@ The Rhai Scripting Language 1. [What is Rhai](about.md) 1. [Features](about/features.md) 2. [Supported Targets and Builds](about/targets.md) - 3. [What Rhai Doesn't Do](about/non-design.md) + 3. [What Rhai Isn't](about/non-design.md) 4. [Related Resources](about/related.md) 2. [Getting Started](start.md) 1. [Install the Rhai Crate](start/install.md) @@ -12,7 +12,7 @@ The Rhai Scripting Language 3. [Special Builds](start/builds.md) 1. [Performance Build](start/builds/performance.md) 2. [Minimal Build](start/builds/minimal.md) - 3. [`no-std` Build](start/builds/no-std.md) + 3. [no-std Build](start/builds/no-std.md) 4. [WebAssembly (WASM)](start/builds/wasm.md) 4. [Examples](start/examples.md) 1. [Rust](start/examples/rust.md) @@ -23,14 +23,16 @@ The Rhai Scripting Language 3. [Call a Rhai Function from Rust](engine/call-fn.md) 4. [Create a Rust Anonymous Function from a Rhai Function](engine/func.md) 5. [Evaluate Expressions Only](engine/expressions.md) - 6. [Raw `Engine`](engine/raw.md) + 6. [Raw Engine](engine/raw.md) 4. [Extend Rhai with Rust](rust.md) 1. [Traits](rust/traits.md) 2. [Register a Rust Function](rust/functions.md) - 1. [`String` Parameters in Rust Functions](rust/strings.md) + 1. [String Parameters in Rust Functions](rust/strings.md) 3. [Register a Generic Rust Function](rust/generic.md) 4. [Register a Fallible Rust Function](rust/fallible.md) 5. [Packages](rust/packages.md) + 1. [Built-in Packages](rust/packages/builtin.md) + 2. [Create a Custom Package](rust/packages/create.md) 6. [Override a Built-in Function](rust/override.md) 7. [Operator Overloading](rust/operators.md) 8. [Register a Custom Type and its Methods](rust/custom.md) @@ -38,13 +40,13 @@ The Rhai Scripting Language 2. [Indexers](rust/indexers.md) 3. [Disable Custom Types](rust/disable-custom.md) 4. [Printing Custom Types](rust/print-custom.md) - 9. [`Scope` - Initializing and Maintaining State](rust/scope.md) + 9. [Scope - Initializing and Maintaining State](rust/scope.md) 10. [Engine Configuration Options](rust/options.md) 5. [Rhai Language Reference](language.md) 1. [Comments](language/comments.md) 2. [Values and Types](language/values-and-types.md) - 1. [`Dynamic` Values](language/dynamic.md) - 2. [`type-of`](language/type-of.md) + 1. [Dynamic Values](language/dynamic.md) + 2. [type-of()](language/type-of.md) 3. [Numbers](language/numbers.md) 1. [Operators](language/num-op.md) 2. [Functions](language/num-fn.md) @@ -71,11 +73,12 @@ The Rhai Scripting Language 2. [Call Method as Function](language/method.md) 15. [Print and Debug](language/print-debug.md) 16. [Modules](language/modules.md) - 1. [Export Variables and Functions](language/modules/export.md) + 1. [Export Variables, Functions and Sub-Modules](language/modules/export.md) 2. [Import Modules](language/modules/import.md) 3. [Create from Rust](language/modules/rust.md) - 4. [Create from `AST`](language/modules/ast.md) + 4. [Create from AST](language/modules/ast.md) 5. [Module Resolvers](language/modules/resolvers.md) + 1. [Implement a Custom Module Resolver](language/modules/imp-resolver.md) 6. [Safety and Protection](safety.md) 1. [Checked Arithmetic](safety/checked.md) 2. [Sand-Boxing](safety/sandbox.md) diff --git a/doc/src/about/non-design.md b/doc/src/about/non-design.md index d5496657..2b07946e 100644 --- a/doc/src/about/non-design.md +++ b/doc/src/about/non-design.md @@ -1,5 +1,5 @@ -What Rhai Doesn't Do -==================== +What Rhai Isn't +=============== {{#include ../links.md}} diff --git a/doc/src/about/targets.md b/doc/src/about/targets.md index 68395396..70124e61 100644 --- a/doc/src/about/targets.md +++ b/doc/src/about/targets.md @@ -7,6 +7,6 @@ The following targets and builds are support by Rhai: * All common CPU targets for Windows, Linux and MacOS. -* [WASM] +* WebAssembly ([WASM]) * [`no-std`] diff --git a/doc/src/engine/raw.md b/doc/src/engine/raw.md index fa054abe..ed7154ed 100644 --- a/doc/src/engine/raw.md +++ b/doc/src/engine/raw.md @@ -5,20 +5,22 @@ Raw `Engine` {{#include ../links.md}} `Engine::new` creates a scripting [`Engine`] with common functionalities (e.g. printing to the console via `print`). -In many controlled embedded environments, however, these are not needed. -Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of basic arithmetic and logical operators -are supported. +In many controlled embedded environments, however, these may not be needed and unnecessarily occupy +program code storage space. + +Use `Engine::new_raw` to create a _raw_ `Engine`, in which only a minimal set of +basic arithmetic and logical operators are supported. Built-in Operators ------------------ -| Operators | Assignment operators | Supported for type (see [standard types]) | +| Operators | Assignment operators | Supported for types (see [standard types]) | | ------------------------ | ---------------------------- | ----------------------------------------------------------------------------- | | `+`, | `+=` | `INT`, `FLOAT` (if not [`no_float`]), `ImmutableString` | | `-`, `*`, `/`, `%`, `~`, | `-=`, `*=`, `/=`, `%=`, `~=` | `INT`, `FLOAT` (if not [`no_float`]) | | `<<`, `>>`, `^`, | `<<=`, `>>=`, `^=` | `INT` | -| `&`, `\|`, | `&=`, `\|=` | `INT`, `bool` | -| `&&`, `\|\|` | | `bool` | +| `&`, `|`, | `&=`, `|=` | `INT`, `bool` | +| `&&`, `||` | | `bool` | | `==`, `!=` | | `INT`, `FLOAT` (if not [`no_float`]), `bool`, `char`, `()`, `ImmutableString` | | `>`, `>=`, `<`, `<=` | | `INT`, `FLOAT` (if not [`no_float`]), `char`, `()`, `ImmutableString` | diff --git a/doc/src/language/logic.md b/doc/src/language/logic.md index 3be2f9f4..057408b5 100644 --- a/doc/src/language/logic.md +++ b/doc/src/language/logic.md @@ -40,9 +40,9 @@ Boolean operators | -------- | ------------------------------------- | | `!` | Boolean _Not_ | | `&&` | Boolean _And_ (short-circuits) | -| `\|\|` | Boolean _Or_ (short-circuits) | +| `||` | Boolean _Or_ (short-circuits) | | `&` | Boolean _And_ (doesn't short-circuit) | -| `\|` | Boolean _Or_ (doesn't short-circuit) | +| `|` | Boolean _Or_ (doesn't short-circuit) | Double boolean operators `&&` and `||` _short-circuit_, meaning that the second operand will not be evaluated if the first one already proves the condition wrong. diff --git a/doc/src/language/modules.md b/doc/src/language/modules.md index 002765f6..6b616103 100644 --- a/doc/src/language/modules.md +++ b/doc/src/language/modules.md @@ -5,3 +5,14 @@ Modules Rhai allows organizing code (functions, both Rust-based or script-based, and variables) into _modules_. Modules can be disabled via the [`no_module`] feature. + +A module is of the type `Module` and encapsulates a Rhai script together with the functions defined +by that script. + +The script text is run, variables are then selectively exposed via the [`export`] statement. +Functions defined by the script are automatically exported. + +Modules loaded within this module at the global level become _sub-modules_ and are also automatically exported. + +Other scripts can then load this module and use the variables and functions exported +as if they were defined inside the same script. diff --git a/doc/src/language/modules/export.md b/doc/src/language/modules/export.md index 0861bc0f..9ab2b9e3 100644 --- a/doc/src/language/modules/export.md +++ b/doc/src/language/modules/export.md @@ -1,17 +1,53 @@ -Export Variables and Functions from Modules -========================================== +Export Variables, Functions and Sub-Modules in Module +=================================================== {{#include ../../links.md}} -A _module_ is a single script (or pre-compiled `AST`) containing global variables and functions. +A _module_ is a single script (or pre-compiled `AST`) containing global variables, functions and sub-modules. + +A module can be created from a script via the `Module::eval_ast_as_new` method. When given an `AST`, +it is first evaluated, then the following items are exposed as members of the new module: + +* Global variables - essentially all variables that remain in the [`Scope`] at the end of a script run - that are exported. Variables not exported (via the `export` statement) remain hidden. + +* Functions not specifically marked `private`. + +* Global modules that remain in the [`Scope`] at the end of a script run. + + +Global Variables +---------------- The `export` statement, which can only be at global level, exposes selected variables as members of a module. -Variables not exported are _private_ and invisible to the outside. +Variables not exported are _private_ and hidden to the outside. -On the other hand, all functions are automatically exported, _unless_ it is explicitly opt-out with the [`private`] prefix. +```rust +// This is a module script. -Functions declared [`private`] are invisible to the outside. +let private = 123; // variable not exported - default hidden +let x = 42; // this will be exported below + +export x; // the variable 'x' is exported under its own name + +export x as answer; // the variable 'x' is exported under the alias 'answer' + // another script can load this module and access 'x' as 'module::answer' + +{ + let inner = 0; // local variable - it disappears when the statement block ends, + // therefore it is not 'global' and is not exported + + export inner; // exporting an temporary variable has no effect +} +``` + + +Functions +--------- + +All functions are automatically exported, _unless_ it is explicitly opt-out with the [`private`] prefix. + +Functions declared [`private`] are hidden to the outside. Everything exported from a module is **constant** (**read-only**). @@ -20,13 +56,25 @@ Everything exported from a module is **constant** (**read-only**). fn inc(x) { x + 1 } // script-defined function - default public -private fn foo() {} // private function - invisible to outside - -let private = 123; // variable not exported - default invisible to outside -let x = 42; // this will be exported below - -export x; // the variable 'x' is exported under its own name - -export x as answer; // the variable 'x' is exported under the alias 'answer' - // another script can load this module and access 'x' as 'module::answer' +private fn foo() {} // private function - hidden +``` + + +Sub-Modules +----------- + +All loaded modules are automatically exported as sub-modules. + +To prevent a module from being exported, load it inside a block statement so that it goes away at the +end of the block. + +```rust +// This is a module script. + +import "hello" as foo; // exported as sub-module 'foo' + +{ + import "world" as bar; // not exported - the module disappears at the end + // of the statement block and is not 'global' +} ``` diff --git a/doc/src/language/modules/imp-resolver.md b/doc/src/language/modules/imp-resolver.md new file mode 100644 index 00000000..15de7253 --- /dev/null +++ b/doc/src/language/modules/imp-resolver.md @@ -0,0 +1,60 @@ +Implement a Custom Module Resolver +================================= + +{{#include ../../links.md}} + +For many applications in which Rhai is embedded, it is necessary to customize the way that modules +are resolved. For instance, modules may need to be loaded from script texts stored in a database, +not in the file system. + +A module resolver must implement the trait `rhai::ModuleResolver`, which contains only one function: +`resolve`. + +When Rhai prepares to load a module, `ModuleResolver::resolve` is called with the name +of the _module path_ (i.e. the path specified in the [`import`] statement). Upon success, it should +return a [`Module`]; if the module cannot be load, return `EvalAltResult::ErrorModuleNotFound`. + +Example +------- + +```rust +use rhai::{ModuleResolver, Module, Engine, EvalAltResult}; + +// Define a custom module resolver. +struct MyModuleResolver {} + +// Implement the 'ModuleResolver' trait. +impl ModuleResolver for MyModuleResolver { + // Only required function. + fn resolve( + &self, + engine: &Engine, // reference to the current 'Engine' + path: &str, // the module path + pos: Position, // location of the 'import' statement + ) -> Result> { + // Check module path. + if is_valid_module_path(path) { + // Load the custom module. + let module: Module = load_secret_module(path); + Ok(module) + } else { + Err(Box::new(EvalAltResult::ErrorModuleNotFound(path.into(), pos))) + } + } +} + +fn main() -> Result<(), Box> { + let mut engine = Engine::new(); + + // Set the custom module resolver into the 'Engine'. + engine.set_module_resolver(Some(MyModuleResolver {})); + + engine.consume(r#" + import "hello" as foo; // this 'import' statement will call + // 'MyModuleResolver::resolve' with "hello" as path + foo:bar(); + "#)?; + + Ok(()) +} +``` diff --git a/doc/src/language/modules/import.md b/doc/src/language/modules/import.md index 0269fdfd..536e0745 100644 --- a/doc/src/language/modules/import.md +++ b/doc/src/language/modules/import.md @@ -18,10 +18,11 @@ lock::status = "off"; // <- runtime error - cannot modify a constant ``` `import` statements are _scoped_, meaning that they are only accessible inside the scope that they're imported. -They can appear anywhere a normal statement can be, but in the vast majority of cases `import` statements are -group at the beginning of a script. -It is, however, not advised to deviate from this common practice unless there is a _Very Good Reason™_. +They can appear anywhere a normal statement can be, but in the vast majority of cases `import` statements are +group at the beginning of a script. It is, however, not advised to deviate from this common practice unless +there is a _Very Good Reason™_. + Especially, do not place an `import` statement within a loop; doing so will repeatedly re-load the same module during every iteration of the loop! @@ -34,7 +35,7 @@ if secured { // new block scope c::encrypt(key); // use a function in the module } // the module disappears at the end of the block scope -crypto::encrypt(others); // <- this causes a run-time error because the 'crypto' module +c::encrypt(others); // <- this causes a run-time error because the 'crypto' module // is no longer available! for x in range(0, 1000) { diff --git a/doc/src/language/num-op.md b/doc/src/language/num-op.md index 290c4aa7..a7bd524d 100644 --- a/doc/src/language/num-op.md +++ b/doc/src/language/num-op.md @@ -31,7 +31,7 @@ Binary Operators | `%` | Modulo (remainder) | | | `~` | Power | | | `&` | Binary _And_ bit-mask | Yes | -| `\|` | Binary _Or_ bit-mask | Yes | +| `|` | Binary _Or_ bit-mask | Yes | | `^` | Binary _Xor_ bit-mask | Yes | | `<<` | Left bit-shift | Yes | | `>>` | Right bit-shift | Yes | diff --git a/doc/src/language/values-and-types.md b/doc/src/language/values-and-types.md index 21bb2474..2aef02c3 100644 --- a/doc/src/language/values-and-types.md +++ b/doc/src/language/values-and-types.md @@ -5,20 +5,20 @@ Values and Types The following primitive types are supported natively: -| Category | Equivalent Rust types | [`type_of()`] | `to_string()` | -| ------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------- | --------------------- | -| **Integer number** | `u8`, `i8`, `u16`, `i16`,
`u32`, `i32` (default for [`only_i32`]),
`u64`, `i64` _(default)_ | `"i32"`, `"u64"` etc. | `"42"`, `"123"` etc. | -| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | `"f32"` or `"f64"` | `"123.4567"` etc. | -| **Boolean value** | `bool` | `"bool"` | `"true"` or `"false"` | -| **Unicode character** | `char` | `"char"` | `"A"`, `"x"` etc. | -| **Immutable Unicode string** | `rhai::ImmutableString` (implemented as `Rc` or `Arc`) | `"string"` | `"hello"` etc. | -| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ?, ?, ? ]"` | -| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `#{ "a": 1, "b": 2 }` | -| **Timestamp** (implemented in the [`BasicTimePackage`]({{rootUrl}}/rust/packages.md)) | `std::time::Instant` | `"timestamp"` | _not supported_ | -| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ | -| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. | -| **System floating-point** (current configuration, disabled with [`no_float`]) | `rhai::FLOAT` (`f32` or `f64`) | `"f32"` or `"f64"` | `"123.456"` etc. | -| **Nothing/void/nil/null** (or whatever it is called) | `()` | `"()"` | `""` _(empty string)_ | +| Category | Equivalent Rust types | [`type_of()`] | `to_string()` | +| --------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | --------------------- | --------------------- | +| **Integer number** | `u8`, `i8`, `u16`, `i16`,
`u32`, `i32` (default for [`only_i32`]),
`u64`, `i64` _(default)_ | `"i32"`, `"u64"` etc. | `"42"`, `"123"` etc. | +| **Floating-point number** (disabled with [`no_float`]) | `f32`, `f64` _(default)_ | `"f32"` or `"f64"` | `"123.4567"` etc. | +| **Boolean value** | `bool` | `"bool"` | `"true"` or `"false"` | +| **Unicode character** | `char` | `"char"` | `"A"`, `"x"` etc. | +| **Immutable Unicode string** | `rhai::ImmutableString` (implemented as `Rc` or `Arc`) | `"string"` | `"hello"` etc. | +| **Array** (disabled with [`no_index`]) | `rhai::Array` | `"array"` | `"[ ?, ?, ? ]"` | +| **Object map** (disabled with [`no_object`]) | `rhai::Map` | `"map"` | `#{ "a": 1, "b": 2 }` | +| **Timestamp** (implemented in the [`BasicTimePackage`]({{rootUrl}}/rust/packages.md), disabled with [`no_std`]) | `std::time::Instant` ([instant::Instant](https://crates.io/crates/instant) if not [WASM] build) | `"timestamp"` | _not supported_ | +| **Dynamic value** (i.e. can be anything) | `rhai::Dynamic` | _the actual type_ | _actual value_ | +| **System integer** (current configuration) | `rhai::INT` (`i32` or `i64`) | `"i32"` or `"i64"` | `"42"`, `"123"` etc. | +| **System floating-point** (current configuration, disabled with [`no_float`]) | `rhai::FLOAT` (`f32` or `f64`) | `"f32"` or `"f64"` | `"123.456"` etc. | +| **Nothing/void/nil/null/Unit** (or whatever it is called) | `()` | `"()"` | `""` _(empty string)_ | All types are treated strictly separate by Rhai, meaning that `i32` and `i64` and `u32` are completely different - they even cannot be added together. This is very similar to Rust. diff --git a/doc/src/links.md b/doc/src/links.md index a6bb5f68..cc4dd9f0 100644 --- a/doc/src/links.md +++ b/doc/src/links.md @@ -17,7 +17,7 @@ [WASM]: {{rootUrl}}/start/builds/wasm.md [`Engine`]: {{rootUrl}}/engine/hello-world.md -[`private`]: {{rootUrl}}/engine/call_fn.md +[`private`]: {{rootUrl}}/engine/call-fn.md [`Func`]: {{rootUrl}}/engine/func.md [`eval_expression`]: {{rootUrl}}/engine/expressions.md [`eval_expression_with_scope`]: {{rootUrl}}/engine/expressions.md @@ -27,7 +27,7 @@ [packages]: {{rootUrl}}/rust/packages.md [`Scope`]: {{rootUrl}}/rust/scope.md -[`type_of()`]: {{rootUrl}}/language/type_of.md +[`type_of()`]: {{rootUrl}}/language/type-of.md [`to_string()`]: {{rootUrl}}/language/values-and-types.md [`()`]: {{rootUrl}}/language/values-and-types.md [standard types]: {{rootUrl}}/language/values-and-types.md @@ -35,8 +35,8 @@ [`to_int`]: {{rootUrl}}/language/convert.md [`to_float`]: {{rootUrl}}/language/convert.md -[custom type]: {{rootUrl}}/language/custom.md -[custom types]: {{rootUrl}}/language/custom.md +[custom type]: {{rootUrl}}/rust/custom.md +[custom types]: {{rootUrl}}/rust/custom.md [`print`]: {{rootUrl}}/language/print-debug.md [`debug`]: {{rootUrl}}/language/print-debug.md diff --git a/doc/src/rust/builtin-packages.md b/doc/src/rust/builtin-packages.md new file mode 100644 index 00000000..f77cc900 --- /dev/null +++ b/doc/src/rust/builtin-packages.md @@ -0,0 +1 @@ +# Built-in Packages diff --git a/doc/src/rust/packages.md b/doc/src/rust/packages.md index df58b56a..6f8c5b6c 100644 --- a/doc/src/rust/packages.md +++ b/doc/src/rust/packages.md @@ -8,6 +8,12 @@ Standard built-in Rhai features are provided in various _packages_ that can be l Packages reside under `rhai::packages::*` and the trait `rhai::packages::Package` must be loaded in order for packages to be used. +Packages typically contain Rust functions that are callable within a Rhai script. +All functions registered in a package is loaded under the _global namespace_ (i.e. they're available without module qualifiers). + +Once a package is created (e.g. via `new`), it can be _shared_ (via `get`) among multiple instances of [`Engine`], +even across threads (under [`sync`]). Therefore, a package only has to be created _once_. + ```rust use rhai::Engine; use rhai::packages::Package // load the 'Package' trait to use packages @@ -19,34 +25,14 @@ let package = CorePackage::new(); // create a package - can be shared among mu engine.load_package(package.get()); // load the package manually. 'get' returns a reference to the shared package ``` -The follow packages are available: -| Package | Description | In `Core` | In `Standard` | -| ---------------------- | ------------------------------------------------------------------------------------------------------ | :-------: | :-----------: | -| `ArithmeticPackage` | Arithmetic operators (e.g. `+`, `-`, `*`, `/`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes | -| `BasicIteratorPackage` | Numeric ranges (e.g. `range(1, 10)`) | Yes | Yes | -| `LogicPackage` | Logical and comparison operators (e.g. `==`, `>`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes | -| `BasicStringPackage` | Basic string functions (e.g. `print`, `debug`, `len`) that are not built in | Yes | Yes | -| `BasicTimePackage` | Basic time functions (e.g. [timestamps]) | Yes | Yes | -| `MoreStringPackage` | Additional string functions, including converting common types to string | No | Yes | -| `BasicMathPackage` | Basic math functions (e.g. `sin`, `sqrt`) | No | Yes | -| `BasicArrayPackage` | Basic [array] functions (not available under `no_index`) | No | Yes | -| `BasicMapPackage` | Basic [object map] functions (not available under `no_object`) | No | Yes | -| `EvalPackage` | Disable [`eval`] | No | No | -| `CorePackage` | Basic essentials | Yes | Yes | -| `StandardPackage` | Standard library (default for `Engine::new`) | No | Yes | - -Packages typically contain Rust functions that are callable within a Rhai script. -All functions registered in a package is loaded under the _global namespace_ (i.e. they're available without module qualifiers). - -Once a package is created (e.g. via `new`), it can be _shared_ (via `get`) among multiple instances of [`Engine`], -even across threads (under [`sync`]). Therefore, a package only has to be created _once_. +Difference Between a Package and a Module +---------------------------------------- Packages are actually implemented as [modules], so they share a lot of behavior and characteristics. + The main difference is that a package loads under the _global_ namespace, while a module loads under its own namespace alias specified in an [`import`] statement (see also [modules]). A package is _static_ (i.e. pre-loaded into an [`Engine`]), while a module is _dynamic_ (i.e. loaded with the `import` statement). - -Custom packages can also be created. See the macro [`def_package!`](https://docs.rs/rhai/0.13.0/rhai/macro.def_package.html). diff --git a/doc/src/rust/packages/builtin.md b/doc/src/rust/packages/builtin.md new file mode 100644 index 00000000..da33bfe4 --- /dev/null +++ b/doc/src/rust/packages/builtin.md @@ -0,0 +1,39 @@ +Built-In Packages +================ + +{{#include ../../links.md}} + +`Engine::new` creates an [`Engine`] with the `StandardPackage` loaded. + +`Engine::new_raw` creates an [`Engine`] with _no_ package loaded. + +| Package | Description | In `Core` | In `Standard` | +| ---------------------- | ------------------------------------------------------------------------------------------------------ | :-------: | :-----------: | +| `ArithmeticPackage` | Arithmetic operators (e.g. `+`, `-`, `*`, `/`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes | +| `BasicIteratorPackage` | Numeric ranges (e.g. `range(1, 10)`) | Yes | Yes | +| `LogicPackage` | Logical and comparison operators (e.g. `==`, `>`) for numeric types that are not built in (e.g. `u16`) | Yes | Yes | +| `BasicStringPackage` | Basic string functions (e.g. `print`, `debug`, `len`) that are not built in | Yes | Yes | +| `BasicTimePackage` | Basic time functions (e.g. [timestamps]) | Yes | Yes | +| `MoreStringPackage` | Additional string functions, including converting common types to string | No | Yes | +| `BasicMathPackage` | Basic math functions (e.g. `sin`, `sqrt`) | No | Yes | +| `BasicArrayPackage` | Basic [array] functions (not available under `no_index`) | No | Yes | +| `BasicMapPackage` | Basic [object map] functions (not available under `no_object`) | No | Yes | +| `EvalPackage` | Disable [`eval`] | No | No | +| `CorePackage` | Basic essentials | Yes | Yes | +| `StandardPackage` | Standard library (default for `Engine::new`) | No | Yes | + + +Load the `CorePackage` +--------------------- + +If only minimal functionalities is required, load the `CorePackage` instead: + +```rust +use rhai::Engine; +use rhai::packages::{Package, CorePackage}; + +let mut engine = Engine::new_raw(); +let package = CorePackage::new(); + +engine.load_package(package.get()); +``` diff --git a/doc/src/rust/packages/create.md b/doc/src/rust/packages/create.md new file mode 100644 index 00000000..cdff10b8 --- /dev/null +++ b/doc/src/rust/packages/create.md @@ -0,0 +1,47 @@ +Create a Custom Package +====================== + +{{#include ../../links.md}} + +Sometimes specific functionalities are needed, so custom packages can be created. + +The macro `rhai::def_package!` is used to create a new custom package. + + +Macro Parameters +--------------- + +`def_package!(root:package_name:description, variable, block)` + +* `root` - root namespace, usually `"rhai"`. + +* `package_name` - name of the package, usually ending in `Package`. + +* `description` - doc comment for the package. + +* `variable` - a variable name holding a reference to the [module] that is to form the package. + +* `block` - a code block that initializes the package. + +```rust +// Import necessary types and traits. +use rhai::{ + def_package, + packages::Package, + packages::{ArithmeticPackage, BasicArrayPackage, BasicMapPackage, LogicPackage} +}; + +// Define the package 'MyPackage'. +def_package!(rhai:MyPackage:"My own personal super package", module, { + // Aggregate existing packages simply by calling 'init' on each. + ArithmeticPackage::init(module); + LogicPackage::init(module); + BasicArrayPackage::init(module); + BasicMapPackage::init(module); + + // Register additional Rust functions using the standard 'set_fn_XXX' module API. + module.set_fn_1("foo", |s: ImmutableString| { + Ok(foo(s.into_owned())) + }); +}); +```