use wasm_bindgen::prelude::*;
use crate::memconv::{self, MemImage};
use crate::memedit;
#[wasm_bindgen(start)]
pub fn start() {
console_error_panic_hook::set_once();
}
fn to_js(e: impl std::fmt::Display) -> JsValue {
JsValue::from_str(&e.to_string())
}
#[wasm_bindgen]
pub fn probe(bytes: &[u8]) -> Result<String, JsValue> {
let report = memconv::probe(bytes).map_err(to_js)?;
serde_json::to_string(&report).map_err(to_js)
}
#[wasm_bindgen]
pub fn supported_targets() -> Result<String, JsValue> {
serde_json::to_string(&memconv::supported_targets()).map_err(to_js)
}
#[wasm_bindgen]
pub struct Image {
inner: MemImage,
}
#[wasm_bindgen]
impl Image {
#[wasm_bindgen(constructor)]
pub fn new(bytes: Vec<u8>) -> Result<Image, JsValue> {
Ok(Image {
inner: MemImage::open(bytes).map_err(to_js)?,
})
}
#[wasm_bindgen(js_name = openPartition)]
pub fn open_partition(bytes: Vec<u8>, part: usize) -> Result<Image, JsValue> {
Ok(Image {
inner: MemImage::open_partition(bytes, Some(part)).map_err(to_js)?,
})
}
#[wasm_bindgen(getter)]
pub fn kind(&self) -> String {
self.inner.kind().to_string()
}
pub fn list(&mut self, path: &str) -> Result<String, JsValue> {
let entries = self.inner.list(path).map_err(to_js)?;
serde_json::to_string(&entries).map_err(to_js)
}
#[wasm_bindgen(js_name = readFile)]
pub fn read_file(&mut self, path: &str) -> Result<Vec<u8>, JsValue> {
self.inner.read_file(path).map_err(to_js)
}
#[wasm_bindgen(js_name = readSymlink)]
pub fn read_symlink(&mut self, path: &str) -> Result<String, JsValue> {
self.inner.read_symlink(path).map_err(to_js)
}
pub fn convert(&mut self, target: &str) -> Result<Vec<u8>, JsValue> {
self.inner.convert(target).map_err(to_js)
}
}
#[wasm_bindgen]
pub fn creatable_filesystems() -> Result<String, JsValue> {
serde_json::to_string(&memedit::creatable_filesystems()).map_err(to_js)
}
#[wasm_bindgen]
pub struct Workspace {
inner: memedit::Workspace,
}
#[wasm_bindgen]
impl Workspace {
#[wasm_bindgen(js_name = newFilesystem)]
pub fn new_filesystem(fs_type: &str, size: f64, options: &str) -> Result<Workspace, JsValue> {
Ok(Workspace {
inner: memedit::Workspace::new_filesystem(fs_type, size_arg(size)?, options)
.map_err(to_js)?,
})
}
#[wasm_bindgen(js_name = newDisk)]
pub fn new_disk(size: f64, table: &str) -> Result<Workspace, JsValue> {
Ok(Workspace {
inner: memedit::Workspace::new_disk(size_arg(size)?, table).map_err(to_js)?,
})
}
#[wasm_bindgen(js_name = fromBytes)]
pub fn from_bytes(bytes: Vec<u8>) -> Result<Workspace, JsValue> {
Ok(Workspace {
inner: memedit::Workspace::from_bytes(bytes).map_err(to_js)?,
})
}
#[wasm_bindgen(js_name = addPartition)]
pub fn add_partition(
&mut self,
size: f64,
kind: &str,
name: &str,
fs_type: &str,
fs_options: &str,
) -> Result<usize, JsValue> {
let size = if size <= 0.0 {
None
} else {
Some(size_arg(size)?)
};
let name = if name.is_empty() { None } else { Some(name) };
self.inner
.add_partition(size, kind, name, fs_type, fs_options)
.map_err(to_js)
}
#[wasm_bindgen(js_name = formatPartition)]
pub fn format_partition(
&mut self,
index: usize,
fs_type: &str,
fs_options: &str,
) -> Result<(), JsValue> {
self.inner
.format_partition(index, fs_type, fs_options)
.map_err(to_js)
}
#[wasm_bindgen(js_name = openPartition)]
pub fn open_partition(&mut self, index: usize) -> Result<(), JsValue> {
self.inner.open_partition(index).map_err(to_js)
}
pub fn info(&mut self) -> Result<String, JsValue> {
let info = self.inner.info().map_err(to_js)?;
serde_json::to_string(&info).map_err(to_js)
}
pub fn list(&mut self, path: &str) -> Result<String, JsValue> {
let entries = self.inner.list(path).map_err(to_js)?;
serde_json::to_string(&entries).map_err(to_js)
}
#[wasm_bindgen(js_name = readFile)]
pub fn read_file(&mut self, path: &str) -> Result<Vec<u8>, JsValue> {
self.inner.read_file(path).map_err(to_js)
}
#[wasm_bindgen(js_name = addFile)]
pub fn add_file(&mut self, path: &str, bytes: Vec<u8>) -> Result<(), JsValue> {
self.inner.add_file(path, bytes).map_err(to_js)
}
pub fn mkdir(&mut self, path: &str) -> Result<(), JsValue> {
self.inner.mkdir(path).map_err(to_js)
}
pub fn remove(&mut self, path: &str) -> Result<(), JsValue> {
self.inner.remove(path).map_err(to_js)
}
pub fn export(&mut self) -> Result<Vec<u8>, JsValue> {
self.inner.export().map_err(to_js)
}
}
fn size_arg(size: f64) -> Result<u64, JsValue> {
if !size.is_finite() || size < 0.0 || size.fract() != 0.0 {
return Err(JsValue::from_str(&format!(
"size must be a non-negative whole number of bytes (got {size})"
)));
}
if size > 9_007_199_254_740_991.0 {
return Err(JsValue::from_str(
"size exceeds the largest integer a JavaScript number represents exactly",
));
}
Ok(size as u64)
}