rhailib/src/derive/docs/ARCHITECTURE.md
2025-06-27 12:09:50 +03:00

67 lines
2.9 KiB
Markdown

# Architecture of the `derive` Crate
The `derive` crate is a procedural macro crate responsible for generating boilerplate code that integrates Rust structs with the Rhai scripting engine. It simplifies the process of exposing Rust types and their properties to Rhai scripts.
## Core Functionality
The crate provides two main procedural macros:
1. `#[derive(RhaiApi)]`
2. `#[derive(FromVec)]`
---
## `#[derive(RhaiApi)]`
This is the primary macro of the crate. When applied to a Rust struct, it automatically generates a Rhai-compatible DSL (Domain-Specific Language) for that struct.
### Generated Code Structure
For a struct named `MyStruct`, the macro generates a new module named `my_struct_rhai_dsl`. This module contains a Rhai `export_module` with the following functions:
* **`new_my_struct()`**: A constructor function that creates a new instance of `MyStruct` within the Rhai engine.
* **Setter Functions**: For each field in `MyStruct`, a corresponding setter function is generated. For a field named `my_field`, a Rhai function `my_field(value)` is created to set its value.
* **`id()`**: A function to retrieve the ID of the object.
This allows for a fluent, chainable API within Rhai scripts, like so:
```rhai
let my_object = new_my_struct().field1(42).field2("hello");
```
### Implementation Details
The implementation resides in `src/rhai_api.rs`. It uses the `syn` crate to parse the input `DeriveInput` and the `quote` crate to construct the output `TokenStream`.
The process is as follows:
1. The macro input is parsed into a `DeriveInput` AST (Abstract Syntax Tree).
2. The struct's name and fields are extracted from the AST.
3. A new module name is generated based on the struct's name (e.g., `MyStruct` -> `my_struct_rhai_dsl`).
4. Using the `quote!` macro, the code for the new module, the `export_module`, the constructor, and the setter functions is generated.
5. The generated code is returned as a `TokenStream`, which the compiler then incorporates into the crate.
### Architectural Diagram
```mermaid
graph TD
A[Rust Struct Definition] -- `#[derive(RhaiApi)]` --> B{`derive` Crate};
B -- `syn` --> C[Parse Struct AST];
C -- Extract Fields & Name --> D[Generate Code with `quote`];
D -- Create --> E[Constructor `new_...()`];
D -- Create --> F[Setter Functions `field(...)`];
D -- Create --> G[`id()` function];
E & F & G -- Packaged into --> H[Rhai `export_module`];
H -- Returned as `TokenStream` --> I[Compiler];
I -- Integrates into --> J[Final Binary];
```
---
## `#[derive(FromVec)]`
This is a simpler utility macro. Its purpose is to generate a `From<Vec<T>>` implementation for a tuple struct that contains a single `Vec<T>`. This is useful for converting a vector of items into a specific newtype-pattern struct.
### Implementation
The implementation is located directly in `src/lib.rs`. It parses the input struct and, if it's a single-element tuple struct, generates the corresponding `From` implementation.