also add the new io file
This commit is contained in:
parent
bc49ece0cf
commit
173fdb913c
106
src/io.rs
Normal file
106
src/io.rs
Normal file
|
@ -0,0 +1,106 @@
|
|||
use wasm_bindgen::prelude::*;
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::value::Value;
|
||||
use crate::vm::Panic;
|
||||
use imbl::Vector;
|
||||
use std::rc::Rc;
|
||||
|
||||
|
||||
#[wasm_bindgen(module = "/pkg/worker.js")]
|
||||
extern "C" {
|
||||
async fn io (output: String) -> JsValue;
|
||||
}
|
||||
|
||||
type Lines = Value; // expect a list of values
|
||||
type Commands = Value; // expect a list of values
|
||||
type Url = Value; // expect a string representing a URL
|
||||
type FinalValue = Result<Value, Panic>;
|
||||
|
||||
fn make_json_payload(verb: &'static str, data: String) -> String {
|
||||
format!("{{\"verb\":\"{verb}\",\"data\":{data}}}")
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub enum MsgOut {
|
||||
Console(Lines),
|
||||
Commands(Commands),
|
||||
SlurpRequest(Url),
|
||||
Complete(Result<Value, Panic>),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for MsgOut {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
write!(f, "{}", self.to_json())
|
||||
}
|
||||
}
|
||||
|
||||
impl MsgOut {
|
||||
pub fn to_json(&self) -> String {
|
||||
match self {
|
||||
MsgOut::Complete(value) => match value {
|
||||
Ok(value) => make_json_payload("complete", value.to_json().unwrap()),
|
||||
Err(_) => make_json_payload("complete", "\"null\"".to_string())
|
||||
},
|
||||
MsgOut::Commands(commands) => {
|
||||
let commands = commands.as_list();
|
||||
let vals_json = commands.iter().map(|v| v.to_json().unwrap()).collect::<Vec<_>>().join(",");
|
||||
let vals_json = format!("[{vals_json}]");
|
||||
make_json_payload("commands", vals_json)
|
||||
}
|
||||
MsgOut::SlurpRequest(value) => {
|
||||
// TODO: do parsing here?
|
||||
// Right now, defer to fetch
|
||||
let url = value.to_json().unwrap();
|
||||
make_json_payload("slurp", url)
|
||||
}
|
||||
MsgOut::Console(lines) => {
|
||||
let lines = lines.as_list();
|
||||
let json_lines = lines.iter().map(|line| line.stringify()).collect::<Vec<_>>().join("\n");
|
||||
let json_lines = format!("\"{json_lines}\"");
|
||||
make_json_payload("console", json_lines)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
#[serde(tag = "verb", content = "data")]
|
||||
pub enum MsgIn {
|
||||
Input(String),
|
||||
SlurpResponse(String, String, String),
|
||||
Kill,
|
||||
Keyboard(Vec<String>),
|
||||
}
|
||||
|
||||
impl MsgIn {
|
||||
pub fn to_value(self) -> Value {
|
||||
match self {
|
||||
MsgIn::Input(str) => Value::string(str),
|
||||
MsgIn::SlurpResponse(url, status, string) => {
|
||||
let url = Value::string(url);
|
||||
let status = Value::keyword(status);
|
||||
let string = Value::string(string);
|
||||
let result_tuple = Value::tuple(vec![status, string]);
|
||||
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))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
||||
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().join(","));
|
||||
let inbox = io (outbox).await;
|
||||
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");
|
||||
inbox
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user