rudus/src/io.rs

106 lines
3.0 KiB
Rust
Raw Normal View History

2025-06-30 16:49:07 +00:00
use wasm_bindgen::prelude::*;
use serde::{Serialize, Deserialize};
use crate::value::Value;
use imbl::Vector;
use std::rc::Rc;
2025-07-04 05:23:16 +00:00
const OK: Value = Value::Keyword("ok");
const ERR: Value = Value::Keyword("err");
2025-06-30 16:49:07 +00:00
#[wasm_bindgen(module = "/pkg/worker.js")]
extern "C" {
2025-07-01 16:54:11 +00:00
#[wasm_bindgen(catch)]
async fn io (output: String) -> Result<JsValue, JsValue>;
2025-06-30 16:49:07 +00:00
}
2025-06-30 22:59:59 +00:00
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: String);
}
2025-07-04 00:22:11 +00:00
type Url = Value; // expect a string
type Commands = Value; // expect a list of command tuples
2025-06-30 16:49:07 +00:00
2025-07-04 00:22:11 +00:00
#[derive(Debug, Clone, PartialEq, Serialize)]
#[serde(tag = "verb", content = "data")]
2025-06-30 16:49:07 +00:00
pub enum MsgOut {
2025-07-03 03:47:02 +00:00
Console(Value),
2025-06-30 16:49:07 +00:00
Commands(Commands),
2025-07-01 22:52:03 +00:00
Fetch(Url),
2025-07-04 00:22:11 +00:00
Complete(Value),
Error(String),
Ready
2025-06-30 16:49:07 +00:00
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "verb", content = "data")]
pub enum MsgIn {
Input(String),
2025-07-01 22:52:03 +00:00
Fetch(String, f64, String),
2025-06-30 16:49:07 +00:00
Kill,
Keyboard(Vec<String>),
}
2025-06-30 22:59:59 +00:00
impl std::fmt::Display for MsgIn {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
2025-07-01 20:59:42 +00:00
MsgIn::Input(str) => write!(f, "Input: {str}"),
MsgIn::Kill => write!(f, "Kill"),
2025-07-01 22:52:03 +00:00
MsgIn::Fetch(url, code, text) => write!(f, "Fetch: {url} :: {code} ::\n{text}"),
2025-06-30 22:59:59 +00:00
_ => todo!()
}
}
}
2025-06-30 16:49:07 +00:00
impl MsgIn {
2025-07-04 05:23:16 +00:00
pub fn into_value(self) -> Value {
2025-06-30 16:49:07 +00:00
match self {
MsgIn::Input(str) => Value::string(str),
2025-07-01 22:52:03 +00:00
MsgIn::Fetch(url, status_f64, string) => {
2025-06-30 16:49:07 +00:00
let url = Value::string(url);
2025-07-01 22:52:03 +00:00
let status = Value::Number(status_f64);
let text = Value::string(string);
let result_tuple = if status_f64 == 200.0 {
2025-07-04 05:23:16 +00:00
Value::tuple(vec![OK, text])
2025-07-01 22:52:03 +00:00
} else {
2025-07-04 05:23:16 +00:00
Value::tuple(vec![ERR, status])
2025-07-01 22:52:03 +00:00
};
2025-06-30 16:49:07 +00:00
Value::tuple(vec![url, result_tuple])
}
MsgIn::Kill => Value::Nothing,
MsgIn::Keyboard(downkeys) => {
let mut vector = Vector::new();
for key in downkeys {
vector.push_back(Value::String(Rc::new(key)));
}
Value::List(Box::new(vector))
}
}
}
}
2025-07-03 03:47:02 +00:00
pub async fn send_err_to_ludus_console(msg: String) {
log(msg.clone());
2025-07-04 00:22:11 +00:00
do_io(vec![MsgOut::Ready, MsgOut::Error(msg)]).await;
2025-07-03 03:47:02 +00:00
}
2025-06-30 16:49:07 +00:00
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
2025-07-04 00:22:11 +00:00
let json = serde_json::to_string(&msgs).unwrap();
let inbox = io (json).await;
2025-07-01 16:54:11 +00:00
let inbox = match inbox {
Ok(msgs) => msgs,
Err(_) => return vec![]
};
2025-06-30 16:49:07 +00:00
let inbox = inbox.as_string().expect("response should be a string");
let inbox: Vec<MsgIn> = serde_json::from_str(inbox.as_str()).expect("response from js should be valid");
2025-06-30 22:59:59 +00:00
if !inbox.is_empty() {
log("ludus received messages".to_string());
2025-06-30 22:59:59 +00:00
for msg in inbox.iter() {
log(format!("{}", msg));
}
}
2025-06-30 16:49:07 +00:00
inbox
}