2025-12-03 07:43:08 +09:00
|
|
|
|
//! Phase 91: CoreServices 定義
|
|
|
|
|
|
//!
|
|
|
|
|
|
//! Ring1-Core: core_required Box の Service trait 群。
|
|
|
|
|
|
//! Phase 87 CoreBoxId の core_required (6個) 全てをカバー。
|
|
|
|
|
|
|
2025-12-03 09:14:49 +09:00
|
|
|
|
use crate::box_trait::NyashBox;
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::runtime::CoreBoxId;
|
|
|
|
|
|
use std::sync::Arc;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
|
2025-12-03 10:30:26 +09:00
|
|
|
|
// Phase 96.5: Adapter実装で使用するBox型をトップレベルでimport
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::box_trait::{BoolBox, IntegerBox, StringBox};
|
2025-12-03 10:30:26 +09:00
|
|
|
|
use crate::boxes::array::ArrayBox;
|
|
|
|
|
|
use crate::boxes::map_box::MapBox;
|
|
|
|
|
|
|
2025-12-03 07:43:08 +09:00
|
|
|
|
/// StringBox Service trait
|
2025-12-03 09:57:38 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 95: len のみ実装
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait StringService: Send + Sync {
|
2025-12-03 09:57:38 +09:00
|
|
|
|
fn len(&self, s: &str) -> i64;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// IntegerBox Service trait
|
2025-12-03 10:41:16 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 97: 純粋関数型(加算・減算・比較など)
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait IntegerService: Send + Sync {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
/// 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<i64>;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// BoolBox Service trait
|
2025-12-03 10:41:16 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 97: 純粋関数型(論理演算)
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait BoolService: Send + Sync {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
/// 論理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;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ArrayBox Service trait
|
2025-12-03 10:27:39 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 96: len/get/set/push 実装
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait ArrayService: Send + Sync {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
/// 配列の要素数を取得
|
|
|
|
|
|
fn len(&self, arr: &dyn NyashBox) -> i64;
|
|
|
|
|
|
|
|
|
|
|
|
/// 指定インデックスの要素を取得
|
|
|
|
|
|
fn get(&self, arr: &dyn NyashBox, index: i64) -> Option<Box<dyn NyashBox>>;
|
|
|
|
|
|
|
|
|
|
|
|
/// 指定インデックスに要素を設定
|
|
|
|
|
|
fn set(&self, arr: &dyn NyashBox, index: i64, value: Box<dyn NyashBox>) -> Result<(), String>;
|
|
|
|
|
|
|
|
|
|
|
|
/// 配列の末尾に要素を追加
|
|
|
|
|
|
fn push(&self, arr: &dyn NyashBox, value: Box<dyn NyashBox>) -> Result<(), String>;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// MapBox Service trait
|
2025-12-03 10:27:39 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 96: size/has/get/set 実装
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait MapService: Send + Sync {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
/// マップのサイズを取得
|
|
|
|
|
|
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<Box<dyn NyashBox>>;
|
|
|
|
|
|
|
|
|
|
|
|
/// 値を設定
|
|
|
|
|
|
fn set(&self, map: &dyn NyashBox, key: &str, value: Box<dyn NyashBox>) -> Result<(), String>;
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ConsoleBox Service trait
|
2025-12-03 09:57:38 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 95: println と print のみ実装
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub trait ConsoleService: Send + Sync {
|
2025-12-03 09:57:38 +09:00
|
|
|
|
fn println(&self, msg: &str);
|
|
|
|
|
|
fn print(&self, msg: &str);
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// CoreServices: core_required Box の集合
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Phase 85 設計原則:
|
|
|
|
|
|
/// - core_required は必ず全て揃っていなければならない
|
|
|
|
|
|
/// - 起動時に全フィールドが初期化されていることを保証
|
|
|
|
|
|
///
|
|
|
|
|
|
/// Phase 87 CoreBoxId との対応:
|
|
|
|
|
|
/// - String → string
|
|
|
|
|
|
/// - Integer → integer
|
|
|
|
|
|
/// - Bool → bool
|
|
|
|
|
|
/// - Array → array
|
|
|
|
|
|
/// - Map → map
|
|
|
|
|
|
/// - Console → console
|
2025-12-03 13:59:06 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 103: Optional化対応
|
|
|
|
|
|
/// - 各サービスは Option<Arc<dyn XyzService>> に変更
|
|
|
|
|
|
/// - ConsoleBox は必須(Graceful Degradation原則)
|
2025-12-03 07:43:08 +09:00
|
|
|
|
pub struct CoreServices {
|
2025-12-03 13:59:06 +09:00
|
|
|
|
pub string: Option<Arc<dyn StringService>>,
|
|
|
|
|
|
pub integer: Option<Arc<dyn IntegerService>>,
|
|
|
|
|
|
pub bool: Option<Arc<dyn BoolService>>,
|
|
|
|
|
|
pub array: Option<Arc<dyn ArrayService>>,
|
|
|
|
|
|
pub map: Option<Arc<dyn MapService>>,
|
|
|
|
|
|
pub console: Option<Arc<dyn ConsoleService>>,
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 09:57:38 +09:00
|
|
|
|
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()
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 07:43:08 +09:00
|
|
|
|
impl CoreServices {
|
2025-12-03 07:57:21 +09:00
|
|
|
|
/// 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,
|
|
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 07:43:08 +09:00
|
|
|
|
/// 全フィールドが初期化されているか検証
|
|
|
|
|
|
/// Phase 92 以降で各 Service の初期化を検証
|
|
|
|
|
|
pub fn ensure_initialized(&self) {
|
|
|
|
|
|
// Phase 91 では trait が空なので何もしない
|
|
|
|
|
|
// Phase 92 以降で各 Service の初期化を検証
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
// Phase 94: Adapter Pattern - Box → Service 変換
|
|
|
|
|
|
// ============================================================================
|
|
|
|
|
|
|
|
|
|
|
|
/// StringBox → StringService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 95.5: 純粋関数設計
|
|
|
|
|
|
/// - Box を保持せず、純粋関数として実装
|
|
|
|
|
|
/// - len(s) → s.chars().count() (UTF-8 文字数)
|
|
|
|
|
|
/// - Phase 96 以降で substring(), concat() など追加予定
|
|
|
|
|
|
pub struct StringBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl StringBoxAdapter {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl StringService for StringBoxAdapter {
|
2025-12-03 09:57:38 +09:00
|
|
|
|
fn len(&self, s: &str) -> i64 {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: 文字列長を返す(UTF-8 バイト数ではなく文字数)
|
2025-12-03 09:57:38 +09:00
|
|
|
|
s.chars().count() as i64
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// IntegerBox → IntegerService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
2025-12-03 10:41:16 +09:00
|
|
|
|
/// Phase 97: 純粋関数型(Box状態不要)
|
|
|
|
|
|
pub struct IntegerBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl IntegerBoxAdapter {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 08:42:45 +09:00
|
|
|
|
}
|
2025-12-03 07:43:08 +09:00
|
|
|
|
}
|
2025-12-03 07:57:21 +09:00
|
|
|
|
|
2025-12-03 09:14:49 +09:00
|
|
|
|
impl IntegerService for IntegerBoxAdapter {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
fn add(&self, a: i64, b: i64) -> i64 {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
a.saturating_add(b) // オーバーフロー対策
|
2025-12-03 10:41:16 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn sub(&self, a: i64, b: i64) -> i64 {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
a.saturating_sub(b) // アンダーフロー対策
|
2025-12-03 10:41:16 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn mul(&self, a: i64, b: i64) -> i64 {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
a.saturating_mul(b) // オーバーフロー対策
|
2025-12-03 10:41:16 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn div(&self, a: i64, b: i64) -> Option<i64> {
|
|
|
|
|
|
if b == 0 {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
None // ゼロ除算
|
2025-12-03 10:41:16 +09:00
|
|
|
|
} else {
|
|
|
|
|
|
Some(a / b)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// BoolBox → BoolService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
2025-12-03 10:41:16 +09:00
|
|
|
|
/// Phase 97: 純粋関数型(Box状態不要)
|
|
|
|
|
|
pub struct BoolBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl BoolBoxAdapter {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl BoolService for BoolBoxAdapter {
|
2025-12-03 10:41:16 +09:00
|
|
|
|
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
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ArrayBox → ArrayService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
2025-12-03 10:27:39 +09:00
|
|
|
|
/// Phase 96: downcast パターンで複数インスタンス対応
|
|
|
|
|
|
pub struct ArrayBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl ArrayBoxAdapter {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ArrayService for ArrayBoxAdapter {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
fn len(&self, arr: &dyn NyashBox) -> i64 {
|
|
|
|
|
|
arr.as_any()
|
2025-12-11 20:54:33 +09:00
|
|
|
|
.downcast_ref::<ArrayBox>()
|
|
|
|
|
|
.map(|a| a.len() as i64)
|
|
|
|
|
|
.unwrap_or(0)
|
2025-12-03 10:27:39 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn get(&self, arr: &dyn NyashBox, index: i64) -> Option<Box<dyn NyashBox>> {
|
|
|
|
|
|
let arr_box = arr.as_any().downcast_ref::<ArrayBox>()?;
|
|
|
|
|
|
let index_box = Box::new(IntegerBox::new(index));
|
|
|
|
|
|
Some(arr_box.get(index_box))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn set(&self, arr: &dyn NyashBox, index: i64, value: Box<dyn NyashBox>) -> Result<(), String> {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
let arr_box = arr
|
|
|
|
|
|
.as_any()
|
2025-12-03 10:27:39 +09:00
|
|
|
|
.downcast_ref::<ArrayBox>()
|
|
|
|
|
|
.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<dyn NyashBox>) -> Result<(), String> {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
let arr_box = arr
|
|
|
|
|
|
.as_any()
|
2025-12-03 10:27:39 +09:00
|
|
|
|
.downcast_ref::<ArrayBox>()
|
|
|
|
|
|
.ok_or("Not an ArrayBox")?;
|
|
|
|
|
|
arr_box.push(value);
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// MapBox → MapService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
2025-12-03 10:27:39 +09:00
|
|
|
|
/// Phase 96: downcast パターンで複数インスタンス対応
|
|
|
|
|
|
pub struct MapBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl MapBoxAdapter {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl MapService for MapBoxAdapter {
|
2025-12-03 10:27:39 +09:00
|
|
|
|
fn size(&self, map: &dyn NyashBox) -> i64 {
|
|
|
|
|
|
map.as_any()
|
2025-12-11 20:54:33 +09:00
|
|
|
|
.downcast_ref::<MapBox>()
|
|
|
|
|
|
.map(|m| {
|
|
|
|
|
|
// MapBox::size() は Box<dyn NyashBox> を返すため、IntegerBox に変換
|
|
|
|
|
|
let size_box = m.size();
|
|
|
|
|
|
size_box
|
|
|
|
|
|
.as_any()
|
|
|
|
|
|
.downcast_ref::<IntegerBox>()
|
|
|
|
|
|
.map(|i| i.value)
|
|
|
|
|
|
.unwrap_or(0)
|
|
|
|
|
|
})
|
|
|
|
|
|
.unwrap_or(0)
|
2025-12-03 10:27:39 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn has(&self, map: &dyn NyashBox, key: &str) -> bool {
|
|
|
|
|
|
let map_box = match map.as_any().downcast_ref::<MapBox>() {
|
|
|
|
|
|
Some(m) => m,
|
|
|
|
|
|
None => return false,
|
|
|
|
|
|
};
|
|
|
|
|
|
let key_box = Box::new(StringBox::new(key));
|
|
|
|
|
|
let result = map_box.has(key_box);
|
2025-12-11 20:54:33 +09:00
|
|
|
|
result
|
|
|
|
|
|
.as_any()
|
|
|
|
|
|
.downcast_ref::<BoolBox>()
|
|
|
|
|
|
.map(|b| b.value)
|
|
|
|
|
|
.unwrap_or(false)
|
2025-12-03 10:27:39 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn get(&self, map: &dyn NyashBox, key: &str) -> Option<Box<dyn NyashBox>> {
|
|
|
|
|
|
let map_box = map.as_any().downcast_ref::<MapBox>()?;
|
|
|
|
|
|
let key_box = Box::new(StringBox::new(key));
|
|
|
|
|
|
Some(map_box.get(key_box))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn set(&self, map: &dyn NyashBox, key: &str, value: Box<dyn NyashBox>) -> Result<(), String> {
|
2025-12-11 20:54:33 +09:00
|
|
|
|
let map_box = map
|
|
|
|
|
|
.as_any()
|
2025-12-03 10:27:39 +09:00
|
|
|
|
.downcast_ref::<MapBox>()
|
|
|
|
|
|
.ok_or("Not a MapBox")?;
|
|
|
|
|
|
let key_box = Box::new(StringBox::new(key));
|
|
|
|
|
|
map_box.set(key_box, value);
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// ConsoleBox → ConsoleService Adapter
|
2025-12-03 10:15:23 +09:00
|
|
|
|
///
|
|
|
|
|
|
/// Phase 95.5: Ring0 直結設計
|
|
|
|
|
|
/// - Box を保持せず、Ring0Context に直結
|
|
|
|
|
|
/// - println() → Ring0Context.log.info()
|
|
|
|
|
|
/// - print() → Ring0Context.io.stdout_write()
|
|
|
|
|
|
pub struct ConsoleBoxAdapter;
|
2025-12-03 09:14:49 +09:00
|
|
|
|
|
|
|
|
|
|
impl ConsoleBoxAdapter {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
|
Self
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl ConsoleService for ConsoleBoxAdapter {
|
2025-12-03 09:57:38 +09:00
|
|
|
|
fn println(&self, msg: &str) {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: Ring0Context 経由でログ出力(自動改行)
|
|
|
|
|
|
use crate::runtime::ring0::get_global_ring0;
|
|
|
|
|
|
let ring0 = get_global_ring0();
|
|
|
|
|
|
ring0.log.info(msg);
|
2025-12-03 09:57:38 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn print(&self, msg: &str) {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// 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();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
}
|
2025-12-03 09:14:49 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 07:57:21 +09:00
|
|
|
|
#[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));
|
|
|
|
|
|
}
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// 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();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-12-03 09:57:38 +09:00
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_console_service_println() {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: Ring0 初期化(安全な初期化)
|
|
|
|
|
|
ensure_ring0_initialized();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
2025-12-03 10:15:23 +09:00
|
|
|
|
let adapter = ConsoleBoxAdapter::new();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: println を呼び出し(Ring0 経由、panic しないことを確認)
|
|
|
|
|
|
adapter.println("Test message from Ring0");
|
2025-12-03 09:57:38 +09:00
|
|
|
|
// 実際の出力検証は Phase 96 以降
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_console_service_print() {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: Ring0 初期化(安全な初期化)
|
|
|
|
|
|
ensure_ring0_initialized();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
2025-12-03 10:15:23 +09:00
|
|
|
|
let adapter = ConsoleBoxAdapter::new();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: print を呼び出し(Ring0 経由、panic しないことを確認)
|
|
|
|
|
|
adapter.print("No newline");
|
2025-12-03 09:57:38 +09:00
|
|
|
|
// 実際の出力検証は Phase 96 以降
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_string_service_len() {
|
2025-12-03 10:15:23 +09:00
|
|
|
|
// Phase 95.5: 純粋関数なので Ring0 不要
|
|
|
|
|
|
let adapter = StringBoxAdapter::new();
|
2025-12-03 09:57:38 +09:00
|
|
|
|
|
|
|
|
|
|
// 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)
|
|
|
|
|
|
}
|
2025-12-03 10:15:23 +09:00
|
|
|
|
|
|
|
|
|
|
#[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 しないことを確認
|
|
|
|
|
|
}
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_array_service_basic_operations() {
|
|
|
|
|
|
use crate::box_trait::IntegerBox;
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::boxes::array::ArrayBox;
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
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::<IntegerBox>().unwrap();
|
|
|
|
|
|
assert_eq!(int_box.value, 42);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_array_service_set() {
|
|
|
|
|
|
use crate::box_trait::IntegerBox;
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::boxes::array::ArrayBox;
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
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::<IntegerBox>().unwrap();
|
|
|
|
|
|
assert_eq!(int_box.value, 20);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_map_service_basic_operations() {
|
|
|
|
|
|
use crate::box_trait::StringBox;
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::boxes::map_box::MapBox;
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
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::<StringBox>().unwrap();
|
|
|
|
|
|
assert_eq!(str_box.value, "Hello");
|
|
|
|
|
|
|
|
|
|
|
|
// size
|
|
|
|
|
|
assert_eq!(adapter.size(&map), 1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_map_service_multiple_keys() {
|
|
|
|
|
|
use crate::box_trait::{IntegerBox, StringBox};
|
2025-12-11 20:54:33 +09:00
|
|
|
|
use crate::boxes::map_box::MapBox;
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
let map = MapBox::new();
|
|
|
|
|
|
let adapter = MapBoxAdapter::new();
|
|
|
|
|
|
|
|
|
|
|
|
// set multiple keys
|
2025-12-11 20:54:33 +09:00
|
|
|
|
adapter
|
|
|
|
|
|
.set(&map, "name", Box::new(StringBox::new("Alice")))
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
adapter
|
|
|
|
|
|
.set(&map, "age", Box::new(IntegerBox::new(25)))
|
|
|
|
|
|
.unwrap();
|
2025-12-03 10:27:39 +09:00
|
|
|
|
|
|
|
|
|
|
// 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::<StringBox>().unwrap();
|
|
|
|
|
|
assert_eq!(name_str.value, "Alice");
|
|
|
|
|
|
|
|
|
|
|
|
let age = adapter.get(&map, "age").unwrap();
|
|
|
|
|
|
let age_int = age.as_any().downcast_ref::<IntegerBox>().unwrap();
|
|
|
|
|
|
assert_eq!(age_int.value, 25);
|
|
|
|
|
|
}
|
2025-12-03 10:41:16 +09:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn test_integer_service_operations() {
|
|
|
|
|
|
let adapter = IntegerBoxAdapter::new();
|
|
|
|
|
|
|
|
|
|
|
|
// add
|
|
|
|
|
|
assert_eq!(adapter.add(10, 20), 30);
|
2025-12-11 20:54:33 +09:00
|
|
|
|
assert_eq!(adapter.add(i64::MAX, 1), i64::MAX); // saturating
|
2025-12-03 10:41:16 +09:00
|
|
|
|
|
|
|
|
|
|
// sub
|
|
|
|
|
|
assert_eq!(adapter.sub(20, 10), 10);
|
2025-12-11 20:54:33 +09:00
|
|
|
|
assert_eq!(adapter.sub(i64::MIN, 1), i64::MIN); // saturating
|
2025-12-03 10:41:16 +09:00
|
|
|
|
|
|
|
|
|
|
// mul
|
|
|
|
|
|
assert_eq!(adapter.mul(5, 6), 30);
|
2025-12-11 20:54:33 +09:00
|
|
|
|
assert_eq!(adapter.mul(i64::MAX, 2), i64::MAX); // saturating
|
2025-12-03 10:41:16 +09:00
|
|
|
|
|
|
|
|
|
|
// div
|
|
|
|
|
|
assert_eq!(adapter.div(20, 5), Some(4));
|
2025-12-11 20:54:33 +09:00
|
|
|
|
assert_eq!(adapter.div(10, 3), Some(3)); // 整数除算
|
|
|
|
|
|
assert_eq!(adapter.div(10, 0), None); // ゼロ除算
|
2025-12-03 10:41:16 +09:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[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);
|
|
|
|
|
|
}
|
2025-12-03 07:57:21 +09:00
|
|
|
|
}
|