//! Phase 91: CoreServices 定義 //! //! Ring1-Core: core_required Box の Service trait 群。 //! Phase 87 CoreBoxId の core_required (6個) 全てをカバー。 use std::sync::Arc; use crate::runtime::CoreBoxId; use crate::box_trait::NyashBox; // Phase 96.5: Adapter実装で使用するBox型をトップレベルでimport use crate::boxes::array::ArrayBox; use crate::boxes::map_box::MapBox; use crate::box_trait::{IntegerBox, StringBox, BoolBox}; /// StringBox Service trait /// /// Phase 95: len のみ実装 pub trait StringService: Send + Sync { fn len(&self, s: &str) -> i64; } /// IntegerBox Service trait /// /// Phase 97: 純粋関数型(加算・減算・比較など) pub trait IntegerService: Send + Sync { /// 2つの整数を加算 fn add(&self, a: i64, b: i64) -> i64; /// 2つの整数を減算 fn sub(&self, a: i64, b: i64) -> i64; /// 2つの整数を乗算 fn mul(&self, a: i64, b: i64) -> i64; /// 2つの整数を除算(ゼロ除算はNone) fn div(&self, a: i64, b: i64) -> Option; } /// BoolBox Service trait /// /// Phase 97: 純粋関数型(論理演算) pub trait BoolService: Send + Sync { /// 論理NOT fn not(&self, value: bool) -> bool; /// 論理AND fn and(&self, a: bool, b: bool) -> bool; /// 論理OR fn or(&self, a: bool, b: bool) -> bool; /// 論理XOR fn xor(&self, a: bool, b: bool) -> bool; } /// ArrayBox Service trait /// /// Phase 96: len/get/set/push 実装 pub trait ArrayService: Send + Sync { /// 配列の要素数を取得 fn len(&self, arr: &dyn NyashBox) -> i64; /// 指定インデックスの要素を取得 fn get(&self, arr: &dyn NyashBox, index: i64) -> Option>; /// 指定インデックスに要素を設定 fn set(&self, arr: &dyn NyashBox, index: i64, value: Box) -> Result<(), String>; /// 配列の末尾に要素を追加 fn push(&self, arr: &dyn NyashBox, value: Box) -> Result<(), String>; } /// MapBox Service trait /// /// Phase 96: size/has/get/set 実装 pub trait MapService: Send + Sync { /// マップのサイズを取得 fn size(&self, map: &dyn NyashBox) -> i64; /// キーが存在するか確認 fn has(&self, map: &dyn NyashBox, key: &str) -> bool; /// 値を取得 fn get(&self, map: &dyn NyashBox, key: &str) -> Option>; /// 値を設定 fn set(&self, map: &dyn NyashBox, key: &str, value: Box) -> Result<(), String>; } /// ConsoleBox Service trait /// /// Phase 95: println と print のみ実装 pub trait ConsoleService: Send + Sync { fn println(&self, msg: &str); fn print(&self, msg: &str); } /// CoreServices: core_required Box の集合 /// /// Phase 85 設計原則: /// - core_required は必ず全て揃っていなければならない /// - 起動時に全フィールドが初期化されていることを保証 /// /// Phase 87 CoreBoxId との対応: /// - String → string /// - Integer → integer /// - Bool → bool /// - Array → array /// - Map → map /// - Console → console pub struct CoreServices { pub string: Arc, pub integer: Arc, pub bool: Arc, pub array: Arc, pub map: Arc, pub console: Arc, } impl std::fmt::Debug for CoreServices { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CoreServices") .field("string", &"StringService") .field("integer", &"IntegerService") .field("bool", &"BoolService") .field("array", &"ArrayService") .field("map", &"MapService") .field("console", &"ConsoleService") .finish() } } impl CoreServices { /// Phase 87 CoreBoxId の core_required (6個) を返す /// /// Phase 87 CoreBoxId::is_core_required() と完全一致する。 pub fn required_ids() -> &'static [CoreBoxId] { &[ CoreBoxId::String, CoreBoxId::Integer, CoreBoxId::Bool, CoreBoxId::Array, CoreBoxId::Map, CoreBoxId::Console, ] } /// 全フィールドが初期化されているか検証 /// Phase 92 以降で各 Service の初期化を検証 pub fn ensure_initialized(&self) { // Phase 91 では trait が空なので何もしない // Phase 92 以降で各 Service の初期化を検証 } } // ============================================================================ // Phase 94: Adapter Pattern - Box → Service 変換 // ============================================================================ /// StringBox → StringService Adapter /// /// Phase 95.5: 純粋関数設計 /// - Box を保持せず、純粋関数として実装 /// - len(s) → s.chars().count() (UTF-8 文字数) /// - Phase 96 以降で substring(), concat() など追加予定 pub struct StringBoxAdapter; impl StringBoxAdapter { pub fn new() -> Self { Self } } impl StringService for StringBoxAdapter { fn len(&self, s: &str) -> i64 { // Phase 95.5: 文字列長を返す(UTF-8 バイト数ではなく文字数) s.chars().count() as i64 } } /// IntegerBox → IntegerService Adapter /// /// Phase 97: 純粋関数型(Box状態不要) pub struct IntegerBoxAdapter; impl IntegerBoxAdapter { pub fn new() -> Self { Self } } impl IntegerService for IntegerBoxAdapter { fn add(&self, a: i64, b: i64) -> i64 { a.saturating_add(b) // オーバーフロー対策 } fn sub(&self, a: i64, b: i64) -> i64 { a.saturating_sub(b) // アンダーフロー対策 } fn mul(&self, a: i64, b: i64) -> i64 { a.saturating_mul(b) // オーバーフロー対策 } fn div(&self, a: i64, b: i64) -> Option { if b == 0 { None // ゼロ除算 } else { Some(a / b) } } } /// BoolBox → BoolService Adapter /// /// Phase 97: 純粋関数型(Box状態不要) pub struct BoolBoxAdapter; impl BoolBoxAdapter { pub fn new() -> Self { Self } } impl BoolService for BoolBoxAdapter { fn not(&self, value: bool) -> bool { !value } fn and(&self, a: bool, b: bool) -> bool { a && b } fn or(&self, a: bool, b: bool) -> bool { a || b } fn xor(&self, a: bool, b: bool) -> bool { a ^ b } } /// ArrayBox → ArrayService Adapter /// /// Phase 96: downcast パターンで複数インスタンス対応 pub struct ArrayBoxAdapter; impl ArrayBoxAdapter { pub fn new() -> Self { Self } } impl ArrayService for ArrayBoxAdapter { fn len(&self, arr: &dyn NyashBox) -> i64 { arr.as_any() .downcast_ref::() .map(|a| a.len() as i64) .unwrap_or(0) } fn get(&self, arr: &dyn NyashBox, index: i64) -> Option> { let arr_box = arr.as_any().downcast_ref::()?; let index_box = Box::new(IntegerBox::new(index)); Some(arr_box.get(index_box)) } fn set(&self, arr: &dyn NyashBox, index: i64, value: Box) -> Result<(), String> { let arr_box = arr.as_any() .downcast_ref::() .ok_or("Not an ArrayBox")?; let index_box = Box::new(IntegerBox::new(index)); arr_box.set(index_box, value); Ok(()) } fn push(&self, arr: &dyn NyashBox, value: Box) -> Result<(), String> { let arr_box = arr.as_any() .downcast_ref::() .ok_or("Not an ArrayBox")?; arr_box.push(value); Ok(()) } } /// MapBox → MapService Adapter /// /// Phase 96: downcast パターンで複数インスタンス対応 pub struct MapBoxAdapter; impl MapBoxAdapter { pub fn new() -> Self { Self } } impl MapService for MapBoxAdapter { fn size(&self, map: &dyn NyashBox) -> i64 { map.as_any() .downcast_ref::() .map(|m| { // MapBox::size() は Box を返すため、IntegerBox に変換 let size_box = m.size(); size_box.as_any() .downcast_ref::() .map(|i| i.value) .unwrap_or(0) }) .unwrap_or(0) } fn has(&self, map: &dyn NyashBox, key: &str) -> bool { let map_box = match map.as_any().downcast_ref::() { Some(m) => m, None => return false, }; let key_box = Box::new(StringBox::new(key)); let result = map_box.has(key_box); result.as_any() .downcast_ref::() .map(|b| b.value) .unwrap_or(false) } fn get(&self, map: &dyn NyashBox, key: &str) -> Option> { let map_box = map.as_any().downcast_ref::()?; let key_box = Box::new(StringBox::new(key)); Some(map_box.get(key_box)) } fn set(&self, map: &dyn NyashBox, key: &str, value: Box) -> Result<(), String> { let map_box = map.as_any() .downcast_ref::() .ok_or("Not a MapBox")?; let key_box = Box::new(StringBox::new(key)); map_box.set(key_box, value); Ok(()) } } /// ConsoleBox → ConsoleService Adapter /// /// Phase 95.5: Ring0 直結設計 /// - Box を保持せず、Ring0Context に直結 /// - println() → Ring0Context.log.info() /// - print() → Ring0Context.io.stdout_write() pub struct ConsoleBoxAdapter; impl ConsoleBoxAdapter { pub fn new() -> Self { Self } } impl ConsoleService for ConsoleBoxAdapter { fn println(&self, msg: &str) { // 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.5: Ring0Context 経由で stdout 出力(改行なし) use crate::runtime::ring0::get_global_ring0; let ring0 = get_global_ring0(); ring0.io.stdout_write(msg.as_bytes()).ok(); } } #[cfg(test)] mod tests { use super::*; #[test] fn test_required_ids_consistency() { let required = CoreServices::required_ids(); assert_eq!(required.len(), 6); // Phase 87 CoreBoxId::is_core_required() と一致 for id in required { assert!(id.is_core_required()); } // 全ての core_required が含まれているか確認 assert!(required.contains(&CoreBoxId::String)); assert!(required.contains(&CoreBoxId::Integer)); assert!(required.contains(&CoreBoxId::Bool)); assert!(required.contains(&CoreBoxId::Array)); assert!(required.contains(&CoreBoxId::Map)); 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() { // Phase 95.5: Ring0 初期化(安全な初期化) ensure_ring0_initialized(); let adapter = ConsoleBoxAdapter::new(); // Phase 95.5: println を呼び出し(Ring0 経由、panic しないことを確認) adapter.println("Test message from Ring0"); // 実際の出力検証は Phase 96 以降 } #[test] fn test_console_service_print() { // Phase 95.5: Ring0 初期化(安全な初期化) ensure_ring0_initialized(); let adapter = ConsoleBoxAdapter::new(); // Phase 95.5: print を呼び出し(Ring0 経由、panic しないことを確認) adapter.print("No newline"); // 実際の出力検証は Phase 96 以降 } #[test] fn test_string_service_len() { // Phase 95.5: 純粋関数なので Ring0 不要 let adapter = StringBoxAdapter::new(); // Phase 95: len を呼び出し let length = adapter.len("Hello"); assert_eq!(length, 5); // UTF-8 対応確認 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 しないことを確認 } #[test] fn test_array_service_basic_operations() { use crate::boxes::array::ArrayBox; use crate::box_trait::IntegerBox; let arr = ArrayBox::new(); let adapter = ArrayBoxAdapter::new(); // push let value = Box::new(IntegerBox::new(42)); adapter.push(&arr, value).unwrap(); // len assert_eq!(adapter.len(&arr), 1); // get let result = adapter.get(&arr, 0).unwrap(); let int_box = result.as_any().downcast_ref::().unwrap(); assert_eq!(int_box.value, 42); } #[test] fn test_array_service_set() { use crate::boxes::array::ArrayBox; use crate::box_trait::IntegerBox; let arr = ArrayBox::new(); let adapter = ArrayBoxAdapter::new(); // push initial value adapter.push(&arr, Box::new(IntegerBox::new(10))).unwrap(); // set adapter.set(&arr, 0, Box::new(IntegerBox::new(20))).unwrap(); // verify let result = adapter.get(&arr, 0).unwrap(); let int_box = result.as_any().downcast_ref::().unwrap(); assert_eq!(int_box.value, 20); } #[test] fn test_map_service_basic_operations() { use crate::boxes::map_box::MapBox; use crate::box_trait::StringBox; let map = MapBox::new(); let adapter = MapBoxAdapter::new(); // set let value = Box::new(StringBox::new("Hello")); adapter.set(&map, "key1", value).unwrap(); // has assert!(adapter.has(&map, "key1")); assert!(!adapter.has(&map, "key2")); // get let result = adapter.get(&map, "key1").unwrap(); let str_box = result.as_any().downcast_ref::().unwrap(); assert_eq!(str_box.value, "Hello"); // size assert_eq!(adapter.size(&map), 1); } #[test] fn test_map_service_multiple_keys() { use crate::boxes::map_box::MapBox; use crate::box_trait::{IntegerBox, StringBox}; let map = MapBox::new(); let adapter = MapBoxAdapter::new(); // set multiple keys adapter.set(&map, "name", Box::new(StringBox::new("Alice"))).unwrap(); adapter.set(&map, "age", Box::new(IntegerBox::new(25))).unwrap(); // verify size assert_eq!(adapter.size(&map), 2); // verify values let name = adapter.get(&map, "name").unwrap(); let name_str = name.as_any().downcast_ref::().unwrap(); assert_eq!(name_str.value, "Alice"); let age = adapter.get(&map, "age").unwrap(); let age_int = age.as_any().downcast_ref::().unwrap(); assert_eq!(age_int.value, 25); } #[test] fn test_integer_service_operations() { let adapter = IntegerBoxAdapter::new(); // add assert_eq!(adapter.add(10, 20), 30); assert_eq!(adapter.add(i64::MAX, 1), i64::MAX); // saturating // sub assert_eq!(adapter.sub(20, 10), 10); assert_eq!(adapter.sub(i64::MIN, 1), i64::MIN); // saturating // mul assert_eq!(adapter.mul(5, 6), 30); assert_eq!(adapter.mul(i64::MAX, 2), i64::MAX); // saturating // div assert_eq!(adapter.div(20, 5), Some(4)); assert_eq!(adapter.div(10, 3), Some(3)); // 整数除算 assert_eq!(adapter.div(10, 0), None); // ゼロ除算 } #[test] fn test_bool_service_operations() { let adapter = BoolBoxAdapter::new(); // not assert_eq!(adapter.not(true), false); assert_eq!(adapter.not(false), true); // and assert_eq!(adapter.and(true, true), true); assert_eq!(adapter.and(true, false), false); assert_eq!(adapter.and(false, false), false); // or assert_eq!(adapter.or(true, false), true); assert_eq!(adapter.or(false, false), false); // xor assert_eq!(adapter.xor(true, false), true); assert_eq!(adapter.xor(true, true), false); assert_eq!(adapter.xor(false, false), false); } }