diff --git a/src/boxes/array/mod.rs b/src/boxes/array/mod.rs index 4cef49f4..33853490 100644 --- a/src/boxes/array/mod.rs +++ b/src/boxes/array/mod.rs @@ -1,15 +1,14 @@ //! ArrayBox 📦 - 配列・リスト操作 // Nyashの箱システムによる配列・リスト操作を提供します。 -// Arcパターンで内部可変性を実現 +// RwLockパターンで内部可変性を実現(Phase 9.75-B Arc削除) use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox, BoxCore, BoxBase}; use std::any::Any; -use std::sync::{Arc, Mutex}; +use std::sync::RwLock; use std::fmt::Display; -#[derive(Debug, Clone)] pub struct ArrayBox { - pub items: Arc>>>, + pub items: RwLock>>, base: BoxBase, } @@ -17,7 +16,7 @@ impl ArrayBox { /// 新しいArrayBoxを作成 pub fn new() -> Self { ArrayBox { - items: Arc::new(Mutex::new(Vec::new())), + items: RwLock::new(Vec::new()), base: BoxBase::new(), } } @@ -25,20 +24,20 @@ impl ArrayBox { /// 要素を持つArrayBoxを作成 pub fn new_with_elements(elements: Vec>) -> Self { ArrayBox { - items: Arc::new(Mutex::new(elements)), + items: RwLock::new(elements), base: BoxBase::new(), } } /// 要素を追加 pub fn push(&self, item: Box) -> Box { - self.items.lock().unwrap().push(item); + self.items.write().unwrap().push(item); Box::new(StringBox::new("ok")) } /// 最後の要素を取り出す pub fn pop(&self) -> Box { - match self.items.lock().unwrap().pop() { + match self.items.write().unwrap().pop() { Some(item) => item, None => Box::new(crate::boxes::null_box::NullBox::new()), } @@ -46,19 +45,19 @@ impl ArrayBox { /// 要素数を取得 pub fn length(&self) -> Box { - Box::new(IntegerBox::new(self.items.lock().unwrap().len() as i64)) + Box::new(IntegerBox::new(self.items.read().unwrap().len() as i64)) } /// Rust向けヘルパー: 要素数をusizeで取得(テスト用) pub fn len(&self) -> usize { - self.items.lock().unwrap().len() + self.items.read().unwrap().len() } /// インデックスで要素を取得 pub fn get(&self, index: Box) -> Box { if let Some(idx_box) = index.as_any().downcast_ref::() { let idx = idx_box.value as usize; - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); match items.get(idx) { Some(item) => item.clone_box(), None => Box::new(crate::boxes::null_box::NullBox::new()), @@ -72,7 +71,7 @@ impl ArrayBox { pub fn set(&self, index: Box, value: Box) -> Box { if let Some(idx_box) = index.as_any().downcast_ref::() { let idx = idx_box.value as usize; - let mut items = self.items.lock().unwrap(); + let mut items = self.items.write().unwrap(); if idx < items.len() { items[idx] = value; Box::new(StringBox::new("ok")) @@ -88,7 +87,7 @@ impl ArrayBox { pub fn remove(&self, index: Box) -> Box { if let Some(idx_box) = index.as_any().downcast_ref::() { let idx = idx_box.value as usize; - let mut items = self.items.lock().unwrap(); + let mut items = self.items.write().unwrap(); if idx < items.len() { items.remove(idx) } else { @@ -101,7 +100,7 @@ impl ArrayBox { /// 指定された値のインデックスを検索 pub fn indexOf(&self, value: Box) -> Box { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); for (i, item) in items.iter().enumerate() { if item.equals(value.as_ref()).value { return Box::new(IntegerBox::new(i as i64)); @@ -112,7 +111,7 @@ impl ArrayBox { /// 指定された値が含まれているか確認 pub fn contains(&self, value: Box) -> Box { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); for item in items.iter() { if item.equals(value.as_ref()).value { return Box::new(BoolBox::new(true)); @@ -123,14 +122,14 @@ impl ArrayBox { /// 配列を空にする pub fn clear(&self) -> Box { - self.items.lock().unwrap().clear(); + self.items.write().unwrap().clear(); Box::new(StringBox::new("ok")) } /// 文字列結合 pub fn join(&self, delimiter: Box) -> Box { if let Some(sep_box) = delimiter.as_any().downcast_ref::() { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); let parts: Vec = items .iter() .map(|item| item.to_string_box().value) @@ -143,7 +142,7 @@ impl ArrayBox { /// 配列をソート(昇順) pub fn sort(&self) -> Box { - let mut items = self.items.lock().unwrap(); + let mut items = self.items.write().unwrap(); // Numeric values first, then string values items.sort_by(|a, b| { @@ -191,14 +190,14 @@ impl ArrayBox { /// 配列を反転 pub fn reverse(&self) -> Box { - let mut items = self.items.lock().unwrap(); + let mut items = self.items.write().unwrap(); items.reverse(); Box::new(StringBox::new("ok")) } /// 部分配列を取得 pub fn slice(&self, start: Box, end: Box) -> Box { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); // Extract start and end indices let start_idx = if let Some(start_int) = start.as_any().downcast_ref::() { @@ -236,6 +235,17 @@ impl ArrayBox { } } +// Clone implementation for ArrayBox (needed since RwLock doesn't auto-derive Clone) +impl Clone for ArrayBox { + fn clone(&self) -> Self { + let items = self.items.read().unwrap(); + let cloned_items: Vec> = items.iter() + .map(|item| item.clone_box()) + .collect(); + ArrayBox::new_with_elements(cloned_items) + } +} + impl BoxCore for ArrayBox { fn box_id(&self) -> u64 { self.base.id @@ -246,7 +256,7 @@ impl BoxCore for ArrayBox { } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); let strings: Vec = items.iter() .map(|item| item.to_string_box().value) .collect(); @@ -274,7 +284,7 @@ impl NyashBox for ArrayBox { } fn to_string_box(&self) -> StringBox { - let items = self.items.lock().unwrap(); + let items = self.items.read().unwrap(); let strings: Vec = items.iter() .map(|item| item.to_string_box().value) .collect(); diff --git a/src/boxes/buffer/mod.rs b/src/boxes/buffer/mod.rs index abc75cef..70788be1 100644 --- a/src/boxes/buffer/mod.rs +++ b/src/boxes/buffer/mod.rs @@ -31,31 +31,30 @@ use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox, BoxCore, BoxBase}; use crate::boxes::array::ArrayBox; use std::any::Any; -use std::sync::{Arc, Mutex}; +use std::sync::RwLock; use std::fmt::{Debug, Display}; -#[derive(Debug, Clone)] pub struct BufferBox { - data: Arc>>, + data: RwLock>, base: BoxBase, } impl BufferBox { pub fn new() -> Self { BufferBox { - data: Arc::new(Mutex::new(Vec::new())), + data: RwLock::new(Vec::new()), base: BoxBase::new(), } } /// Rust向けヘルパー: バッファ長をusizeで取得(テスト用) pub fn len(&self) -> usize { - self.data.lock().unwrap().len() + self.data.read().unwrap().len() } pub fn from_vec(data: Vec) -> Self { BufferBox { - data: Arc::new(Mutex::new(data)), + data: RwLock::new(data), base: BoxBase::new(), } } @@ -64,8 +63,8 @@ impl BufferBox { pub fn write(&self, data: Box) -> Box { // ArrayBoxから変換 - use crate::boxes::array::ArrayBox directly if let Some(array_box) = data.as_any().downcast_ref::() { - let mut buffer = self.data.lock().unwrap(); - let items = array_box.items.lock().unwrap(); + let mut buffer = self.data.write().unwrap(); + let items = array_box.items.read().unwrap(); for item in items.iter() { if let Some(int_box) = item.as_any().downcast_ref::() { if int_box.value >= 0 && int_box.value <= 255 { @@ -82,7 +81,7 @@ impl BufferBox { /// すべてのデータを読み取る pub fn readAll(&self) -> Box { - let buffer = self.data.lock().unwrap(); + let buffer = self.data.read().unwrap(); let array = ArrayBox::new(); for &byte in buffer.iter() { array.push(Box::new(IntegerBox::new(byte as i64))); @@ -93,7 +92,7 @@ impl BufferBox { /// 指定バイト数読み取る pub fn read(&self, count: Box) -> Box { if let Some(count_int) = count.as_any().downcast_ref::() { - let mut buffer = self.data.lock().unwrap(); + let mut buffer = self.data.write().unwrap(); let count = count_int.value.min(buffer.len() as i64) as usize; let array = ArrayBox::new(); @@ -110,20 +109,20 @@ impl BufferBox { /// バッファをクリア pub fn clear(&self) -> Box { - self.data.lock().unwrap().clear(); + self.data.write().unwrap().clear(); Box::new(StringBox::new("ok")) } /// データサイズを取得 pub fn length(&self) -> Box { - Box::new(IntegerBox::new(self.data.lock().unwrap().len() as i64)) + Box::new(IntegerBox::new(self.data.read().unwrap().len() as i64)) } /// 他のBufferBoxを追加 pub fn append(&self, other: Box) -> Box { if let Some(other_buffer) = other.as_any().downcast_ref::() { - let mut self_data = self.data.lock().unwrap(); - let other_data = other_buffer.data.lock().unwrap(); + let mut self_data = self.data.write().unwrap(); + let other_data = other_buffer.data.read().unwrap(); self_data.extend_from_slice(&other_data); Box::new(IntegerBox::new(self_data.len() as i64)) } else { @@ -137,7 +136,7 @@ impl BufferBox { start.as_any().downcast_ref::(), end.as_any().downcast_ref::() ) { - let data = self.data.lock().unwrap(); + let data = self.data.read().unwrap(); let start = (start_int.value as usize).min(data.len()); let end = (end_int.value as usize).min(data.len()); @@ -153,6 +152,14 @@ impl BufferBox { } } +// Clone implementation for BufferBox (needed since RwLock doesn't auto-derive Clone) +impl Clone for BufferBox { + fn clone(&self) -> Self { + let data = self.data.read().unwrap(); + BufferBox::from_vec(data.clone()) + } +} + impl BoxCore for BufferBox { fn box_id(&self) -> u64 { self.base.id @@ -163,7 +170,7 @@ impl BoxCore for BufferBox { } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let data = self.data.lock().unwrap(); + let data = self.data.read().unwrap(); write!(f, "BufferBox({} bytes)", data.len()) } @@ -188,7 +195,7 @@ impl NyashBox for BufferBox { } fn to_string_box(&self) -> StringBox { - let data = self.data.lock().unwrap(); + let data = self.data.read().unwrap(); StringBox::new(format!("BufferBox({} bytes)", data.len())) } @@ -200,9 +207,9 @@ impl NyashBox for BufferBox { fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_buffer) = other.as_any().downcast_ref::() { - // Arcの内容を比較 - let self_data = self.data.lock().unwrap(); - let other_data = other_buffer.data.lock().unwrap(); + // RwLock内容を比較 + let self_data = self.data.read().unwrap(); + let other_data = other_buffer.data.read().unwrap(); BoolBox::new(*self_data == *other_data) } else { BoolBox::new(false) diff --git a/src/boxes/map_box.rs b/src/boxes/map_box.rs index c8535d74..d2e31be0 100644 --- a/src/boxes/map_box.rs +++ b/src/boxes/map_box.rs @@ -108,19 +108,18 @@ use crate::boxes::ArrayBox; use std::fmt::{Debug, Display}; use std::any::Any; use std::collections::HashMap; -use std::sync::{Arc, Mutex}; +use std::sync::RwLock; /// キーバリューストアを表すBox -#[derive(Clone)] pub struct MapBox { - data: Arc>>>, + data: RwLock>>, base: BoxBase, } impl MapBox { pub fn new() -> Self { Self { - data: Arc::new(Mutex::new(HashMap::new())), + data: RwLock::new(HashMap::new()), base: BoxBase::new(), } } @@ -128,14 +127,14 @@ impl MapBox { /// 値を設定 pub fn set(&self, key: Box, value: Box) -> Box { let key_str = key.to_string_box().value; - self.data.lock().unwrap().insert(key_str.clone(), value); + self.data.write().unwrap().insert(key_str.clone(), value); Box::new(StringBox::new(&format!("Set key: {}", key_str))) } /// 値を取得 pub fn get(&self, key: Box) -> Box { let key_str = key.to_string_box().value; - match self.data.lock().unwrap().get(&key_str) { + match self.data.read().unwrap().get(&key_str) { Some(value) => value.clone_box(), None => Box::new(StringBox::new(&format!("Key not found: {}", key_str))), } @@ -144,13 +143,13 @@ impl MapBox { /// キーが存在するかチェック pub fn has(&self, key: Box) -> Box { let key_str = key.to_string_box().value; - Box::new(BoolBox::new(self.data.lock().unwrap().contains_key(&key_str))) + Box::new(BoolBox::new(self.data.read().unwrap().contains_key(&key_str))) } /// キーを削除 pub fn delete(&self, key: Box) -> Box { let key_str = key.to_string_box().value; - match self.data.lock().unwrap().remove(&key_str) { + match self.data.write().unwrap().remove(&key_str) { Some(_) => Box::new(StringBox::new(&format!("Deleted key: {}", key_str))), None => Box::new(StringBox::new(&format!("Key not found: {}", key_str))), } @@ -158,7 +157,7 @@ impl MapBox { /// 全てのキーを取得 pub fn keys(&self) -> Box { - let keys: Vec = self.data.lock().unwrap().keys().cloned().collect(); + let keys: Vec = self.data.read().unwrap().keys().cloned().collect(); let array = ArrayBox::new(); for key in keys { array.push(Box::new(StringBox::new(&key))); @@ -168,7 +167,7 @@ impl MapBox { /// 全ての値を取得 pub fn values(&self) -> Box { - let values: Vec> = self.data.lock().unwrap() + let values: Vec> = self.data.read().unwrap() .values() .map(|v| v.clone_box()) .collect(); @@ -181,25 +180,25 @@ impl MapBox { /// サイズを取得 pub fn size(&self) -> Box { - Box::new(IntegerBox::new(self.data.lock().unwrap().len() as i64)) + Box::new(IntegerBox::new(self.data.read().unwrap().len() as i64)) } /// 全てクリア pub fn clear(&self) -> Box { - self.data.lock().unwrap().clear(); + self.data.write().unwrap().clear(); Box::new(StringBox::new("Map cleared")) } /// 各要素に対して関数を実行 pub fn forEach(&self, _callback: Box) -> Box { // 簡易実装:callbackの実行はスキップ - let count = self.data.lock().unwrap().len(); + let count = self.data.read().unwrap().len(); Box::new(StringBox::new(&format!("Iterated over {} items", count))) } /// JSON文字列に変換 pub fn toJSON(&self) -> Box { - let data = self.data.lock().unwrap(); + let data = self.data.read().unwrap(); let mut json_parts = Vec::new(); for (key, value) in data.iter() { @@ -218,8 +217,22 @@ impl MapBox { } /// 内部データへのアクセス(JSONBox用) - pub fn get_data(&self) -> Arc>>> { - self.data.clone() + pub fn get_data(&self) -> &RwLock>> { + &self.data + } +} + +// Clone implementation for MapBox (needed since RwLock doesn't auto-derive Clone) +impl Clone for MapBox { + fn clone(&self) -> Self { + let data = self.data.read().unwrap(); + let cloned_data: HashMap> = data.iter() + .map(|(k, v)| (k.clone(), v.clone_box())) + .collect(); + MapBox { + data: RwLock::new(cloned_data), + base: BoxBase::new(), + } } } @@ -233,7 +246,7 @@ impl BoxCore for MapBox { } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - let size = self.data.lock().unwrap().len(); + let size = self.data.read().unwrap().len(); write!(f, "MapBox(size={})", size) } @@ -252,7 +265,7 @@ impl NyashBox for MapBox { } fn to_string_box(&self) -> StringBox { - let size = self.data.lock().unwrap().len(); + let size = self.data.read().unwrap().len(); StringBox::new(&format!("MapBox(size={})", size)) } @@ -279,7 +292,7 @@ impl Display for MapBox { impl Debug for MapBox { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let data = self.data.lock().unwrap(); + let data = self.data.read().unwrap(); f.debug_struct("MapBox") .field("id", &self.base.id) .field("size", &data.len())