2020-01-02 15:13:47 -05:00
|
|
|
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
2020-09-05 20:34:02 -04:00
|
|
|
|
|
|
|
use crate::BufVec;
|
|
|
|
use crate::ErrBox;
|
2020-01-24 15:10:49 -05:00
|
|
|
use crate::ZeroCopyBuf;
|
2019-09-30 14:59:44 -04:00
|
|
|
use futures::Future;
|
2020-09-05 20:34:02 -04:00
|
|
|
use futures::FutureExt;
|
|
|
|
use indexmap::IndexMap;
|
|
|
|
use serde_json::json;
|
|
|
|
use serde_json::Value;
|
2019-09-30 14:59:44 -04:00
|
|
|
use std::collections::HashMap;
|
2020-09-05 20:34:02 -04:00
|
|
|
use std::iter::once;
|
|
|
|
use std::ops::Deref;
|
|
|
|
use std::ops::DerefMut;
|
2019-11-16 19:17:47 -05:00
|
|
|
use std::pin::Pin;
|
2020-02-14 19:18:36 -05:00
|
|
|
use std::rc::Rc;
|
2019-09-30 14:59:44 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
pub type OpAsyncFuture = Pin<Box<dyn Future<Output = Box<[u8]>>>>;
|
|
|
|
pub type OpFn<S> = dyn Fn(Rc<S>, BufVec) -> Op + 'static;
|
|
|
|
pub type OpId = usize;
|
2019-09-30 14:59:44 -04:00
|
|
|
|
2020-04-18 20:05:13 -04:00
|
|
|
pub enum Op {
|
2020-09-05 20:34:02 -04:00
|
|
|
Sync(Box<[u8]>),
|
2020-04-18 20:05:13 -04:00
|
|
|
Async(OpAsyncFuture),
|
2020-01-21 12:01:10 -05:00
|
|
|
/// AsyncUnref is the variation of Async, which doesn't block the program
|
|
|
|
/// exiting.
|
2020-04-18 20:05:13 -04:00
|
|
|
AsyncUnref(OpAsyncFuture),
|
2020-09-05 20:34:02 -04:00
|
|
|
NotFound,
|
2019-09-30 14:59:44 -04:00
|
|
|
}
|
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
pub trait OpRouter {
|
|
|
|
fn route_op(self: Rc<Self>, op_id: OpId, bufs: BufVec) -> Op;
|
2019-09-30 14:59:44 -04:00
|
|
|
}
|
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
pub trait OpRegistry: OpRouter + 'static {
|
|
|
|
fn get_op_catalog(self: Rc<Self>) -> HashMap<String, OpId>;
|
|
|
|
|
|
|
|
fn register_op<F>(&self, name: &str, op_fn: F) -> OpId
|
|
|
|
where
|
|
|
|
F: Fn(Rc<Self>, BufVec) -> Op + 'static;
|
|
|
|
|
|
|
|
fn register_op_json_sync<F>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
|
|
|
|
where
|
|
|
|
F: Fn(&Self, Value, &mut [ZeroCopyBuf]) -> Result<Value, ErrBox> + 'static,
|
|
|
|
{
|
|
|
|
let base_op_fn = move |state: Rc<Self>, mut bufs: BufVec| -> Op {
|
|
|
|
let result = serde_json::from_slice(&bufs[0])
|
|
|
|
.map_err(ErrBox::from)
|
|
|
|
.and_then(|args| op_fn(&state, args, &mut bufs[1..]));
|
|
|
|
let buf = state.json_serialize_op_result(None, result);
|
2020-08-12 10:44:58 -04:00
|
|
|
Op::Sync(buf)
|
2020-09-05 20:34:02 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
self.register_op(name, base_op_fn)
|
2019-09-30 14:59:44 -04:00
|
|
|
}
|
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
fn register_op_json_async<F, R>(self: &Rc<Self>, name: &str, op_fn: F) -> OpId
|
2020-08-12 10:44:58 -04:00
|
|
|
where
|
2020-09-05 20:34:02 -04:00
|
|
|
F: Fn(Rc<Self>, Value, BufVec) -> R + 'static,
|
|
|
|
R: Future<Output = Result<Value, ErrBox>> + 'static,
|
2020-08-12 10:44:58 -04:00
|
|
|
{
|
2020-09-05 20:34:02 -04:00
|
|
|
let try_dispatch_op = move |state: Rc<Self>,
|
|
|
|
bufs: BufVec|
|
|
|
|
-> Result<Op, ErrBox> {
|
|
|
|
let args: Value = serde_json::from_slice(&bufs[0])?;
|
|
|
|
let promise_id = args
|
|
|
|
.get("promiseId")
|
|
|
|
.and_then(Value::as_u64)
|
|
|
|
.ok_or_else(|| ErrBox::type_error("missing or invalid `promiseId`"))?;
|
|
|
|
let bufs = bufs[1..].into();
|
|
|
|
let fut = op_fn(state.clone(), args, bufs).map(move |result| {
|
|
|
|
state.json_serialize_op_result(Some(promise_id), result)
|
|
|
|
});
|
|
|
|
Ok(Op::Async(Box::pin(fut)))
|
|
|
|
};
|
2019-09-30 14:59:44 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
let base_op_fn = move |state: Rc<Self>, bufs: BufVec| -> Op {
|
|
|
|
match try_dispatch_op(state.clone(), bufs) {
|
|
|
|
Ok(op) => op,
|
|
|
|
Err(err) => Op::Sync(state.json_serialize_op_result(None, Err(err))),
|
|
|
|
}
|
|
|
|
};
|
2019-09-30 14:59:44 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
self.register_op(name, base_op_fn)
|
2019-09-30 14:59:44 -04:00
|
|
|
}
|
2020-06-09 18:14:13 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
fn json_serialize_op_result(
|
|
|
|
&self,
|
|
|
|
promise_id: Option<u64>,
|
|
|
|
result: Result<Value, ErrBox>,
|
|
|
|
) -> Box<[u8]> {
|
|
|
|
let value = match result {
|
|
|
|
Ok(v) => json!({ "ok": v, "promiseId": promise_id }),
|
|
|
|
Err(err) => json!({
|
|
|
|
"promiseId": promise_id ,
|
|
|
|
"err": {
|
|
|
|
"className": self.get_error_class_name(&err),
|
|
|
|
"message": err.to_string(),
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
};
|
|
|
|
serde_json::to_vec(&value).unwrap().into_boxed_slice()
|
2020-06-09 18:14:13 -04:00
|
|
|
}
|
2019-09-30 14:59:44 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
fn get_error_class_name(&self, _err: &ErrBox) -> &'static str {
|
|
|
|
"Error"
|
2019-09-30 14:59:44 -04:00
|
|
|
}
|
|
|
|
}
|
2019-11-18 21:13:04 -05:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
/// Collection for storing registered ops. The special 'get_op_catalog'
|
|
|
|
/// op with OpId `0` is automatically added when the OpTable is created.
|
|
|
|
pub struct OpTable<S>(IndexMap<String, Rc<OpFn<S>>>);
|
2019-11-18 21:13:04 -05:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
impl<S: OpRegistry> OpTable<S> {
|
|
|
|
pub fn get_op_catalog(&self) -> HashMap<String, OpId> {
|
|
|
|
self.keys().cloned().zip(0..).collect()
|
|
|
|
}
|
2020-04-19 23:54:46 -04:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
fn op_get_op_catalog(state: Rc<S>, _bufs: BufVec) -> Op {
|
|
|
|
let ops = state.get_op_catalog();
|
|
|
|
let buf = serde_json::to_vec(&ops).map(Into::into).unwrap();
|
|
|
|
Op::Sync(buf)
|
2020-05-29 17:41:39 -04:00
|
|
|
}
|
2020-09-05 20:34:02 -04:00
|
|
|
}
|
2019-11-18 21:13:04 -05:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
impl<S: OpRegistry> Default for OpTable<S> {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self(
|
|
|
|
once(("ops".to_owned(), Rc::new(Self::op_get_op_catalog) as _)).collect(),
|
|
|
|
)
|
2020-04-19 23:54:46 -04:00
|
|
|
}
|
2020-09-05 20:34:02 -04:00
|
|
|
}
|
2019-11-18 21:13:04 -05:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
impl<S> Deref for OpTable<S> {
|
|
|
|
type Target = IndexMap<String, Rc<OpFn<S>>>;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
2019-11-18 21:13:04 -05:00
|
|
|
}
|
2020-09-05 20:34:02 -04:00
|
|
|
}
|
2019-11-18 21:13:04 -05:00
|
|
|
|
2020-09-05 20:34:02 -04:00
|
|
|
impl<S> DerefMut for OpTable<S> {
|
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
|
|
|
&mut self.0
|
|
|
|
}
|
2019-11-18 21:13:04 -05:00
|
|
|
}
|