arora-engine 5.5.0

The Arora engine: loads and executes Arora modules (wasm and native hosts).
# Arora Engine

Welcome to the core of the project!

## WebAssembly executors

The Arora engine runs WASM modules — advertised with
[a custom module description format (or schema)](https://github.com/semio-ai/arora-sdk) —
through pluggable [`Executor`](src/executor/mod.rs) implementations, chosen
by the `executor.name` of a module's header. Each kind runs natively, on
[`wasmtime`](https://docs.wasmtime.dev/) (the default `wasmtime-host`
feature), and in the browser, on its native `WebAssembly` runtime, when
`arora` itself is compiled to `wasm32-unknown-unknown` (the JS-facing
wrapper is [`arora-web`](https://github.com/semio-ai/arora-sdk)):

- **`wasm-component`**, what Arora guests are built as: a component of the
  `arora:module` world ([`wit/arora-module.wit`]wit/arora-module.wit), as
  Rust and C++ build one for `wasm32-wasip2`. It exports `functions` and
  `dispatch`, and may import the world's `host` interface and the WASI 0.2
  interfaces `wasi:cli`, `wasi:io`, `wasi:clocks`, `wasi:random` and
  `wasi:filesystem`, with no directory preopened — no sockets
  ([`component_layout`]src/component_layout.rs).
  Hosted by [`component::ComponentExecutor`]src/executor/component/mod.rs
  and [`browser::BrowserComponentExecutor`]src/executor/browser/component.rs,
  which a `BrowserExecutor`'s `component_executor()` gives. A component that
  traps runs no more calls until it is reloaded.
- **`wasm`**, a core module speaking the core-module ABI
  (`arora_buffer_alloc`/`free` and `arora_function_<uuid>` exports,
  `arora_dispatch` / `arora_dispatch_indirect` imports), as guests built for
  `wasm32-wasip1` are. Hosted by
  [`wasm::WebAssemblyExecutor`]src/executor/wasm/mod.rs and
  [`browser::BrowserExecutor`]src/executor/browser/mod.rs.

A guest that exports `_initialize` — a WASI reactor, which a C or C++ guest
is when linked with `-mexec-model=reactor` — has it run once, when it loads,
before any other export: a component's initializer calls it, and the `wasm`
executors call it for a core module. It runs the guest's static
constructors.

### Compiling a module once

[`Engine::load_module`](src/engine.rs) compiles the module's executable for
the engine that loads it. A module that several engines load — one per
device, say — compiles once as a [`CompiledModule`](src/compiled.rs), which
each engine loads with `Engine::load_compiled_module`: it instantiates the
compiled code, with an instance (memory, globals) of its own, and compiles
nothing. Natively, every executor of a kind in the process runs on one
wasmtime engine, the one a compiled module belongs to; in the browser, a
`WebAssembly.Module` — for a component, of the guest's core module —
instantiates anywhere.

## Native Executor

A [`native::NativeExecutor`](src/executor/native.rs) is available and is
capable of loading native dynamic libraries, and call the functions
declared in the module description. Beware of figuring out the right
dynamic library extension for the host platform. Gated behind the
default `native-host` feature; disabled on `wasm32-*` targets.

## Calling Module Functions

Once modules are loaded — either via [`Engine::load_module`](src/engine.rs)
directly, or via the [`load::load_module_from_parts`](src/load.rs)
convenience that takes a parsed `Header` plus the executable bytes and
also returns the module's function IDs —
their functions can be called using engine's
implementation of the [`CallBridge` trait](src/call.rs).
`arora_call` takes a `Call` description holding generic `Value`s as an input,
and returns a `CallResult` holding the return value
and the mutated parameters.
The engine also advertises a function called `arora_dispatch`
in the module's runtime context, so that they can call one another.
It is recommended to use the bindings generated by
[`arora-module-cli`](../arora-module-authoring/cli/readme.md),
rather than calling these functions directly.

The host of the engine (the process loading this library)
can also register native functions using [`arora_register_callable`](src/call.rs).
An `u64` identifier is attributed to each registered function,
so that they can be called later using `arora_call_indirect` from the host side,
or from any module via `arora_dispatch_indirect`.

> [Behavior Trees]https://github.com/semio-ai/arora-sdk typically use this mechanism
> to wrap the various node functions into uniform tick functions.

### Call Mechanism

When a call is performed, its description is serialized into a raw buffer,
using the [Arora Buffers library](../arora-buffers/readme.md),
copied into the module's memory
(allocated using `arora_buffer_alloc` that must be exported by the modules),
before the function is called with a pointer to the memory segment.
The module is in charge of deserializing it
and serializing the result into a new buffer,
that the engine will free using `arora_buffer_free`.