🔧 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:
@ -1,13 +1,42 @@
|
|||||||
//! BufferBox 📊 - バイナリデータ処理
|
/*! 📊 BufferBox - バイナリデータ処理Box
|
||||||
// Nyashの箱システムによるバイナリデータ処理を提供します。
|
*
|
||||||
// 参考: 既存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::any::Any;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
use std::fmt::{Debug, Display};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct BufferBox {
|
pub struct BufferBox {
|
||||||
pub data: Vec<u8>,
|
data: Arc<Mutex<Vec<u8>>>,
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,7 +48,7 @@ impl BufferBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
BufferBox {
|
BufferBox {
|
||||||
data: Vec::new(),
|
data: Arc::new(Mutex::new(Vec::new())),
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -30,15 +59,101 @@ impl BufferBox {
|
|||||||
COUNTER += 1;
|
COUNTER += 1;
|
||||||
COUNTER
|
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 {
|
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 {
|
fn as_any(&self) -> &dyn Any {
|
||||||
|
|||||||
@ -6,11 +6,12 @@ use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
|||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fs::{File, OpenOptions};
|
use std::fs::{File, OpenOptions};
|
||||||
use std::io::{Read, Write, Result};
|
use std::io::{Read, Write, Result};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct FileBox {
|
pub struct FileBox {
|
||||||
pub file: File,
|
file: Arc<Mutex<File>>,
|
||||||
pub path: String,
|
path: Arc<String>,
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -23,20 +24,61 @@ impl FileBox {
|
|||||||
};
|
};
|
||||||
let file = OpenOptions::new().read(true).write(true).create(true).open(path)?;
|
let file = OpenOptions::new().read(true).write(true).create(true).open(path)?;
|
||||||
Ok(FileBox {
|
Ok(FileBox {
|
||||||
file,
|
file: Arc::new(Mutex::new(file)),
|
||||||
path: path.to_string(),
|
path: Arc::new(path.to_string()),
|
||||||
id,
|
id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_to_string(&mut self) -> Result<String> {
|
pub fn read_to_string(&self) -> Result<String> {
|
||||||
|
let mut file = self.file.lock().unwrap();
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
self.file.read_to_string(&mut s)?;
|
file.read_to_string(&mut s)?;
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_all(&mut self, buf: &[u8]) -> Result<()> {
|
pub fn write_all(&self, buf: &[u8]) -> Result<()> {
|
||||||
self.file.write_all(buf)
|
let mut file = self.file.lock().unwrap();
|
||||||
|
file.write_all(buf)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ファイルの内容を読み取る
|
||||||
|
pub fn read(&self) -> Box<dyn NyashBox> {
|
||||||
|
match self.read_to_string() {
|
||||||
|
Ok(content) => Box::new(StringBox::new(&content)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading file: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ファイルに内容を書き込む
|
||||||
|
pub fn write(&self, content: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let content_str = content.to_string_box().value;
|
||||||
|
match self.write_all(content_str.as_bytes()) {
|
||||||
|
Ok(()) => Box::new(StringBox::new("ok")),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error writing file: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ファイルが存在するかチェック
|
||||||
|
pub fn exists(&self) -> Box<dyn NyashBox> {
|
||||||
|
use std::path::Path;
|
||||||
|
Box::new(BoolBox::new(Path::new(&**self.path).exists()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ファイルを削除
|
||||||
|
pub fn delete(&self) -> Box<dyn NyashBox> {
|
||||||
|
match std::fs::remove_file(&**self.path) {
|
||||||
|
Ok(()) => Box::new(StringBox::new("ok")),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error deleting file: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ファイルをコピー
|
||||||
|
pub fn copy(&self, dest: &str) -> Box<dyn NyashBox> {
|
||||||
|
match std::fs::copy(&**self.path, dest) {
|
||||||
|
Ok(_) => Box::new(StringBox::new("ok")),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error copying file: {}", e))),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +109,7 @@ impl NyashBox for FileBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_file) = other.as_any().downcast_ref::<FileBox>() {
|
if let Some(other_file) = other.as_any().downcast_ref::<FileBox>() {
|
||||||
BoolBox::new(self.path == other_file.path)
|
BoolBox::new(*self.path == *other_file.path)
|
||||||
} else {
|
} else {
|
||||||
BoolBox::new(false)
|
BoolBox::new(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,18 +109,12 @@ impl NyashBox for NyashFutureBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the original generic FutureBox for compatibility
|
// Export NyashFutureBox as FutureBox for consistency
|
||||||
pub struct FutureBox<T> {
|
pub type FutureBox = NyashFutureBox;
|
||||||
pub future: Pin<Box<dyn Future<Output = T> + Send>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> FutureBox<T> {
|
impl FutureBox {
|
||||||
pub fn new<F>(fut: F) -> Self
|
/// wait_and_get()の実装 - await演算子で使用
|
||||||
where
|
pub fn wait_and_get(&self) -> Result<Box<dyn NyashBox>, String> {
|
||||||
F: Future<Output = T> + Send + 'static,
|
Ok(self.get())
|
||||||
{
|
|
||||||
FutureBox {
|
|
||||||
future: Box::pin(fut),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,13 +3,15 @@
|
|||||||
// 参考: 既存Boxの設計思想
|
// 参考: 既存Boxの設計思想
|
||||||
|
|
||||||
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
||||||
|
use crate::boxes::map_box::MapBox;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use reqwest::blocking::Client;
|
use reqwest::blocking::Client;
|
||||||
use reqwest::Result;
|
use reqwest::Result;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct HttpClientBox {
|
pub struct HttpClientBox {
|
||||||
pub client: Client,
|
client: Arc<Mutex<Client>>,
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,21 +23,123 @@ impl HttpClientBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
HttpClientBox {
|
HttpClientBox {
|
||||||
client: Client::new(),
|
client: Arc::new(Mutex::new(Client::new())),
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, url: &str) -> Result<String> {
|
pub fn get(&self, url: &str) -> Result<String> {
|
||||||
let res = self.client.get(url).send()?.text()?;
|
let client = self.client.lock().unwrap();
|
||||||
|
let res = client.get(url).send()?.text()?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// HTTP GETリクエスト
|
||||||
|
pub fn http_get(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let url_str = url.to_string_box().value;
|
||||||
|
match self.get(&url_str) {
|
||||||
|
Ok(response) => Box::new(StringBox::new(&response)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error in HTTP GET: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HTTP POSTリクエスト
|
||||||
|
pub fn post(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let url_str = url.to_string_box().value;
|
||||||
|
let body_str = body.to_string_box().value;
|
||||||
|
|
||||||
|
let client = self.client.lock().unwrap();
|
||||||
|
match client.post(&url_str).body(body_str).send() {
|
||||||
|
Ok(response) => {
|
||||||
|
match response.text() {
|
||||||
|
Ok(text) => Box::new(StringBox::new(&text)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading response: {}", e))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error in HTTP POST: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HTTP PUT リクエスト
|
||||||
|
pub fn put(&self, url: Box<dyn NyashBox>, body: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let url_str = url.to_string_box().value;
|
||||||
|
let body_str = body.to_string_box().value;
|
||||||
|
|
||||||
|
let client = self.client.lock().unwrap();
|
||||||
|
match client.put(&url_str).body(body_str).send() {
|
||||||
|
Ok(response) => {
|
||||||
|
match response.text() {
|
||||||
|
Ok(text) => Box::new(StringBox::new(&text)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading response: {}", e))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error in HTTP PUT: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// HTTP DELETE リクエスト
|
||||||
|
pub fn delete(&self, url: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let url_str = url.to_string_box().value;
|
||||||
|
|
||||||
|
let client = self.client.lock().unwrap();
|
||||||
|
match client.delete(&url_str).send() {
|
||||||
|
Ok(response) => {
|
||||||
|
match response.text() {
|
||||||
|
Ok(text) => Box::new(StringBox::new(&text)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading response: {}", e))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error in HTTP DELETE: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ヘッダー付きHTTPリクエスト
|
||||||
|
pub fn request(&self, method: Box<dyn NyashBox>, url: Box<dyn NyashBox>, options: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let method_str = method.to_string_box().value.to_uppercase();
|
||||||
|
let url_str = url.to_string_box().value;
|
||||||
|
|
||||||
|
// optionsはMapBoxと仮定
|
||||||
|
if let Some(map_box) = options.as_any().downcast_ref::<MapBox>() {
|
||||||
|
let client = self.client.lock().unwrap();
|
||||||
|
let mut request = match method_str.as_str() {
|
||||||
|
"GET" => client.get(&url_str),
|
||||||
|
"POST" => client.post(&url_str),
|
||||||
|
"PUT" => client.put(&url_str),
|
||||||
|
"DELETE" => client.delete(&url_str),
|
||||||
|
_ => return Box::new(StringBox::new(&format!("Unsupported HTTP method: {}", method_str))),
|
||||||
|
};
|
||||||
|
|
||||||
|
// ヘッダー設定
|
||||||
|
if let Some(headers_box) = map_box.get(Box::new(StringBox::new("headers"))).as_any().downcast_ref::<MapBox>() {
|
||||||
|
let headers_map = headers_box.map.lock().unwrap();
|
||||||
|
for (key, value) in headers_map.iter() {
|
||||||
|
request = request.header(key, value.to_string_box().value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ボディ設定
|
||||||
|
if let Some(body_box) = map_box.get(Box::new(StringBox::new("body"))).as_any().downcast_ref::<StringBox>() {
|
||||||
|
request = request.body(body_box.value.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
match request.send() {
|
||||||
|
Ok(response) => {
|
||||||
|
match response.text() {
|
||||||
|
Ok(text) => Box::new(StringBox::new(&text)),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading response: {}", e))),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error in HTTP request: {}", e))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box::new(StringBox::new("Error: options must be a MapBox"))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyashBox for HttpClientBox {
|
impl NyashBox for HttpClientBox {
|
||||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||||
// Create a new client instance since Client doesn't implement Clone in a straightforward way
|
Box::new(self.clone())
|
||||||
Box::new(HttpClientBox::new())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_box(&self) -> StringBox {
|
fn to_string_box(&self) -> StringBox {
|
||||||
|
|||||||
@ -2,13 +2,16 @@
|
|||||||
// Nyashの箱システムによるJSON解析・生成を提供します。
|
// Nyashの箱システムによるJSON解析・生成を提供します。
|
||||||
// 参考: 既存Boxの設計思想
|
// 参考: 既存Boxの設計思想
|
||||||
|
|
||||||
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox};
|
||||||
|
use crate::boxes::array::ArrayBox;
|
||||||
|
use crate::boxes::map_box::MapBox;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use serde_json::{Value, Error};
|
use serde_json::{Value, Error};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct JSONBox {
|
pub struct JSONBox {
|
||||||
pub value: Value,
|
value: Arc<Mutex<Value>>,
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,7 +23,10 @@ impl JSONBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
let value = serde_json::from_str(s)?;
|
let value = serde_json::from_str(s)?;
|
||||||
Ok(JSONBox { value, id })
|
Ok(JSONBox {
|
||||||
|
value: Arc::new(Mutex::new(value)),
|
||||||
|
id
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(value: Value) -> Self {
|
pub fn new(value: Value) -> Self {
|
||||||
@ -29,11 +35,96 @@ impl JSONBox {
|
|||||||
COUNTER += 1;
|
COUNTER += 1;
|
||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
JSONBox { value, id }
|
JSONBox {
|
||||||
|
value: Arc::new(Mutex::new(value)),
|
||||||
|
id
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_string(&self) -> String {
|
pub fn to_string(&self) -> String {
|
||||||
self.value.to_string()
|
let value = self.value.lock().unwrap();
|
||||||
|
value.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// JSONパース
|
||||||
|
pub fn parse(data: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let json_str = data.to_string_box().value;
|
||||||
|
match JSONBox::from_str(&json_str) {
|
||||||
|
Ok(json_box) => Box::new(json_box),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error parsing JSON: {}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// JSON文字列化
|
||||||
|
pub fn stringify(&self) -> Box<dyn NyashBox> {
|
||||||
|
Box::new(StringBox::new(&self.to_string()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 値取得
|
||||||
|
pub fn get(&self, key: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let key_str = key.to_string_box().value;
|
||||||
|
let value = self.value.lock().unwrap();
|
||||||
|
|
||||||
|
if let Some(obj) = value.as_object() {
|
||||||
|
if let Some(val) = obj.get(&key_str) {
|
||||||
|
json_value_to_nyash_box(val)
|
||||||
|
} else {
|
||||||
|
Box::new(crate::boxes::null_box::NullBox::new())
|
||||||
|
}
|
||||||
|
} else if let Some(arr) = value.as_array() {
|
||||||
|
if let Ok(index) = key_str.parse::<usize>() {
|
||||||
|
if let Some(val) = arr.get(index) {
|
||||||
|
json_value_to_nyash_box(val)
|
||||||
|
} else {
|
||||||
|
Box::new(crate::boxes::null_box::NullBox::new())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box::new(crate::boxes::null_box::NullBox::new())
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box::new(crate::boxes::null_box::NullBox::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 値設定
|
||||||
|
pub fn set(&self, key: Box<dyn NyashBox>, new_value: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let key_str = key.to_string_box().value;
|
||||||
|
let mut value = self.value.lock().unwrap();
|
||||||
|
|
||||||
|
let json_value = nyash_box_to_json_value(new_value);
|
||||||
|
|
||||||
|
if let Some(obj) = value.as_object_mut() {
|
||||||
|
obj.insert(key_str, json_value);
|
||||||
|
Box::new(StringBox::new("ok"))
|
||||||
|
} else {
|
||||||
|
Box::new(StringBox::new("Error: JSONBox is not an object"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// キー存在チェック
|
||||||
|
pub fn has(&self, key: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let key_str = key.to_string_box().value;
|
||||||
|
let value = self.value.lock().unwrap();
|
||||||
|
|
||||||
|
if let Some(obj) = value.as_object() {
|
||||||
|
Box::new(BoolBox::new(obj.contains_key(&key_str)))
|
||||||
|
} else {
|
||||||
|
Box::new(BoolBox::new(false))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// すべてのキーを取得
|
||||||
|
pub fn keys(&self) -> Box<dyn NyashBox> {
|
||||||
|
let value = self.value.lock().unwrap();
|
||||||
|
let array = ArrayBox::new();
|
||||||
|
|
||||||
|
if let Some(obj) = value.as_object() {
|
||||||
|
for key in obj.keys() {
|
||||||
|
array.push(Box::new(StringBox::new(key)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::new(array)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,7 +134,8 @@ impl NyashBox for JSONBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_box(&self) -> StringBox {
|
fn to_string_box(&self) -> StringBox {
|
||||||
StringBox::new(self.value.to_string())
|
let value = self.value.lock().unwrap();
|
||||||
|
StringBox::new(value.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
@ -60,9 +152,81 @@ impl NyashBox for JSONBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_json) = other.as_any().downcast_ref::<JSONBox>() {
|
if let Some(other_json) = other.as_any().downcast_ref::<JSONBox>() {
|
||||||
BoolBox::new(self.value == other_json.value)
|
let self_value = self.value.lock().unwrap();
|
||||||
|
let other_value = other_json.value.lock().unwrap();
|
||||||
|
BoolBox::new(*self_value == *other_value)
|
||||||
} else {
|
} else {
|
||||||
BoolBox::new(false)
|
BoolBox::new(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// JSON Value を NyashBox に変換
|
||||||
|
fn json_value_to_nyash_box(value: &Value) -> Box<dyn NyashBox> {
|
||||||
|
match value {
|
||||||
|
Value::Null => Box::new(crate::boxes::null_box::NullBox::new()),
|
||||||
|
Value::Bool(b) => Box::new(BoolBox::new(*b)),
|
||||||
|
Value::Number(n) => {
|
||||||
|
if let Some(i) = n.as_i64() {
|
||||||
|
Box::new(IntegerBox::new(i))
|
||||||
|
} else if let Some(f) = n.as_f64() {
|
||||||
|
Box::new(crate::box_trait::FloatBox::new(f))
|
||||||
|
} else {
|
||||||
|
Box::new(StringBox::new(&n.to_string()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Value::String(s) => Box::new(StringBox::new(s)),
|
||||||
|
Value::Array(arr) => {
|
||||||
|
let array_box = ArrayBox::new();
|
||||||
|
for item in arr {
|
||||||
|
array_box.push(json_value_to_nyash_box(item));
|
||||||
|
}
|
||||||
|
Box::new(array_box)
|
||||||
|
}
|
||||||
|
Value::Object(obj) => {
|
||||||
|
let map_box = MapBox::new();
|
||||||
|
for (key, val) in obj {
|
||||||
|
map_box.set(
|
||||||
|
Box::new(StringBox::new(key)),
|
||||||
|
json_value_to_nyash_box(val)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Box::new(map_box)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// NyashBox を JSON Value に変換
|
||||||
|
fn nyash_box_to_json_value(value: Box<dyn NyashBox>) -> Value {
|
||||||
|
if value.as_any().downcast_ref::<crate::boxes::null_box::NullBox>().is_some() {
|
||||||
|
Value::Null
|
||||||
|
} else if let Some(bool_box) = value.as_any().downcast_ref::<BoolBox>() {
|
||||||
|
Value::Bool(bool_box.value)
|
||||||
|
} else if let Some(int_box) = value.as_any().downcast_ref::<IntegerBox>() {
|
||||||
|
Value::Number(serde_json::Number::from(int_box.value))
|
||||||
|
} else if let Some(float_box) = value.as_any().downcast_ref::<crate::box_trait::FloatBox>() {
|
||||||
|
if let Some(n) = serde_json::Number::from_f64(float_box.value) {
|
||||||
|
Value::Number(n)
|
||||||
|
} else {
|
||||||
|
Value::String(float_box.value.to_string())
|
||||||
|
}
|
||||||
|
} else if let Some(string_box) = value.as_any().downcast_ref::<StringBox>() {
|
||||||
|
Value::String(string_box.value.clone())
|
||||||
|
} else if let Some(array_box) = value.as_any().downcast_ref::<ArrayBox>() {
|
||||||
|
let items = array_box.items.lock().unwrap();
|
||||||
|
let arr: Vec<Value> = items.iter()
|
||||||
|
.map(|item| nyash_box_to_json_value(item.clone_box()))
|
||||||
|
.collect();
|
||||||
|
Value::Array(arr)
|
||||||
|
} else if let Some(map_box) = value.as_any().downcast_ref::<MapBox>() {
|
||||||
|
let map = map_box.map.lock().unwrap();
|
||||||
|
let mut obj = serde_json::Map::new();
|
||||||
|
for (key, val) in map.iter() {
|
||||||
|
obj.insert(key.clone(), nyash_box_to_json_value(val.clone_box()));
|
||||||
|
}
|
||||||
|
Value::Object(obj)
|
||||||
|
} else {
|
||||||
|
// その他の型は文字列に変換
|
||||||
|
Value::String(value.to_string_box().value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -4,14 +4,16 @@
|
|||||||
|
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
||||||
|
use crate::boxes::array::ArrayBox;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct RegexBox {
|
pub struct RegexBox {
|
||||||
pub regex: Regex,
|
regex: Arc<Regex>,
|
||||||
|
pattern: Arc<String>,
|
||||||
id: u64,
|
id: u64,
|
||||||
pattern: String,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RegexBox {
|
impl RegexBox {
|
||||||
@ -23,9 +25,9 @@ impl RegexBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
Ok(RegexBox {
|
Ok(RegexBox {
|
||||||
regex,
|
regex: Arc::new(regex),
|
||||||
|
pattern: Arc::new(pattern.to_string()),
|
||||||
id,
|
id,
|
||||||
pattern: pattern.to_string(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pub fn is_match(&self, text: &str) -> bool {
|
pub fn is_match(&self, text: &str) -> bool {
|
||||||
@ -34,6 +36,54 @@ impl RegexBox {
|
|||||||
pub fn pattern(&self) -> &str {
|
pub fn pattern(&self) -> &str {
|
||||||
&self.pattern
|
&self.pattern
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// パターンマッチテスト
|
||||||
|
pub fn test(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let text_str = text.to_string_box().value;
|
||||||
|
Box::new(BoolBox::new(self.is_match(&text_str)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// マッチ箇所を検索
|
||||||
|
pub fn find(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let text_str = text.to_string_box().value;
|
||||||
|
if let Some(mat) = self.regex.find(&text_str) {
|
||||||
|
Box::new(StringBox::new(mat.as_str()))
|
||||||
|
} else {
|
||||||
|
Box::new(crate::boxes::null_box::NullBox::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// すべてのマッチを検索
|
||||||
|
pub fn find_all(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let text_str = text.to_string_box().value;
|
||||||
|
let array = ArrayBox::new();
|
||||||
|
|
||||||
|
for mat in self.regex.find_iter(&text_str) {
|
||||||
|
array.push(Box::new(StringBox::new(mat.as_str())));
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::new(array)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 文字列置換
|
||||||
|
pub fn replace(&self, text: Box<dyn NyashBox>, replacement: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let text_str = text.to_string_box().value;
|
||||||
|
let replacement_str = replacement.to_string_box().value;
|
||||||
|
let result = self.regex.replace_all(&text_str, replacement_str.as_str());
|
||||||
|
Box::new(StringBox::new(&result))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 文字列分割
|
||||||
|
pub fn split(&self, text: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
let text_str = text.to_string_box().value;
|
||||||
|
let array = ArrayBox::new();
|
||||||
|
|
||||||
|
for part in self.regex.split(&text_str) {
|
||||||
|
array.push(Box::new(StringBox::new(part)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Box::new(array)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyashBox for RegexBox {
|
impl NyashBox for RegexBox {
|
||||||
@ -42,7 +92,7 @@ impl NyashBox for RegexBox {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_box(&self) -> StringBox {
|
fn to_string_box(&self) -> StringBox {
|
||||||
StringBox::new(format!("RegexBox({})", self.pattern))
|
StringBox::new(format!("RegexBox({})", **self.pattern))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
@ -59,7 +109,7 @@ impl NyashBox for RegexBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_regex) = other.as_any().downcast_ref::<RegexBox>() {
|
if let Some(other_regex) = other.as_any().downcast_ref::<RegexBox>() {
|
||||||
BoolBox::new(self.pattern == other_regex.pattern)
|
BoolBox::new(**self.pattern == **other_regex.pattern)
|
||||||
} else {
|
} else {
|
||||||
BoolBox::new(false)
|
BoolBox::new(false)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,23 +80,28 @@ impl NyashBox for NyashResultBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the original generic ResultBox for compatibility
|
// Export NyashResultBox as ResultBox for compatibility
|
||||||
pub enum ResultBox<T, E> {
|
pub type ResultBox = NyashResultBox;
|
||||||
Ok(T),
|
|
||||||
Err(E),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T, E> ResultBox<T, E> {
|
impl ResultBox {
|
||||||
pub fn is_ok(&self) -> bool {
|
/// is_ok()の実装
|
||||||
matches!(self, ResultBox::Ok(_))
|
pub fn is_ok(&self) -> Box<dyn NyashBox> {
|
||||||
|
Box::new(BoolBox::new(matches!(self, NyashResultBox::Ok(_))))
|
||||||
}
|
}
|
||||||
pub fn is_err(&self) -> bool {
|
|
||||||
matches!(self, ResultBox::Err(_))
|
/// getValue()の実装 - Ok値を取得
|
||||||
}
|
pub fn get_value(&self) -> Box<dyn NyashBox> {
|
||||||
pub fn unwrap(self) -> T {
|
|
||||||
match self {
|
match self {
|
||||||
ResultBox::Ok(val) => val,
|
NyashResultBox::Ok(val) => val.clone_box(),
|
||||||
ResultBox::Err(_) => panic!("called `unwrap()` on an `Err` value"),
|
NyashResultBox::Err(_) => Box::new(StringBox::new("Error: Result is Err")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// getError()の実装 - Err値を取得
|
||||||
|
pub fn get_error(&self) -> Box<dyn NyashBox> {
|
||||||
|
match self {
|
||||||
|
NyashResultBox::Ok(_) => Box::new(StringBox::new("Error: Result is Ok")),
|
||||||
|
NyashResultBox::Err(err) => err.clone_box(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,14 +2,16 @@
|
|||||||
// Nyashの箱システムによるストリーミング処理を提供します。
|
// Nyashの箱システムによるストリーミング処理を提供します。
|
||||||
// 参考: 既存Boxの設計思想
|
// 参考: 既存Boxの設計思想
|
||||||
|
|
||||||
use crate::box_trait::{NyashBox, StringBox, BoolBox};
|
use crate::box_trait::{NyashBox, StringBox, BoolBox, IntegerBox};
|
||||||
|
use crate::boxes::buffer::BufferBox;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
use std::io::{Read, Write, Result};
|
use std::io::{Read, Write, Result};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct NyashStreamBox {
|
pub struct NyashStreamBox {
|
||||||
pub buffer: Vec<u8>,
|
buffer: Arc<Mutex<Vec<u8>>>,
|
||||||
pub position: usize,
|
position: Arc<Mutex<usize>>,
|
||||||
id: u64,
|
id: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -21,8 +23,8 @@ impl NyashStreamBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
NyashStreamBox {
|
NyashStreamBox {
|
||||||
buffer: Vec::new(),
|
buffer: Arc::new(Mutex::new(Vec::new())),
|
||||||
position: 0,
|
position: Arc::new(Mutex::new(0)),
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -34,54 +36,109 @@ impl NyashStreamBox {
|
|||||||
COUNTER
|
COUNTER
|
||||||
};
|
};
|
||||||
NyashStreamBox {
|
NyashStreamBox {
|
||||||
buffer: data,
|
buffer: Arc::new(Mutex::new(data)),
|
||||||
position: 0,
|
position: Arc::new(Mutex::new(0)),
|
||||||
id,
|
id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
|
||||||
let available = self.buffer.len().saturating_sub(self.position);
|
let buffer = self.buffer.lock().unwrap();
|
||||||
|
let mut position = self.position.lock().unwrap();
|
||||||
|
|
||||||
|
let available = buffer.len().saturating_sub(*position);
|
||||||
let to_read = buf.len().min(available);
|
let to_read = buf.len().min(available);
|
||||||
|
|
||||||
if to_read == 0 {
|
if to_read == 0 {
|
||||||
return Ok(0);
|
return Ok(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
buf[..to_read].copy_from_slice(&self.buffer[self.position..self.position + to_read]);
|
buf[..to_read].copy_from_slice(&buffer[*position..*position + to_read]);
|
||||||
self.position += to_read;
|
*position += to_read;
|
||||||
Ok(to_read)
|
Ok(to_read)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&mut self, buf: &[u8]) -> Result<()> {
|
pub fn write(&self, buf: &[u8]) -> Result<()> {
|
||||||
self.buffer.extend_from_slice(buf);
|
let mut buffer = self.buffer.lock().unwrap();
|
||||||
|
buffer.extend_from_slice(buf);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
pub fn len(&self) -> usize {
|
||||||
self.buffer.len()
|
self.buffer.lock().unwrap().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn position(&self) -> usize {
|
pub fn position(&self) -> usize {
|
||||||
self.position
|
*self.position.lock().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&mut self) {
|
pub fn reset(&self) {
|
||||||
self.position = 0;
|
*self.position.lock().unwrap() = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ストリームに書き込み
|
||||||
|
pub fn stream_write(&self, data: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
// BufferBoxから変換
|
||||||
|
if let Some(buffer_box) = data.as_any().downcast_ref::<BufferBox>() {
|
||||||
|
let buffer_data = buffer_box.data.lock().unwrap();
|
||||||
|
match self.write(&buffer_data) {
|
||||||
|
Ok(()) => Box::new(StringBox::new("ok")),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error writing to stream: {}", e))),
|
||||||
|
}
|
||||||
|
} else if let Some(string_box) = data.as_any().downcast_ref::<StringBox>() {
|
||||||
|
match self.write(string_box.value.as_bytes()) {
|
||||||
|
Ok(()) => Box::new(StringBox::new("ok")),
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error writing to stream: {}", e))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box::new(StringBox::new("Error: write() requires BufferBox or StringBox"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ストリームから読み込み
|
||||||
|
pub fn stream_read(&self, count: Box<dyn NyashBox>) -> Box<dyn NyashBox> {
|
||||||
|
if let Some(count_int) = count.as_any().downcast_ref::<IntegerBox>() {
|
||||||
|
let count_val = count_int.value as usize;
|
||||||
|
let mut buf = vec![0u8; count_val];
|
||||||
|
|
||||||
|
match self.read(&mut buf) {
|
||||||
|
Ok(bytes_read) => {
|
||||||
|
buf.truncate(bytes_read);
|
||||||
|
Box::new(BufferBox::from_vec(buf))
|
||||||
|
},
|
||||||
|
Err(e) => Box::new(StringBox::new(&format!("Error reading from stream: {}", e))),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box::new(StringBox::new("Error: read() requires integer count"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 現在位置を取得
|
||||||
|
pub fn get_position(&self) -> Box<dyn NyashBox> {
|
||||||
|
Box::new(IntegerBox::new(self.position() as i64))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// バッファサイズを取得
|
||||||
|
pub fn get_length(&self) -> Box<dyn NyashBox> {
|
||||||
|
Box::new(IntegerBox::new(self.len() as i64))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ストリームをリセット
|
||||||
|
pub fn stream_reset(&self) -> Box<dyn NyashBox> {
|
||||||
|
self.reset();
|
||||||
|
Box::new(StringBox::new("ok"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NyashBox for NyashStreamBox {
|
impl NyashBox for NyashStreamBox {
|
||||||
fn clone_box(&self) -> Box<dyn NyashBox> {
|
fn clone_box(&self) -> Box<dyn NyashBox> {
|
||||||
Box::new(NyashStreamBox {
|
Box::new(self.clone())
|
||||||
buffer: self.buffer.clone(),
|
|
||||||
position: self.position,
|
|
||||||
id: self.id,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_box(&self) -> StringBox {
|
fn to_string_box(&self) -> StringBox {
|
||||||
StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", self.buffer.len(), self.position))
|
let buffer = self.buffer.lock().unwrap();
|
||||||
|
let position = self.position.lock().unwrap();
|
||||||
|
StringBox::new(format!("NyashStreamBox({} bytes, pos: {})", buffer.len(), *position))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_any(&self) -> &dyn Any {
|
fn as_any(&self) -> &dyn Any {
|
||||||
@ -98,27 +155,16 @@ impl NyashBox for NyashStreamBox {
|
|||||||
|
|
||||||
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
fn equals(&self, other: &dyn NyashBox) -> BoolBox {
|
||||||
if let Some(other_stream) = other.as_any().downcast_ref::<NyashStreamBox>() {
|
if let Some(other_stream) = other.as_any().downcast_ref::<NyashStreamBox>() {
|
||||||
BoolBox::new(self.buffer == other_stream.buffer && self.position == other_stream.position)
|
let self_buffer = self.buffer.lock().unwrap();
|
||||||
|
let self_position = self.position.lock().unwrap();
|
||||||
|
let other_buffer = other_stream.buffer.lock().unwrap();
|
||||||
|
let other_position = other_stream.position.lock().unwrap();
|
||||||
|
BoolBox::new(*self_buffer == *other_buffer && *self_position == *other_position)
|
||||||
} else {
|
} else {
|
||||||
BoolBox::new(false)
|
BoolBox::new(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the original generic StreamBox for compatibility
|
// Export NyashStreamBox as StreamBox for consistency
|
||||||
pub struct StreamBox<R: Read, W: Write> {
|
pub type StreamBox = NyashStreamBox;
|
||||||
pub reader: R,
|
|
||||||
pub writer: W,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Read, W: Write> StreamBox<R, W> {
|
|
||||||
pub fn new(reader: R, writer: W) -> Self {
|
|
||||||
StreamBox { reader, writer }
|
|
||||||
}
|
|
||||||
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
|
|
||||||
self.reader.read(buf)
|
|
||||||
}
|
|
||||||
pub fn write(&mut self, buf: &[u8]) -> Result<()> {
|
|
||||||
self.writer.write_all(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::ast::UnaryOperator;
|
use crate::ast::UnaryOperator;
|
||||||
|
use crate::boxes::{BufferBox, JSONBox, HttpClientBox, StreamBox, RegexBox};
|
||||||
// TODO: Fix NullBox import issue later
|
// TODO: Fix NullBox import issue later
|
||||||
// use crate::NullBox;
|
// use crate::NullBox;
|
||||||
|
|
||||||
@ -326,6 +327,11 @@ impl NyashInterpreter {
|
|||||||
return self.execute_array_method(array_box, method, arguments);
|
return self.execute_array_method(array_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BufferBox method calls
|
||||||
|
if let Some(buffer_box) = obj_value.as_any().downcast_ref::<BufferBox>() {
|
||||||
|
return self.execute_buffer_method(buffer_box, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
// FileBox method calls
|
// FileBox method calls
|
||||||
if let Some(file_box) = obj_value.as_any().downcast_ref::<FileBox>() {
|
if let Some(file_box) = obj_value.as_any().downcast_ref::<FileBox>() {
|
||||||
return self.execute_file_method(file_box, method, arguments);
|
return self.execute_file_method(file_box, method, arguments);
|
||||||
@ -346,6 +352,26 @@ impl NyashInterpreter {
|
|||||||
return self.execute_channel_method(channel_box, method, arguments);
|
return self.execute_channel_method(channel_box, method, arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// JSONBox method calls
|
||||||
|
if let Some(json_box) = obj_value.as_any().downcast_ref::<JSONBox>() {
|
||||||
|
return self.execute_json_method(json_box, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// HttpClientBox method calls
|
||||||
|
if let Some(http_box) = obj_value.as_any().downcast_ref::<HttpClientBox>() {
|
||||||
|
return self.execute_http_method(http_box, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// StreamBox method calls
|
||||||
|
if let Some(stream_box) = obj_value.as_any().downcast_ref::<StreamBox>() {
|
||||||
|
return self.execute_stream_method(stream_box, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegexBox method calls
|
||||||
|
if let Some(regex_box) = obj_value.as_any().downcast_ref::<RegexBox>() {
|
||||||
|
return self.execute_regex_method(regex_box, method, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
// MathBox method calls
|
// MathBox method calls
|
||||||
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
if let Some(math_box) = obj_value.as_any().downcast_ref::<MathBox>() {
|
||||||
return self.execute_math_method(math_box, method, arguments);
|
return self.execute_math_method(math_box, method, arguments);
|
||||||
|
|||||||
204
src/interpreter/methods/data_methods.rs
Normal file
204
src/interpreter/methods/data_methods.rs
Normal file
@ -0,0 +1,204 @@
|
|||||||
|
/*!
|
||||||
|
* Data Processing Box Methods Module
|
||||||
|
*
|
||||||
|
* Contains method implementations for data processing Box types:
|
||||||
|
* - BufferBox (execute_buffer_method) - Binary data operations
|
||||||
|
* - JSONBox (execute_json_method) - JSON parsing and manipulation
|
||||||
|
* - RegexBox (execute_regex_method) - Regular expression operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::super::*;
|
||||||
|
use crate::box_trait::{NyashBox, StringBox, IntegerBox};
|
||||||
|
use crate::boxes::{BufferBox, JSONBox, RegexBox};
|
||||||
|
|
||||||
|
impl NyashInterpreter {
|
||||||
|
/// BufferBoxのメソッド呼び出しを実行
|
||||||
|
pub(in crate::interpreter) fn execute_buffer_method(&mut self, buffer_box: &BufferBox, method: &str, arguments: &[ASTNode])
|
||||||
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
|
match method {
|
||||||
|
"write" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("write() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let data = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(buffer_box.write(data))
|
||||||
|
}
|
||||||
|
"readAll" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("readAll() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(buffer_box.readAll())
|
||||||
|
}
|
||||||
|
"read" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("read() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let count = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(buffer_box.read(count))
|
||||||
|
}
|
||||||
|
"clear" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("clear() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(buffer_box.clear())
|
||||||
|
}
|
||||||
|
"length" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("length() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(buffer_box.length())
|
||||||
|
}
|
||||||
|
"append" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("append() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let other = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(buffer_box.append(other))
|
||||||
|
}
|
||||||
|
"slice" => {
|
||||||
|
if arguments.len() != 2 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("slice() expects 2 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let start = self.execute_expression(&arguments[0])?;
|
||||||
|
let end = self.execute_expression(&arguments[1])?;
|
||||||
|
Ok(buffer_box.slice(start, end))
|
||||||
|
}
|
||||||
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("Unknown method '{}' for BufferBox", method),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// JSONBoxのメソッド呼び出しを実行
|
||||||
|
pub(in crate::interpreter) fn execute_json_method(&mut self, json_box: &JSONBox, method: &str, arguments: &[ASTNode])
|
||||||
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
|
match method {
|
||||||
|
"parse" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("parse() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let data = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(JSONBox::parse(data))
|
||||||
|
}
|
||||||
|
"stringify" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("stringify() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(json_box.stringify())
|
||||||
|
}
|
||||||
|
"get" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("get() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let key = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(json_box.get(key))
|
||||||
|
}
|
||||||
|
"set" => {
|
||||||
|
if arguments.len() != 2 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("set() expects 2 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let key = self.execute_expression(&arguments[0])?;
|
||||||
|
let value = self.execute_expression(&arguments[1])?;
|
||||||
|
Ok(json_box.set(key, value))
|
||||||
|
}
|
||||||
|
"has" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("has() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let key = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(json_box.has(key))
|
||||||
|
}
|
||||||
|
"keys" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("keys() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(json_box.keys())
|
||||||
|
}
|
||||||
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("Unknown method '{}' for JSONBox", method),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RegexBoxのメソッド呼び出しを実行
|
||||||
|
pub(in crate::interpreter) fn execute_regex_method(&mut self, regex_box: &RegexBox, method: &str, arguments: &[ASTNode])
|
||||||
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
|
match method {
|
||||||
|
"test" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("test() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let text = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(regex_box.test(text))
|
||||||
|
}
|
||||||
|
"find" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("find() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let text = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(regex_box.find(text))
|
||||||
|
}
|
||||||
|
"findAll" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("findAll() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let text = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(regex_box.find_all(text))
|
||||||
|
}
|
||||||
|
"replace" => {
|
||||||
|
if arguments.len() != 2 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("replace() expects 2 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let text = self.execute_expression(&arguments[0])?;
|
||||||
|
let replacement = self.execute_expression(&arguments[1])?;
|
||||||
|
Ok(regex_box.replace(text, replacement))
|
||||||
|
}
|
||||||
|
"split" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("split() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let text = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(regex_box.split(text))
|
||||||
|
}
|
||||||
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("Unknown method '{}' for RegexBox", method),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -19,8 +19,12 @@
|
|||||||
pub mod basic_methods; // StringBox, IntegerBox, BoolBox, FloatBox
|
pub mod basic_methods; // StringBox, IntegerBox, BoolBox, FloatBox
|
||||||
pub mod collection_methods; // ArrayBox, MapBox
|
pub mod collection_methods; // ArrayBox, MapBox
|
||||||
pub mod io_methods; // FileBox, ResultBox
|
pub mod io_methods; // FileBox, ResultBox
|
||||||
|
pub mod data_methods; // BufferBox, JSONBox, RegexBox
|
||||||
|
pub mod network_methods; // HttpClientBox, StreamBox
|
||||||
|
|
||||||
// Re-export methods for easy access
|
// Re-export methods for easy access
|
||||||
pub use basic_methods::*;
|
pub use basic_methods::*;
|
||||||
pub use collection_methods::*;
|
pub use collection_methods::*;
|
||||||
pub use io_methods::*;
|
pub use io_methods::*;
|
||||||
|
pub use data_methods::*;
|
||||||
|
pub use network_methods::*;
|
||||||
124
src/interpreter/methods/network_methods.rs
Normal file
124
src/interpreter/methods/network_methods.rs
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
/*!
|
||||||
|
* Network and Communication Box Methods Module
|
||||||
|
*
|
||||||
|
* Contains method implementations for network-related Box types:
|
||||||
|
* - HttpClientBox (execute_http_method) - HTTP client operations
|
||||||
|
* - StreamBox (execute_stream_method) - Stream processing operations
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::super::*;
|
||||||
|
use crate::box_trait::{NyashBox, StringBox};
|
||||||
|
use crate::boxes::{HttpClientBox, StreamBox};
|
||||||
|
|
||||||
|
impl NyashInterpreter {
|
||||||
|
/// HttpClientBoxのメソッド呼び出しを実行
|
||||||
|
pub(in crate::interpreter) fn execute_http_method(&mut self, http_box: &HttpClientBox, method: &str, arguments: &[ASTNode])
|
||||||
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
|
match method {
|
||||||
|
"get" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("get() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let url = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(http_box.http_get(url))
|
||||||
|
}
|
||||||
|
"post" => {
|
||||||
|
if arguments.len() != 2 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("post() expects 2 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let url = self.execute_expression(&arguments[0])?;
|
||||||
|
let body = self.execute_expression(&arguments[1])?;
|
||||||
|
Ok(http_box.post(url, body))
|
||||||
|
}
|
||||||
|
"put" => {
|
||||||
|
if arguments.len() != 2 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("put() expects 2 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let url = self.execute_expression(&arguments[0])?;
|
||||||
|
let body = self.execute_expression(&arguments[1])?;
|
||||||
|
Ok(http_box.put(url, body))
|
||||||
|
}
|
||||||
|
"delete" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("delete() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let url = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(http_box.delete(url))
|
||||||
|
}
|
||||||
|
"request" => {
|
||||||
|
if arguments.len() != 3 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("request() expects 3 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let method_arg = self.execute_expression(&arguments[0])?;
|
||||||
|
let url = self.execute_expression(&arguments[1])?;
|
||||||
|
let options = self.execute_expression(&arguments[2])?;
|
||||||
|
Ok(http_box.request(method_arg, url, options))
|
||||||
|
}
|
||||||
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("Unknown method '{}' for HttpClientBox", method),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// StreamBoxのメソッド呼び出しを実行
|
||||||
|
pub(in crate::interpreter) fn execute_stream_method(&mut self, stream_box: &StreamBox, method: &str, arguments: &[ASTNode])
|
||||||
|
-> Result<Box<dyn NyashBox>, RuntimeError> {
|
||||||
|
match method {
|
||||||
|
"write" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("write() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let data = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(stream_box.stream_write(data))
|
||||||
|
}
|
||||||
|
"read" => {
|
||||||
|
if arguments.len() != 1 {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("read() expects 1 argument, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
let count = self.execute_expression(&arguments[0])?;
|
||||||
|
Ok(stream_box.stream_read(count))
|
||||||
|
}
|
||||||
|
"position" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("position() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(stream_box.get_position())
|
||||||
|
}
|
||||||
|
"length" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("length() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(stream_box.get_length())
|
||||||
|
}
|
||||||
|
"reset" => {
|
||||||
|
if !arguments.is_empty() {
|
||||||
|
return Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("reset() expects 0 arguments, got {}", arguments.len()),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Ok(stream_box.stream_reset())
|
||||||
|
}
|
||||||
|
_ => Err(RuntimeError::InvalidOperation {
|
||||||
|
message: format!("Unknown method '{}' for StreamBox", method),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user