/*! 📊 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, IntegerBox, BoxCore, BoxBase}; use crate::boxes::array::ArrayBox; use std::any::Any; use std::sync::RwLock; use std::fmt::{Debug, Display}; pub struct BufferBox { data: RwLock>, base: BoxBase, } impl BufferBox { pub fn new() -> Self { BufferBox { data: RwLock::new(Vec::new()), base: BoxBase::new(), } } /// Rust向けヘルパー: バッファ長をusizeで取得(テスト用) pub fn len(&self) -> usize { self.data.read().unwrap().len() } pub fn from_vec(data: Vec) -> Self { BufferBox { data: RwLock::new(data), base: BoxBase::new(), } } /// データを書き込む 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.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 { buffer.push(int_box.value as u8); } } } Box::new(IntegerBox::new(buffer.len() as i64)) } else { let type_name = data.type_name(); Box::new(StringBox::new(&format!("Error: write() requires ArrayBox of integers, got {}", type_name))) } } /// すべてのデータを読み取る pub fn readAll(&self) -> Box { let buffer = self.data.read().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) -> Box { if let Some(count_int) = count.as_any().downcast_ref::() { let mut buffer = self.data.write().unwrap(); let count = count_int.value.min(buffer.len() as i64) as usize; let array = ArrayBox::new(); // 先頭からcount個取り出す let bytes: Vec = 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 { self.data.write().unwrap().clear(); Box::new(StringBox::new("ok")) } /// データサイズを取得 pub fn length(&self) -> Box { 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.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 { Box::new(StringBox::new("Error: append() requires BufferBox")) } } /// 部分データ取得 pub fn slice(&self, start: Box, end: Box) -> Box { if let (Some(start_int), Some(end_int)) = ( start.as_any().downcast_ref::(), end.as_any().downcast_ref::() ) { 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()); 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")) } } } // 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 } fn parent_type_id(&self) -> Option { self.base.parent_type_id } fn fmt_box(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { let data = self.data.read().unwrap(); write!(f, "BufferBox({} bytes)", data.len()) } fn as_any(&self) -> &dyn Any { self } fn as_any_mut(&mut self) -> &mut dyn Any { self } } impl Display for BufferBox { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { self.fmt_box(f) } } impl NyashBox for BufferBox { fn clone_box(&self) -> Box { Box::new(self.clone()) } fn to_string_box(&self) -> StringBox { let data = self.data.read().unwrap(); StringBox::new(format!("BufferBox({} bytes)", data.len())) } fn type_name(&self) -> &'static str { "BufferBox" } fn equals(&self, other: &dyn NyashBox) -> BoolBox { if let Some(other_buffer) = other.as_any().downcast_ref::() { // 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) } } }