use std::ops::{Deref, DerefMut};
use crate::{lang::SError, Library, SDoc, SNum, SVal};
#[derive(Default, Debug)]
pub struct BlobLibrary;
impl BlobLibrary {
pub fn operate(&self, pid: &str, doc: &mut SDoc, name: &str, blob: &mut Vec<u8>, parameters: &mut Vec<SVal>) -> Result<SVal, SError> {
match name {
"len" |
"size" => {
Ok(SVal::Number(SNum::I64(blob.len() as i64)))
},
"at" => {
if parameters.len() < 1 {
return Err(SError::blob(pid, &doc, "at", "index argument not found"));
}
match ¶meters[0] {
SVal::Number(num) => {
let index = num.int() as usize;
if index < blob.len() {
return Ok(SVal::Number(SNum::I64(blob[index] as i64)));
}
},
SVal::Boxed(val) => {
let val = val.lock().unwrap();
let val = val.deref();
match val {
SVal::Number(num) => {
let index = num.int() as usize;
if index < blob.len() {
return Ok(SVal::Number(SNum::I64(blob[index] as i64)));
}
},
_ => {}
}
},
_ => {}
}
Err(SError::blob(pid, &doc, "at", "index argument not found"))
},
_ => {
Err(SError::blob(pid, &doc, "NotFound", &format!("{} is not a function in the Blob Library", name)))
}
}
}
}
impl Library for BlobLibrary {
fn scope(&self) -> String {
"Blob".to_string()
}
fn call(&self, pid: &str, doc: &mut SDoc, name: &str, parameters: &mut Vec<SVal>) -> Result<SVal, SError> {
if parameters.len() > 0 {
match name {
"toString" => {
return Ok(SVal::String(parameters[0].print(doc)));
},
"or" => {
for param in parameters.drain(..) {
if !param.is_empty() {
return Ok(param);
}
}
return Ok(SVal::Null);
},
_ => {}
}
let mut params;
if parameters.len() > 1 {
params = parameters.drain(1..).collect();
} else {
params = Vec::new();
}
match &mut parameters[0] {
SVal::Blob(val) => {
return self.operate(pid, doc, name, val, &mut params);
},
SVal::Boxed(val) => {
let mut val = val.lock().unwrap();
let val = val.deref_mut();
match val {
SVal::Blob(val) => {
return self.operate(pid, doc, name, val, &mut params);
},
_ => {
return Err(SError::blob(pid, &doc, "InvalidArgument", "blob argument not found"));
}
}
},
_ => {
return Err(SError::blob(pid, &doc, "InvalidArgument", "blob argument not found"));
}
}
} else {
return Err(SError::blob(pid, &doc, "InvalidArgument", "blob argument not found"));
}
}
}