feat(phase95.5): Ring0統合完了 - Adapter整理とコード簡略化

Phase 95.5完全達成 - ConsoleService/StringService Ring0直結化

### 実装成果
-  ConsoleBoxAdapter Ring0直結(println → log.info, print → io.stdout_write)
-  StringBoxAdapter 純粋関数化(Box状態不要)
-  #[allow(dead_code)] 6→4箇所削減(2削除)
-  PluginHost初期化簡略化(存在確認のみ)
-  テスト14/14 PASS(100%)

### 変更ファイル
- src/runtime/core_services.rs: ConsoleBoxAdapter/StringBoxAdapter unit struct化
- src/runtime/plugin_host.rs: 初期化ロジック簡略化(create_box → has_type)
- docs/development/current/main/core_boxes_design.md: Section 12追加
- CURRENT_TASK.md: Phase 95.5成果記録

### 設計パターン確立
**2つのAdapterパターン**:
1. Ring0直結型(ConsoleService): OS API thin wrapper
2. 純粋関数型(StringService): Box状態不要

**将来実装方針**:
- ArrayService/MapService: 状態管理必要 → Box保持
- IntegerService/BoolService: 純粋関数 → Box不要

### 技術的成果
- Ring0統合完成(ログ経路統一: Ring0 → Ring1-Core → 実行パス)
- コード簡略化(不要なinnerフィールド削除)
- 設計明確化(Adapterの役割を2パターンに整理)
- テスト容易性向上(Ring0モック可能)

### 削減統計
- #[allow(dead_code)]: 2箇所削除
- innerフィールド: 2個削除
- Box依存: 2箇所削除

### 次のステップ
Phase 96: ArrayService/MapService実装(downcastパターン)

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
nyash-codex
2025-12-03 10:15:23 +09:00
parent e74694d08b
commit 1108a61533
4 changed files with 319 additions and 54 deletions

View File

@ -106,25 +106,30 @@ impl CoreServices {
// ============================================================================
/// StringBox → StringService Adapter
pub struct StringBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
}
///
/// Phase 95.5: 純粋関数設計
/// - Box を保持せず、純粋関数として実装
/// - len(s) → s.chars().count() (UTF-8 文字数)
/// - Phase 96 以降で substring(), concat() など追加予定
pub struct StringBoxAdapter;
impl StringBoxAdapter {
pub fn new(box_instance: Box<dyn NyashBox>) -> Self {
Self { inner: box_instance }
pub fn new() -> Self {
Self
}
}
impl StringService for StringBoxAdapter {
fn len(&self, s: &str) -> i64 {
// Phase 95: 文字列長を返すUTF-8 バイト数ではなく文字数)
// Phase 95.5: 文字列長を返すUTF-8 バイト数ではなく文字数)
s.chars().count() as i64
}
}
/// IntegerBox → IntegerService Adapter
///
/// Phase 95.5: inner フィールドは #[allow(dead_code)] のまま保持
/// Phase 96 以降で実装時に、Box 状態が必要か純粋関数で足りるか判断
pub struct IntegerBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
@ -137,10 +142,13 @@ impl IntegerBoxAdapter {
}
impl IntegerService for IntegerBoxAdapter {
// Phase 95 以降で実装
// Phase 96 以降で実装
}
/// BoolBox → BoolService Adapter
///
/// Phase 95.5: inner フィールドは #[allow(dead_code)] のまま保持
/// Phase 96 以降で実装時に、Box 状態が必要か純粋関数で足りるか判断
pub struct BoolBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
@ -153,10 +161,13 @@ impl BoolBoxAdapter {
}
impl BoolService for BoolBoxAdapter {
// Phase 95 以降で実装
// Phase 96 以降で実装
}
/// ArrayBox → ArrayService Adapter
///
/// Phase 95.5: inner フィールドは #[allow(dead_code)] のまま保持
/// Phase 96 以降で実装時に、Box 状態が必要か純粋関数で足りるか判断
pub struct ArrayBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
@ -169,10 +180,13 @@ impl ArrayBoxAdapter {
}
impl ArrayService for ArrayBoxAdapter {
// Phase 95 以降で実装
// Phase 96 以降で実装
}
/// MapBox → MapService Adapter
///
/// Phase 95.5: inner フィールドは #[allow(dead_code)] のまま保持
/// Phase 96 以降で実装時に、Box 状態が必要か純粋関数で足りるか判断
pub struct MapBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
@ -185,31 +199,36 @@ impl MapBoxAdapter {
}
impl MapService for MapBoxAdapter {
// Phase 95 以降で実装
// Phase 96 以降で実装
}
/// ConsoleBox → ConsoleService Adapter
pub struct ConsoleBoxAdapter {
#[allow(dead_code)]
inner: Box<dyn NyashBox>,
}
///
/// Phase 95.5: Ring0 直結設計
/// - Box を保持せず、Ring0Context に直結
/// - println() → Ring0Context.log.info()
/// - print() → Ring0Context.io.stdout_write()
pub struct ConsoleBoxAdapter;
impl ConsoleBoxAdapter {
pub fn new(box_instance: Box<dyn NyashBox>) -> Self {
Self { inner: box_instance }
pub fn new() -> Self {
Self
}
}
impl ConsoleService for ConsoleBoxAdapter {
fn println(&self, msg: &str) {
// Phase 95: ConsoleBox の println 機能を使用
// ConsoleBox は直接 println! を呼ぶだけなので、ここでも同様に実装
println!("{}", msg);
// Phase 95.5: Ring0Context 経由でログ出力(自動改行)
use crate::runtime::ring0::get_global_ring0;
let ring0 = get_global_ring0();
ring0.log.info(msg);
}
fn print(&self, msg: &str) {
// Phase 95: ConsoleBox の print 機能を使用
print!("{}", msg);
// Phase 95.5: Ring0Context 経由で stdout 出力(改行なし)
use crate::runtime::ring0::get_global_ring0;
let ring0 = get_global_ring0();
ring0.io.stdout_write(msg.as_bytes()).ok();
}
}
@ -236,36 +255,46 @@ mod tests {
assert!(required.contains(&CoreBoxId::Console));
}
// Phase 95.5: Ring0 初期化ヘルパー(テスト用)
#[cfg(test)]
fn ensure_ring0_initialized() {
use crate::runtime::ring0::{default_ring0, GLOBAL_RING0};
use std::sync::Arc;
// 既に初期化済みなら何もしない
if GLOBAL_RING0.get().is_none() {
GLOBAL_RING0.set(Arc::new(default_ring0())).ok();
}
}
#[test]
fn test_console_service_println() {
use crate::boxes::console_box::ConsoleBox;
// Phase 95.5: Ring0 初期化(安全な初期化)
ensure_ring0_initialized();
let console_box = Box::new(ConsoleBox::new()) as Box<dyn NyashBox>;
let adapter = ConsoleBoxAdapter::new(console_box);
let adapter = ConsoleBoxAdapter::new();
// Phase 95: println を呼び出しpanic しないことを確認)
adapter.println("Test message");
// Phase 95.5: println を呼び出し(Ring0 経由、panic しないことを確認)
adapter.println("Test message from Ring0");
// 実際の出力検証は Phase 96 以降
}
#[test]
fn test_console_service_print() {
use crate::boxes::console_box::ConsoleBox;
// Phase 95.5: Ring0 初期化(安全な初期化)
ensure_ring0_initialized();
let console_box = Box::new(ConsoleBox::new()) as Box<dyn NyashBox>;
let adapter = ConsoleBoxAdapter::new(console_box);
let adapter = ConsoleBoxAdapter::new();
// Phase 95: print を呼び出しpanic しないことを確認)
adapter.print("Test message");
// Phase 95.5: print を呼び出し(Ring0 経由、panic しないことを確認)
adapter.print("No newline");
// 実際の出力検証は Phase 96 以降
}
#[test]
fn test_string_service_len() {
use crate::boxes::string_box::StringBox;
let string_box = Box::new(StringBox::new("Hello")) as Box<dyn NyashBox>;
let adapter = StringBoxAdapter::new(string_box);
// Phase 95.5: 純粋関数なので Ring0 不要
let adapter = StringBoxAdapter::new();
// Phase 95: len を呼び出し
let length = adapter.len("Hello");
@ -275,4 +304,17 @@ mod tests {
let length_utf8 = adapter.len("こんにちは");
assert_eq!(length_utf8, 5); // 5文字バイト数は15
}
#[test]
fn test_console_service_ring0_integration() {
// Phase 95.5: Ring0 初期化(安全な初期化)
ensure_ring0_initialized();
// ConsoleService 経由で出力Ring0 使用)
let adapter = ConsoleBoxAdapter::new();
adapter.println("Test message from Ring0");
adapter.print("No newline");
// panic しないことを確認
}
}

View File

@ -100,14 +100,14 @@ impl PluginHost {
// Phase 94: 各 core_required Box を取得して Adapter に変換
// StringBox
let string_box = registry
.create_box("StringBox", &[])
.map_err(|e| CoreInitError::MissingService {
// StringBox (Phase 95.5: 純粋関数化、存在チェックのみ)
if !registry.has_type("StringBox") {
return Err(CoreInitError::MissingService {
box_id: CoreBoxId::String,
message: format!("StringBox creation failed: {}", e),
})?;
let string_service = Arc::new(StringBoxAdapter::new(string_box));
message: "StringBox not found in registry".to_string(),
});
}
let string_service = Arc::new(StringBoxAdapter::new());
// IntegerBox
let integer_box = registry
@ -145,14 +145,14 @@ impl PluginHost {
})?;
let map_service = Arc::new(MapBoxAdapter::new(map_box));
// ConsoleBox
let console_box = registry
.create_box("ConsoleBox", &[])
.map_err(|e| CoreInitError::MissingService {
// ConsoleBox (Phase 95.5: Ring0 直結、存在チェックのみ)
if !registry.has_type("ConsoleBox") {
return Err(CoreInitError::MissingService {
box_id: CoreBoxId::Console,
message: format!("ConsoleBox creation failed: {}", e),
})?;
let console_service = Arc::new(ConsoleBoxAdapter::new(console_box));
message: "ConsoleBox not found in registry".to_string(),
});
}
let console_service = Arc::new(ConsoleBoxAdapter::new());
// Phase 94: 実際の Adapter を使用して CoreServices を構築
let core = CoreServices {
@ -277,7 +277,7 @@ mod tests {
#[test]
fn test_with_core_from_registry_missing_box() {
// Phase 94: registry が空の場合はエラーを返すことを確認
// Phase 95.5: registry が空の場合はエラーを返すことを確認
use crate::runtime::ring0::default_ring0;
let ring0 = Arc::new(default_ring0());
let registry = UnifiedBoxRegistry::new();
@ -285,13 +285,13 @@ mod tests {
let result = PluginHost::with_core_from_registry(ring0, &registry);
assert!(result.is_err());
// Phase 94: エラーメッセージに "creation failed" または "Unknown Box type" が含まれることを確認
// Phase 95.5: エラーメッセージに "not found in registry" が含まれることを確認
if let Err(e) = result {
let msg = format!("{}", e);
eprintln!("Error message: {}", msg); // デバッグ出力
assert!(
msg.contains("creation failed") || msg.contains("Unknown Box type"),
"Error message should contain 'creation failed' or 'Unknown Box type', got: {}",
msg.contains("not found in registry") || msg.contains("creation failed") || msg.contains("Unknown Box type"),
"Error message should contain 'not found in registry', 'creation failed' or 'Unknown Box type', got: {}",
msg
);
}