Вы можете создавать собственный плагины для RDL на языке Rust.
Для упрощения разработки плагинов создан специальный крейт netter_plugger (crates.io). Установка крейта:
cargo add netter_plugger - добавит крейт для создания плагинов в зависимости вашего кода.
Начнём с простого примера:
use netter_plugger::{netter_plugin, generate_dispatch_func};
generate_dispatch_func!();
#[netter_plugin]
fn something(
path: String,
) -> Result<String, String> {
let result = "heey".to_string();
if path == "error" {
Err("err from plugin".to_string())
} else {
Ok(format!("{result}: {path}"))
}
}
#[netter_plugin]
fn add_numbers(a: i32, b: i32) -> Result<String, String> {
Ok((a + b).to_string())
}
#[netter_plugin]
fn check_flag(flag: bool) -> Result<String, String> {
if flag {
Ok("Flag is set".to_string())
} else {
Ok("Flag is not set".to_string())
}
}use netter_plugger::{netter_plugin, generate_dispatch_func};- импорт атрибута и макроса от крейта для упрощения;generate_dispatch_func!();- данный макрос инициализирует входную точку в плагин. Очень важно расположить этот макрос в самом верху вашего кода (после всех use)#[netter_plugin]- атрибут, который ставится на функции, чтобы пометить их для интеграции в RDL.
Warning
У функций, которые вы интегрируете в RDL есть важные ограничения: Входные типы данных На вход функция может принимать только следующие типы: String, &str, i64, i32, f64, f32, bool. Выходные типы Функция обязательно должна возвращать тип Result<String, String>
Данные ограничения связаны со строковой типизацией RDL и ограничений интерпретатора. Со времен список поддерживаемых типов будет увеличиваться
- После атрибута объявляется функция и вся её логика - всё как обычно.
Весь ваш код функций преобразуется в C-совместимые типы, соответственно участвует unsafe extern "C" (подробнее можно почитать здесь).
Учтите это, но чаще всего проблем быть не должно.
Чтобы вызвать фукнции вашего плагина из RDL вам необходимо получить динамическую библиотеку из вашего кода плагина:
Note
Ваш Rust проект должен быть инициализирован с флагом --lib:
cargo init --lib
Добавьте в ваш Cargo.toml следующее:
[dependencies]
netter_plugger = "0.1.0"
syn = { version = "2.0", features = ["full"] }
quote = "1.0"
lazy_static = "1.5.0"
serde = "1.0.219"
serde_json = "1.0.140"
ctor = "0.4.2"
...
[lib]
crate-type = ["cdylib"]Все зависимости, который указаны в кодде выше, обязательно должны быть добавлны в ваш Cargo.toml Версию плагина выбирайте самую последнюю, чтобы избежать проблем с несовместимостью весрий и получить доступ ко всему функционалу крейта!
В терминале пропишите следующее:
cargo build --releaseЭто сгенерирует динамическую библиотеку (.dll или .so).
До объявления маршрутов (Ключевое слово route) вам необходимо импортировать динамическую библиотеку, собранную ранее:
import "path/to/file.dll" as plugin_alias; // "path/to/file.dll" - путь (относительный или абсолютный) до вашей динамической библиотеки
// plugin_alias - алиас для использования далее
После этого вы сможете использовать ваши функции в коде:
route "/" GET {
val a = 1;
val b = 2;
val plugin = plugin_alias::add_numbers(a, b)?;
Response.body(plugin);
Response.send();
} onError(e) {
Response.status(500);
Response.body(e);
Response.send();
};
Important
Вы могли заметить, что после вызова функции из плагина стоит ?. Он необходим, чтобы поймать ошибку, если вддруг функция до неё дойдёт, поэтому обрабатывать эту ошибку надо точно также, как и обычные ошибки
Хотя вы, если уверены, что до ошибки не дойдёт, можете её игнорировать с помощью !!, но тогда, в случае ошибки, код завершиться паникой (экстренное звершение)