use serde to serialize the things
This commit is contained in:
parent
9f9f59b33b
commit
c6709bb2e8
|
@ -18,3 +18,4 @@ serde = {version = "1.0", features = ["derive"]}
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
console_error_panic_hook = "0.1.7"
|
console_error_panic_hook = "0.1.7"
|
||||||
struct_scalpel = "0.1.1"
|
struct_scalpel = "0.1.1"
|
||||||
|
serde-wasm-bindgen = "0.6.5"
|
||||||
|
|
12
pkg/ludus.js
12
pkg/ludus.js
|
@ -32,10 +32,18 @@ async function handle_messages (e) {
|
||||||
outbox = []
|
outbox = []
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
case "Error": {
|
||||||
|
console.log("Main: ludus errored with => ", msg.data)
|
||||||
|
running = false
|
||||||
|
ready = false
|
||||||
|
outbox = []
|
||||||
|
break
|
||||||
|
}
|
||||||
// TODO: do more than report these
|
// TODO: do more than report these
|
||||||
case "Console": {
|
case "Console": {
|
||||||
console.log("Main: ludus says => ", msg.data)
|
let new_lines = msg.data.join("\n");
|
||||||
ludus_console = ludus_console + msg.data
|
console.log("Main: ludus says => ", new_lines)
|
||||||
|
ludus_console = ludus_console + new_lines
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case "Commands": {
|
case "Commands": {
|
||||||
|
|
4
pkg/rudus.d.ts
vendored
4
pkg/rudus.d.ts
vendored
|
@ -14,8 +14,8 @@ export interface InitOutput {
|
||||||
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
readonly __wbindgen_export_6: WebAssembly.Table;
|
readonly __wbindgen_export_6: WebAssembly.Table;
|
||||||
readonly closure347_externref_shim: (a: number, b: number, c: any) => void;
|
readonly closure305_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
readonly closure371_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
readonly closure329_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
readonly __wbindgen_start: () => void;
|
readonly __wbindgen_start: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -240,13 +240,13 @@ function _assertNum(n) {
|
||||||
function __wbg_adapter_20(arg0, arg1, arg2) {
|
function __wbg_adapter_20(arg0, arg1, arg2) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure347_externref_shim(arg0, arg1, arg2);
|
wasm.closure305_externref_shim(arg0, arg1, arg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
function __wbg_adapter_50(arg0, arg1, arg2, arg3) {
|
||||||
_assertNum(arg0);
|
_assertNum(arg0);
|
||||||
_assertNum(arg1);
|
_assertNum(arg1);
|
||||||
wasm.closure371_externref_shim(arg0, arg1, arg2, arg3);
|
wasm.closure329_externref_shim(arg0, arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function __wbg_load(module, imports) {
|
async function __wbg_load(module, imports) {
|
||||||
|
@ -425,8 +425,8 @@ function __wbg_get_imports() {
|
||||||
_assertBoolean(ret);
|
_assertBoolean(ret);
|
||||||
return ret;
|
return ret;
|
||||||
};
|
};
|
||||||
imports.wbg.__wbindgen_closure_wrapper7945 = function() { return logError(function (arg0, arg1, arg2) {
|
imports.wbg.__wbindgen_closure_wrapper7885 = function() { return logError(function (arg0, arg1, arg2) {
|
||||||
const ret = makeMutClosure(arg0, arg1, 348, __wbg_adapter_20);
|
const ret = makeMutClosure(arg0, arg1, 306, __wbg_adapter_20);
|
||||||
return ret;
|
return ret;
|
||||||
}, arguments) };
|
}, arguments) };
|
||||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||||
|
|
Binary file not shown.
4
pkg/rudus_bg.wasm.d.ts
vendored
4
pkg/rudus_bg.wasm.d.ts
vendored
|
@ -9,6 +9,6 @@ export const __wbindgen_free: (a: number, b: number, c: number) => void;
|
||||||
export const __wbindgen_malloc: (a: number, b: number) => number;
|
export const __wbindgen_malloc: (a: number, b: number) => number;
|
||||||
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
export const __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
||||||
export const __wbindgen_export_6: WebAssembly.Table;
|
export const __wbindgen_export_6: WebAssembly.Table;
|
||||||
export const closure347_externref_shim: (a: number, b: number, c: any) => void;
|
export const closure305_externref_shim: (a: number, b: number, c: any) => void;
|
||||||
export const closure371_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
export const closure329_externref_shim: (a: number, b: number, c: any, d: any) => void;
|
||||||
export const __wbindgen_start: () => void;
|
export const __wbindgen_start: () => void;
|
||||||
|
|
98
src/io.rs
98
src/io.rs
|
@ -18,62 +18,54 @@ extern "C" {
|
||||||
fn log(s: String);
|
fn log(s: String);
|
||||||
}
|
}
|
||||||
|
|
||||||
type Commands = Value; // expect a list of values
|
type Url = Value; // expect a string
|
||||||
type Url = Value; // expect a string representing a URL
|
type Commands = Value; // expect a list of command tuples
|
||||||
type FinalValue = Result<Value, Panic>;
|
|
||||||
|
|
||||||
fn make_json_payload(verb: &'static str, data: String) -> String {
|
#[derive(Debug, Clone, PartialEq, Serialize)]
|
||||||
format!("{{\"verb\":\"{verb}\",\"data\":{data}}}")
|
#[serde(tag = "verb", content = "data")]
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub enum MsgOut {
|
pub enum MsgOut {
|
||||||
Console(Value),
|
Console(Value),
|
||||||
Commands(Commands),
|
Commands(Commands),
|
||||||
Fetch(Url),
|
Fetch(Url),
|
||||||
Complete(FinalValue),
|
Complete(Value),
|
||||||
|
Error(String),
|
||||||
Ready
|
Ready
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for MsgOut {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(f, "{}", self.to_json())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MsgOut {
|
// impl MsgOut {
|
||||||
pub fn to_json(&self) -> String {
|
// pub fn to_json(&self) -> String {
|
||||||
match self {
|
// match self {
|
||||||
MsgOut::Complete(value) => match value {
|
// MsgOut::Complete(value) => match value {
|
||||||
Ok(value) => {
|
// Ok(value) => {
|
||||||
make_json_payload("Complete", serde_json::to_string(&value.show()).unwrap())
|
// make_json_payload("Complete", serde_json::to_string(&value.show()).unwrap())
|
||||||
},
|
// },
|
||||||
Err(_) => make_json_payload("Complete", "\"null\"".to_string())
|
// Err(_) => make_json_payload("Complete", "\"null\"".to_string())
|
||||||
},
|
// },
|
||||||
MsgOut::Commands(commands) => {
|
// MsgOut::Commands(commands) => {
|
||||||
let commands = commands.as_list();
|
// let commands = commands.as_list();
|
||||||
let vals_json = commands.iter().map(|v| v.to_json().unwrap()).collect::<Vec<_>>().join(",");
|
// let vals_json = commands.iter().map(|v| v.to_json().unwrap()).collect::<Vec<_>>().join(",");
|
||||||
let vals_json = format!("[{vals_json}]");
|
// let vals_json = format!("[{vals_json}]");
|
||||||
make_json_payload("Commands", vals_json)
|
// make_json_payload("Commands", vals_json)
|
||||||
}
|
// }
|
||||||
MsgOut::Fetch(value) => {
|
// MsgOut::Fetch(value) => {
|
||||||
// TODO: do parsing here?
|
// // TODO: do parsing here?
|
||||||
// Right now, defer to fetch
|
// // Right now, defer to fetch
|
||||||
let url = value.to_json().unwrap();
|
// let url = value.to_json().unwrap();
|
||||||
make_json_payload("Fetch", url)
|
// make_json_payload("Fetch", url)
|
||||||
}
|
// }
|
||||||
MsgOut::Console(lines) => {
|
// MsgOut::Console(lines) => {
|
||||||
let lines = lines.as_list();
|
// let lines = lines.as_list();
|
||||||
let json_lines = lines.iter().map(|line| line.to_json().unwrap()).collect::<Vec<_>>().join("\\n");
|
// let json_lines = lines.iter().map(|line| line.to_json().unwrap()).collect::<Vec<_>>().join("\\n");
|
||||||
let json_lines = format!("\"{json_lines}\"");
|
// let json_lines = format!("\"{json_lines}\"");
|
||||||
make_json_payload("Console", json_lines)
|
// make_json_payload("Console", json_lines)
|
||||||
}
|
// }
|
||||||
MsgOut::Ready => {
|
// MsgOut::Ready => {
|
||||||
make_json_payload("Ready", "\"null\"".to_string())
|
// make_json_payload("Ready", "\"null\"".to_string())
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
#[serde(tag = "verb", content = "data")]
|
#[serde(tag = "verb", content = "data")]
|
||||||
|
@ -124,18 +116,12 @@ impl MsgIn {
|
||||||
|
|
||||||
pub async fn send_err_to_ludus_console(msg: String) {
|
pub async fn send_err_to_ludus_console(msg: String) {
|
||||||
log(msg.clone());
|
log(msg.clone());
|
||||||
let console_msg = Value::string(msg);
|
do_io(vec![MsgOut::Ready, MsgOut::Error(msg)]).await;
|
||||||
let mut console_vector = Vector::new();
|
|
||||||
console_vector.push_back(console_msg);
|
|
||||||
let console_list = Value::list(console_vector);
|
|
||||||
let console = MsgOut::Console(console_list);
|
|
||||||
let completion = MsgOut::Complete(Err(Panic::Str("")));
|
|
||||||
do_io(vec![MsgOut::Ready, console, completion]).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
pub async fn do_io (msgs: Vec<MsgOut>) -> Vec<MsgIn> {
|
||||||
let outbox = format!("[{}]", msgs.iter().map(|msg| msg.to_json()).collect::<Vec<_>>().join(","));
|
let json = serde_json::to_string(&msgs).unwrap();
|
||||||
let inbox = io (outbox).await;
|
let inbox = io (json).await;
|
||||||
// if our request dies, make sure we return back to the event loop
|
// if our request dies, make sure we return back to the event loop
|
||||||
let inbox = match inbox {
|
let inbox = match inbox {
|
||||||
Ok(msgs) => msgs,
|
Ok(msgs) => msgs,
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use rudus::value::Value;
|
use rudus::value::Value;
|
||||||
use std::env;
|
use std::env;
|
||||||
use struct_scalpel::print_dissection_info;
|
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
env::set_var("RUST_BACKTRACE", "1");
|
env::set_var("RUST_BACKTRACE", "1");
|
||||||
print_dissection_info::<Value>();
|
|
||||||
}
|
}
|
||||||
|
|
179
src/value.rs
179
src/value.rs
|
@ -1,9 +1,10 @@
|
||||||
use crate::base::BaseFn;
|
use crate::base::BaseFn;
|
||||||
use crate::chunk::Chunk;
|
use crate::chunk::Chunk;
|
||||||
use imbl::{HashMap, Vector};
|
use imbl::{HashMap, Vector};
|
||||||
|
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use struct_scalpel::Dissectible;
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum LFn {
|
pub enum LFn {
|
||||||
|
@ -130,6 +131,19 @@ impl std::fmt::Display for Key {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Key {
|
||||||
|
fn serialize<S>(&self, srlzr: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Key::Keyword(s) => srlzr.serialize_str(s),
|
||||||
|
Key::Interned(s) => srlzr.serialize_str(s),
|
||||||
|
Key::String(s) => srlzr.serialize_str(s.as_str()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Key {
|
impl Key {
|
||||||
pub fn to_value(&self) -> Value {
|
pub fn to_value(&self) -> Value {
|
||||||
match self {
|
match self {
|
||||||
|
@ -149,7 +163,7 @@ impl Key {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Dissectible)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Nothing,
|
Nothing,
|
||||||
Nil,
|
Nil,
|
||||||
|
@ -247,6 +261,51 @@ impl std::fmt::Display for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Serialize for Value {
|
||||||
|
fn serialize<S>(&self, srlzr: S) -> Result<S::Ok, S::Error>
|
||||||
|
where
|
||||||
|
S: Serializer,
|
||||||
|
{
|
||||||
|
use Value::*;
|
||||||
|
match self {
|
||||||
|
Nil => srlzr.serialize_none(),
|
||||||
|
True => srlzr.serialize_bool(true),
|
||||||
|
False => srlzr.serialize_bool(false),
|
||||||
|
Number(n) => srlzr.serialize_f64(*n),
|
||||||
|
Interned(s) => srlzr.serialize_str(s),
|
||||||
|
Keyword(k) => srlzr.serialize_str(k),
|
||||||
|
String(s) => srlzr.serialize_str(s.as_str()),
|
||||||
|
Tuple(t) => {
|
||||||
|
let mut seq = srlzr.serialize_seq(Some(t.len()))?;
|
||||||
|
for e in t.iter() {
|
||||||
|
seq.serialize_element(e)?;
|
||||||
|
}
|
||||||
|
seq.end()
|
||||||
|
}
|
||||||
|
List(l) => {
|
||||||
|
let mut seq = srlzr.serialize_seq(Some(l.len()))?;
|
||||||
|
for e in l.iter() {
|
||||||
|
seq.serialize_element(e)?;
|
||||||
|
}
|
||||||
|
seq.end()
|
||||||
|
}
|
||||||
|
Dict(d) => {
|
||||||
|
let mut map = srlzr.serialize_map(Some(d.len()))?;
|
||||||
|
for (k, v) in d.iter() {
|
||||||
|
map.serialize_entry(k, v)?;
|
||||||
|
}
|
||||||
|
map.end()
|
||||||
|
}
|
||||||
|
Box(b) => {
|
||||||
|
let boxed = b.borrow();
|
||||||
|
(*boxed).serialize(srlzr)
|
||||||
|
}
|
||||||
|
Fn(..) | BaseFn(..) | Partial(..) => unreachable!(),
|
||||||
|
Process | Nothing => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
pub fn show(&self) -> String {
|
pub fn show(&self) -> String {
|
||||||
use Value::*;
|
use Value::*;
|
||||||
|
@ -292,57 +351,71 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_json(&self) -> Option<String> {
|
// pub fn to_js(&self) -> JsValue {
|
||||||
use Value::*;
|
// use Value::*;
|
||||||
match self {
|
// match self {
|
||||||
True | False | Number(..) => Some(self.show()),
|
// Nil => JsValue::NULL,
|
||||||
String(string) => Some(string.escape_default().to_string()),
|
// True => JsValue::TRUE,
|
||||||
Interned(str) => Some(str.escape_default().to_string()),
|
// False => JsValue::FALSE,
|
||||||
Keyword(str) => Some(format!("\"{str}\"")),
|
// Number(n) => JsValue::from_f64(*n),
|
||||||
List(members) => {
|
// Interned(s) => JsValue::from_str(s),
|
||||||
let mut joined = "".to_string();
|
// String(s) => JsValue::from_str(s.as_str()),
|
||||||
let mut members = members.iter();
|
// Keyword(k) => JsValue::from_str(k),
|
||||||
if let Some(member) = members.next() {
|
// _ => todo!(),
|
||||||
joined = member.to_json()?;
|
// }
|
||||||
}
|
// }
|
||||||
for member in members {
|
|
||||||
let json = member.to_json()?;
|
// pub fn to_json(&self) -> Option<String> {
|
||||||
joined = format!("{joined},{json}");
|
// use Value::*;
|
||||||
}
|
// match self {
|
||||||
Some(format!("[{joined}]"))
|
// True | False | Number(..) => Some(self.show()),
|
||||||
}
|
// String(string) => Some(string.escape_default().to_string()),
|
||||||
Tuple(members) => {
|
// Interned(str) => Some(str.escape_default().to_string()),
|
||||||
let mut joined = "".to_string();
|
// Keyword(str) => Some(format!("\"{str}\"")),
|
||||||
let mut members = members.iter();
|
// List(members) => {
|
||||||
if let Some(member) = members.next() {
|
// let mut joined = "".to_string();
|
||||||
joined = member.to_json()?;
|
// let mut members = members.iter();
|
||||||
}
|
// if let Some(member) = members.next() {
|
||||||
for member in members {
|
// joined = member.to_json()?;
|
||||||
let json = member.to_json()?;
|
// }
|
||||||
joined = format!("{joined},{json}");
|
// for member in members {
|
||||||
}
|
// let json = member.to_json()?;
|
||||||
Some(format!("[{joined}]"))
|
// joined = format!("{joined},{json}");
|
||||||
}
|
// }
|
||||||
Dict(members) => {
|
// Some(format!("[{joined}]"))
|
||||||
let mut joined = "".to_string();
|
// }
|
||||||
let mut members = members.iter();
|
// Tuple(members) => {
|
||||||
if let Some((key, value)) = members.next() {
|
// let mut joined = "".to_string();
|
||||||
let json = value.to_json()?;
|
// let mut members = members.iter();
|
||||||
joined = format!("\"{key}\":{json}")
|
// if let Some(member) = members.next() {
|
||||||
}
|
// joined = member.to_json()?;
|
||||||
for (key, value) in members {
|
// }
|
||||||
let json = value.to_json()?;
|
// for member in members {
|
||||||
joined = format!("{joined},\"{key}\": {json}");
|
// let json = member.to_json()?;
|
||||||
}
|
// joined = format!("{joined},{json}");
|
||||||
Some(format!("{{{joined}}}"))
|
// }
|
||||||
}
|
// Some(format!("[{joined}]"))
|
||||||
not_serializable => {
|
// }
|
||||||
println!("Cannot convert to json:");
|
// Dict(members) => {
|
||||||
dbg!(not_serializable);
|
// let mut joined = "".to_string();
|
||||||
None
|
// let mut members = members.iter();
|
||||||
}
|
// if let Some((key, value)) = members.next() {
|
||||||
}
|
// let json = value.to_json()?;
|
||||||
}
|
// joined = format!("\"{key}\":{json}")
|
||||||
|
// }
|
||||||
|
// for (key, value) in members {
|
||||||
|
// let json = value.to_json()?;
|
||||||
|
// joined = format!("{joined},\"{key}\": {json}");
|
||||||
|
// }
|
||||||
|
// Some(format!("{{{joined}}}"))
|
||||||
|
// }
|
||||||
|
// not_serializable => {
|
||||||
|
// println!("Cannot convert to json:");
|
||||||
|
// dbg!(not_serializable);
|
||||||
|
// None
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
pub fn stringify(&self) -> String {
|
pub fn stringify(&self) -> String {
|
||||||
use Value::*;
|
use Value::*;
|
||||||
|
|
|
@ -417,7 +417,11 @@ impl World {
|
||||||
// TODO: if we have a panic, actually add the panic message to the console
|
// TODO: if we have a panic, actually add the panic message to the console
|
||||||
let result = self.active_result().clone().unwrap();
|
let result = self.active_result().clone().unwrap();
|
||||||
self.result = Some(result.clone());
|
self.result = Some(result.clone());
|
||||||
outbox.push(MsgOut::Complete(result));
|
let result_msg = match result {
|
||||||
|
Ok(value) => MsgOut::Complete(Value::string(value.show())),
|
||||||
|
Err(_msg) => MsgOut::Error("Ludus panicked!".to_string())
|
||||||
|
};
|
||||||
|
outbox.push(result_msg);
|
||||||
outbox
|
outbox
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,7 +474,7 @@ impl World {
|
||||||
self.maybe_do_io().await;
|
self.maybe_do_io().await;
|
||||||
if self.kill_signal {
|
if self.kill_signal {
|
||||||
let mut outbox = self.flush_buffers();
|
let mut outbox = self.flush_buffers();
|
||||||
outbox.push(MsgOut::Complete(Err(Panic::Str("ludus killed by user"))));
|
outbox.push(MsgOut::Error("Ludus killed by user".to_string()));
|
||||||
do_io(outbox).await;
|
do_io(outbox).await;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user