🔧 refactor: すべてのBoxをArc<Mutex>パターンで統一

CopilotのBox実装を私たちのArc<Mutex>パターンで統一:
- BufferBox: Arc<Mutex<Vec<u8>>>で内部可変性を実現
- FileBox: Arc<Mutex<File>>でファイルハンドル管理
- JSONBox: Arc<Mutex<Value>>でJSON値を保持
- HttpClientBox: Arc<Mutex<Client>>でHTTPクライアント管理
- StreamBox: Arc<Mutex>でストリームバッファと位置を管理
- RegexBox: Arc<Regex>で軽量ラッパー実装

各Boxに実用的なメソッドも追加:
- BufferBox: write, read, readAll, clear, length, append, slice
- FileBox: read, write, exists, delete, copy
- JSONBox: parse, stringify, get, set, has, keys
- HttpClientBox: get, post, put, delete, request
- StreamBox: write, read, position, length, reset
- RegexBox: test, find, findAll, replace, split

interpreterに新Box用のメソッド実行を追加:
- data_methods.rs: BufferBox, JSONBox, RegexBox
- network_methods.rs: HttpClientBox, StreamBox

これでコードベース全体が一貫性のあるArc<Mutex>パターンで統一されました!

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-10 13:03:42 +09:00
parent b745f5ffa2
commit 750543be7c
12 changed files with 989 additions and 110 deletions

View File

@ -1,13 +1,42 @@
//! BufferBox 📊 - バイナリデータ処理
// Nyashの箱システムによるバイナリデータ処理を提供します。
// 参考: 既存Boxの設計思想
/*! 📊 BufferBox - バイナリデータ処理Box
*
* ## 📝 概要
* バイナリデータの読み書きを扱うBox。
* ファイル操作、ネットワーク通信、画像処理などで使用。
*
* ## 🛠️ 利用可能メソッド
* - `write(data)` - バイトデータ書き込み
* - `read(count)` - 指定バイト数読み取り
* - `readAll()` - 全データ読み取り
* - `clear()` - バッファクリア
* - `length()` - データサイズ取得
* - `append(buffer)` - 他のBufferを追加
* - `slice(start, end)` - 部分データ取得
*
* ## 💡 使用例
* ```nyash
* local buffer
* buffer = new BufferBox()
*
* // データ書き込み
* buffer.write([72, 101, 108, 108, 111]) // "Hello"
* print("Size: " + buffer.length())
*
* // データ読み取り
* local data
* data = buffer.readAll()
* ```
*/
use crate::box_trait::{NyashBox, StringBox, BoolBox};
use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox};
use crate::boxes::array::ArrayBox;
use std::any::Any;
use std::sync::{Arc, Mutex};
use std::fmt::{Debug, Display};
#[derive(Debug, Clone)]
pub struct BufferBox {
pub data: Vec<u8>,
data: Arc<Mutex<Vec<u8>>>,
id: u64,
}
@ -19,7 +48,7 @@ impl BufferBox {
COUNTER
};
BufferBox {
data: Vec::new(),
data: Arc::new(Mutex::new(Vec::new())),
id,
}
}
@ -30,15 +59,101 @@ impl BufferBox {
COUNTER += 1;
COUNTER
};
BufferBox { data, id }
BufferBox {
data: Arc::new(Mutex::new(data)),
id,
}
}
pub fn len(&self) -> usize {
self.data.len()
/// データを書き込む
pub fn write(&self, data: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
// ArrayBoxから変換
if let Some(array_box) = data.as_any().downcast_ref::<ArrayBox>() {
let mut buffer = self.data.lock().unwrap();
let items = array_box.items.lock().unwrap();
for item in items.iter() {
if let Some(int_box) = item.as_any().downcast_ref::<IntegerBox>() {
if int_box.value >= 0 && int_box.value <= 255 {
buffer.push(int_box.value as u8);
}
}
}
Box::new(IntegerBox::new(buffer.len() as i64))
} else {
Box::new(StringBox::new("Error: write() requires ArrayBox of integers"))
}
}
pub fn as_slice(&self) -> &[u8] {
&self.data
/// すべてのデータを読み取る
pub fn readAll(&self) -> Box<dyn NyashBox> {
let buffer = self.data.lock().unwrap();
let array = ArrayBox::new();
for &byte in buffer.iter() {
array.push(Box::new(IntegerBox::new(byte as i64)));
}
Box::new(array)
}
/// 指定バイト数読み取る
pub fn read(&self, count: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
if let Some(count_int) = count.as_any().downcast_ref::<IntegerBox>() {
let mut buffer = self.data.lock().unwrap();
let count = count_int.value.min(buffer.len() as i64) as usize;
let array = ArrayBox::new();
// 先頭からcount個取り出す
let bytes: Vec<u8> = buffer.drain(0..count).collect();
for byte in bytes {
array.push(Box::new(IntegerBox::new(byte as i64)));
}
Box::new(array)
} else {
Box::new(StringBox::new("Error: read() requires integer count"))
}
}
/// バッファをクリア
pub fn clear(&self) -> Box<dyn NyashBox> {
self.data.lock().unwrap().clear();
Box::new(StringBox::new("ok"))
}
/// データサイズを取得
pub fn length(&self) -> Box<dyn NyashBox> {
Box::new(IntegerBox::new(self.data.lock().unwrap().len() as i64))
}
/// 他のBufferBoxを追加
pub fn append(&self, other: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
if let Some(other_buffer) = other.as_any().downcast_ref::<BufferBox>() {
let mut self_data = self.data.lock().unwrap();
let other_data = other_buffer.data.lock().unwrap();
self_data.extend_from_slice(&other_data);
Box::new(IntegerBox::new(self_data.len() as i64))
} else {
Box::new(StringBox::new("Error: append() requires BufferBox"))
}
}
/// 部分データ取得
pub fn slice(&self, start: Box<dyn NyashBox>, end: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
if let (Some(start_int), Some(end_int)) = (
start.as_any().downcast_ref::<IntegerBox>(),
end.as_any().downcast_ref::<IntegerBox>()
) {
let data = self.data.lock().unwrap();
let start = (start_int.value as usize).min(data.len());
let end = (end_int.value as usize).min(data.len());
if start <= end {
let slice_data = data[start..end].to_vec();
Box::new(BufferBox::from_vec(slice_data))
} else {
Box::new(StringBox::new("Error: invalid slice range"))
}
} else {
Box::new(StringBox::new("Error: slice() requires integer indices"))
}
}
}
@ -48,7 +163,8 @@ impl NyashBox for BufferBox {
}
fn to_string_box(&self) -> StringBox {
StringBox::new(format!("BufferBox({} bytes)", self.data.len()))
let data = self.data.lock().unwrap();
StringBox::new(format!("BufferBox({} bytes)", data.len()))
}
fn as_any(&self) -> &dyn Any {