pub trait Platform {
fn file_read(&self, path: &str) -> Result<Vec<u8>, String>;
fn file_write(&self, path: &str, data: &[u8]) -> Result<(), String>;
fn file_exists(&self, path: &str) -> bool;
fn file_list(&self, path: &str) -> Result<Vec<String>, String>;
fn file_delete(&self, path: &str) -> Result<(), String>;
fn http_get(&self, url: &str) -> Result<(Vec<u8>, u16), String>;
fn http_post(&self, url: &str, body: &[u8]) -> Result<(Vec<u8>, u16), String>;
fn shell_exec(&self, cmd: &str) -> Result<(Vec<u8>, i32), String>;
fn env_var(&self, name: &str) -> Option<String>;
fn timestamp(&self) -> i64;
fn sleep_ms(&self, ms: u64);
fn random_bytes(&self, buf: &mut [u8]);
fn save_state(&self, key: &str, data: &[u8]) -> Result<(), String>;
fn load_state(&self, key: &str) -> Option<Vec<u8>>;
fn name(&self) -> &str;
}
#[cfg(not(target_arch = "wasm32"))]
pub struct NativePlatform;
#[cfg(not(target_arch = "wasm32"))]
impl NativePlatform {
pub fn new() -> Self {
NativePlatform
}
}
#[cfg(not(target_arch = "wasm32"))]
impl Platform for NativePlatform {
fn file_read(&self, path: &str) -> Result<Vec<u8>, String> {
crate::features::io_words::file_read(path)
}
fn file_write(&self, path: &str, data: &[u8]) -> Result<(), String> {
crate::features::io_words::file_write(path, data)
}
fn file_exists(&self, path: &str) -> bool {
crate::features::io_words::file_exists(path)
}
fn file_list(&self, path: &str) -> Result<Vec<String>, String> {
crate::features::io_words::file_list(path)
}
fn file_delete(&self, path: &str) -> Result<(), String> {
crate::features::io_words::file_delete(path)
}
fn http_get(&self, url: &str) -> Result<(Vec<u8>, u16), String> {
crate::features::io_words::http_get(url)
}
fn http_post(&self, url: &str, body: &[u8]) -> Result<(Vec<u8>, u16), String> {
crate::features::io_words::http_post(url, body)
}
fn shell_exec(&self, cmd: &str) -> Result<(Vec<u8>, i32), String> {
crate::features::io_words::shell_exec(cmd)
}
fn env_var(&self, name: &str) -> Option<String> {
crate::features::io_words::env_var(name)
}
fn timestamp(&self) -> i64 {
crate::features::io_words::timestamp()
}
fn sleep_ms(&self, ms: u64) {
std::thread::sleep(std::time::Duration::from_millis(ms));
}
fn random_bytes(&self, buf: &mut [u8]) {
if let Ok(mut f) = std::fs::File::open("/dev/urandom") {
use std::io::Read;
let _ = f.read_exact(buf);
}
}
fn save_state(&self, key: &str, data: &[u8]) -> Result<(), String> {
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
let dir = format!("{}/.unit", home);
std::fs::create_dir_all(&dir).map_err(|e| e.to_string())?;
std::fs::write(format!("{}/{}", dir, key), data).map_err(|e| e.to_string())
}
fn load_state(&self, key: &str) -> Option<Vec<u8>> {
let home = std::env::var("HOME").unwrap_or_else(|_| ".".to_string());
std::fs::read(format!("{}/.unit/{}", home, key)).ok()
}
fn name(&self) -> &str {
"native"
}
}
#[cfg(target_arch = "wasm32")]
pub struct WasmPlatform;
#[cfg(target_arch = "wasm32")]
impl WasmPlatform {
pub fn new() -> Self {
WasmPlatform
}
}
#[cfg(target_arch = "wasm32")]
impl Platform for WasmPlatform {
fn file_read(&self, _: &str) -> Result<Vec<u8>, String> {
Err("no filesystem on WASM".into())
}
fn file_write(&self, _: &str, _: &[u8]) -> Result<(), String> {
Err("no filesystem on WASM".into())
}
fn file_exists(&self, _: &str) -> bool {
false
}
fn file_list(&self, _: &str) -> Result<Vec<String>, String> {
Err("no filesystem on WASM".into())
}
fn file_delete(&self, _: &str) -> Result<(), String> {
Err("no filesystem on WASM".into())
}
fn http_get(&self, _: &str) -> Result<(Vec<u8>, u16), String> {
Err("use fetch() from JS".into())
}
fn http_post(&self, _: &str, _: &[u8]) -> Result<(Vec<u8>, u16), String> {
Err("use fetch() from JS".into())
}
fn shell_exec(&self, _: &str) -> Result<(Vec<u8>, i32), String> {
Err("no shell on WASM".into())
}
fn env_var(&self, _: &str) -> Option<String> {
None
}
fn timestamp(&self) -> i64 {
0
} fn sleep_ms(&self, _: u64) {} fn random_bytes(&self, buf: &mut [u8]) {
for (i, b) in buf.iter_mut().enumerate() {
*b = (i as u8).wrapping_mul(137).wrapping_add(42);
}
}
fn save_state(&self, _: &str, _: &[u8]) -> Result<(), String> {
Err("use localStorage from JS".into())
}
fn load_state(&self, _: &str) -> Option<Vec<u8>> {
None
}
fn name(&self) -> &str {
"wasm"
}
}