feat: nyash.toml v2完全対応とinit関数オプション化

主な変更:
- nyash.toml v2形式(マルチBox型プラグイン)に完全対応
- plugin-testerをv2対応に全面更新
- Host VTable完全廃止でシンプル化
- init関数をオプション化(グローバル初期化用)
- FileBoxプラグインを新設計に移行(once_cell使用)

仕様更新:
- nyash_plugin_invoke(必須)とnyash_plugin_init(オプション)の2関数体制
- すべてのメタ情報はnyash.tomlから取得
- プラグインは自己完結でログ出力

テスト確認:
- plugin-testerでFileBoxの動作確認済み
- birth/finiライフサイクル正常動作

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-19 04:48:25 +09:00
parent 5f6f946179
commit e1b148051b
8 changed files with 638 additions and 1137 deletions

View File

@ -1,107 +1,155 @@
# nyash.toml v2 仕様 - マルチBox型プラグイン対応
# nyash.toml v2 仕様 - 究極のシンプル設計
## 🎯 概要
1つのプラグインライブラリが複数のBox型を提供できるように拡張した仕様。
**革命的シンプル設計**: nyash.toml中心アーキテクチャ + 最小限FFI
## 📝 基本構造
## 📝 nyash.toml v2形式
### 1. 後方互換性のある現行形式単一Box型
### マルチBox型プラグイン対応
```toml
[plugins]
FileBox = "nyash-filebox-plugin"
[plugins.FileBox.methods]
read = { args = [] }
write = { args = [{ from = "string", to = "bytes" }] }
```
### 2. 新形式マルチBox型プラグイン
```toml
# ライブラリ定義
[plugins.libraries]
"nyash-network" = {
plugin_path = "libnyash_network.so",
provides = ["SocketBox", "HTTPServerBox", "HTTPRequestBox", "HTTPResponseBox"]
[libraries]
# ライブラリ定義1つのプラグインで複数のBox型を提供可能
"libnyash_filebox_plugin.so" = {
boxes = ["FileBox"],
path = "./target/release/libnyash_filebox_plugin.so"
}
# 各Box型の詳細定義
[plugins.types.SocketBox]
library = "nyash-network"
type_id = 100
methods = {
bind = { args = [
{ name = "address", from = "string", to = "string" },
{ name = "port", from = "integer", to = "u16" }
]}
# 将来の拡張例: 1つのプラグインで複数Box型
"libnyash_network_plugin.so" = {
boxes = ["SocketBox", "HTTPServerBox", "HTTPClientBox"],
path = "./target/release/libnyash_network_plugin.so"
}
[plugins.types.HTTPServerBox]
library = "nyash-network"
type_id = 101
methods = {
bind = { args = [
{ name = "address", from = "string", to = "string" },
{ name = "port", from = "integer", to = "u16" }
]},
route = { args = [
{ name = "path", from = "string", to = "string" },
{ name = "handler", from = "box", to = "box" }
]}
}
# FileBoxの型情報定義
[libraries."libnyash_filebox_plugin.so".FileBox]
type_id = 6
abi_version = 1 # ABIバージョンもここに
[libraries."libnyash_filebox_plugin.so".FileBox.methods]
# method_id だけで十分(引数情報は実行時チェック)
birth = { method_id = 0 }
open = { method_id = 1 }
read = { method_id = 2 }
write = { method_id = 3 }
close = { method_id = 4 }
fini = { method_id = 4294967295 } # 0xFFFFFFFF
```
## 🔧 型システム
## 🚀 究極のシンプルFFI
### サポートする型(基本型のみ)
```toml
{ from = "string", to = "string" } # 文字列
{ from = "integer", to = "i64" } # 整数
{ from = "float", to = "f64" } # 浮動小数点
{ from = "bool", to = "bool" } # 真偽値
{ from = "bytes", to = "bytes" } # バイト配列
```
### プラグインが実装する関数
**重要**: プラグインとNyash本体間では基本型のみやり取り。Box型の受け渡しは行わない箱は箱で完結
### 2. プラグインFFI拡張
#### 必須: メソッド実行エントリーポイント
```c
// 既存: 単一Box型
nyash_plugin_abi_version()
nyash_plugin_init()
// 新規: 複数Box型
nyash_plugin_get_box_count() // 提供するBox型の
nyash_plugin_get_box_info(index) // 各Box型の情報
// 唯一の必須関数 - すべてのメソッド呼び出しはここから
extern "C" fn nyash_plugin_invoke(
type_id: u32, // Box型ID例: FileBox = 6
method_id: u32, // メソッドID0=birth, 0xFFFFFFFF=fini
instance_id: u32, // インスタンスID0=static/birth
args: *const u8, // TLVエンコード引
args_len: usize,
result: *mut u8, // TLVエンコード結果バッファ
result_len: *mut usize // [IN/OUT]バッファサイズ
) -> i32 // 0=成功, 負=エラー
```
## 📊 実装優先順位
1. **Phase 1**: nyash.toml v2パーサー実装
- 後方互換性維持
- 新形式の読み込み
2. **Phase 2**: plugin-tester拡張
- 複数Box型の検出
- 各Box型のメソッド検証
3. **Phase 3**: ローダー拡張
- 複数Box型の登録
- 型ID管理
## 🎯 HTTPServerBox依存問題の解決
この設計により、以下が可能になります:
```toml
[plugins.libraries]
"nyash-network" = {
plugin_path = "libnyash_network.so",
provides = ["SocketBox", "HTTPServerBox", "HTTPRequestBox", "HTTPResponseBox"]
#### オプション: グローバル初期化
```c
// プラグインロード時に1回だけ呼ばれる実装は任意
extern "C" fn nyash_plugin_init() -> i32 {
// グローバルリソースの初期化
// 設定ファイルの読み込み
// ログファイルのオープン
// 0=成功, 負=エラー(プラグインは無効化される)
}
```
# HTTPServerBoxはプラグイン内でSocketBoxを直接使用可能
# MapBoxへの依存は以下のように解決
# - HTTPResponseBoxは内部でHashMapを使用
# - get_header("name") で個別アクセス
# - get_all_headers() は文字列配列として返す
```
### 廃止されたAPI
```c
// ❌ これらは全部不要!
nyash_plugin_abi_version() // → nyash.tomlのabi_version
nyash_plugin_get_box_count() // → nyash.tomlのboxes配列
nyash_plugin_get_box_info() // → nyash.tomlから取得
NyashHostVtable // → 完全廃止!
```
## 📊 設計原則
### 1. **Single Source of Truth**
- すべてのメタ情報はnyash.tomlに集約
- プラグインは純粋な実装のみ
### 2. **Zero Dependencies**
- Host VTable廃止 = 依存関係ゼロ
- プラグインは完全に独立
### 3. **シンプルなライフサイクル**
- `init` (オプション): プラグインロード時の初期化
- `birth` (method_id=0): インスタンス作成
- 各種メソッド: インスタンス操作
- `fini` (method_id=0xFFFFFFFF): 論理的終了
### 4. **ログ出力**
```rust
// プラグインは自己完結でログ出力
eprintln!("[FileBox] Opened: {}", path); // 標準エラー
// または専用ログファイル
let mut log = File::create("plugin_debug.log")?;
writeln!(log, "{}: FileBox birth", chrono::Local::now())?;
```
### 5. **init関数の活用例**
```rust
static mut LOG_FILE: Option<File> = None;
#[no_mangle]
pub extern "C" fn nyash_plugin_init() -> i32 {
// ログファイルを事前に開く
match File::create("filebox.log") {
Ok(f) => {
unsafe { LOG_FILE = Some(f); }
0 // 成功
}
Err(_) => -1 // エラー → プラグイン無効化
}
}
```
## 🔧 実装の流れ
### Phase 1: nyash.toml v2パーサー
1. 新形式の読み込み
2. Box型情報の抽出
3. メソッドID管理
### Phase 2: プラグインローダー簡素化
1. `nyash_plugin_init`(オプション)と`nyash_plugin_invoke`(必須)をロード
2. nyash.tomlベースの型登録
3. Host VTable関連コードを削除
4. init関数が存在し失敗した場合はプラグインを無効化
### Phase 3: プラグイン側の対応
1. abi/get_box_count/get_box_info関数を削除
2. init関数は必要に応じて実装グローバル初期化
3. invoke関数でメソッド処理
4. ログ出力を自己完結に
## 🎉 メリット
1. **究極のシンプルさ** - 基本的にFFI関数1つinitはオプション
2. **保守性向上** - 複雑な相互依存なし
3. **テスト容易性** - モック不要
4. **移植性** - どの言語でも実装可能
5. **拡張性** - nyash.toml編集で機能追加
6. **初期化保証** - init関数で早期エラー検出可能
## 🚨 注意事項
- プラグインのログは標準エラー出力かファイル出力で
- メモリ管理はプラグイン内で完結
- 非同期処理はNyash側でFutureBoxラップ
---
**革命完了**: これ以上シンプルにできない究極の設計!