diff options
author | Inteon <42113979+inteon@users.noreply.github.com> | 2021-03-20 17:51:08 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-20 17:51:08 +0100 |
commit | 1251c893212d57303ecdfa8d953d1e487cb7ec7d (patch) | |
tree | 80b3a55872db0a4ee0c9e594601d330e39ca4873 /core/ops.rs | |
parent | 0d26a82ea9169c013e9b0f29c1ec418b28e273cf (diff) |
refactor: Move bin ops to deno_core and unify logic with json ops (#9457)
This commit moves implementation of bin ops to "deno_core" crates
as well as unifying logic between bin ops and json ops to reuse
as much code as possible (both in Rust and JavaScript).
Diffstat (limited to 'core/ops.rs')
-rw-r--r-- | core/ops.rs | 122 |
1 files changed, 0 insertions, 122 deletions
diff --git a/core/ops.rs b/core/ops.rs index eceab7feb..212a713ad 100644 --- a/core/ops.rs +++ b/core/ops.rs @@ -10,13 +10,10 @@ use crate::BufVec; use crate::ZeroCopyBuf; use futures::Future; use indexmap::IndexMap; -use serde::de::DeserializeOwned; -use serde::Serialize; use serde_json::json; use serde_json::Value; use std::cell::RefCell; use std::collections::HashMap; -use std::convert::TryInto; use std::iter::once; use std::ops::Deref; use std::ops::DerefMut; @@ -117,125 +114,6 @@ impl Default for OpTable { } } -/// Creates an op that passes data synchronously using JSON. -/// -/// The provided function `op_fn` has the following parameters: -/// * `&mut OpState`: the op state, can be used to read/write resources in the runtime from an op. -/// * `V`: the deserializable value that is passed to the Rust function. -/// * `&mut [ZeroCopyBuf]`: raw bytes passed along, usually not needed if the JSON value is used. -/// -/// `op_fn` returns a serializable value, which is directly returned to JavaScript. -/// -/// When registering an op like this... -/// ```ignore -/// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::json_op_sync(Self::hello_op)); -/// ``` -/// -/// ...it can be invoked from JS using the provided name, for example: -/// ```js -/// Deno.core.ops(); -/// let result = Deno.core.jsonOpSync("function_name", args); -/// ``` -/// -/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. -/// A more complete example is available in the examples directory. -pub fn json_op_sync<F, V, R>(op_fn: F) -> Box<OpFn> -where - F: Fn(&mut OpState, V, &mut [ZeroCopyBuf]) -> Result<R, AnyError> + 'static, - V: DeserializeOwned, - R: Serialize, -{ - Box::new(move |state: Rc<RefCell<OpState>>, mut bufs: BufVec| -> Op { - let result = serde_json::from_slice(&bufs[0]) - .map_err(AnyError::from) - .and_then(|args| op_fn(&mut state.borrow_mut(), args, &mut bufs[1..])); - let buf = - json_serialize_op_result(None, result, state.borrow().get_error_class_fn); - Op::Sync(buf) - }) -} - -/// Creates an op that passes data asynchronously using JSON. -/// -/// The provided function `op_fn` has the following parameters: -/// * `Rc<RefCell<OpState>`: the op state, can be used to read/write resources in the runtime from an op. -/// * `V`: the deserializable value that is passed to the Rust function. -/// * `BufVec`: raw bytes passed along, usually not needed if the JSON value is used. -/// -/// `op_fn` returns a future, whose output is a serializable value. This value will be asynchronously -/// returned to JavaScript. -/// -/// When registering an op like this... -/// ```ignore -/// let mut runtime = JsRuntime::new(...); -/// runtime.register_op("hello", deno_core::json_op_async(Self::hello_op)); -/// ``` -/// -/// ...it can be invoked from JS using the provided name, for example: -/// ```js -/// Deno.core.ops(); -/// let future = Deno.core.jsonOpAsync("function_name", args); -/// ``` -/// -/// The `Deno.core.ops()` statement is needed once before any op calls, for initialization. -/// A more complete example is available in the examples directory. -pub fn json_op_async<F, V, R, RV>(op_fn: F) -> Box<OpFn> -where - F: Fn(Rc<RefCell<OpState>>, V, BufVec) -> R + 'static, - V: DeserializeOwned, - R: Future<Output = Result<RV, AnyError>> + 'static, - RV: Serialize, -{ - let try_dispatch_op = - move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Result<Op, AnyError> { - let promise_id = bufs[0] - .get(0..8) - .map(|b| u64::from_be_bytes(b.try_into().unwrap())) - .ok_or_else(|| type_error("missing or invalid `promiseId`"))?; - let args = serde_json::from_slice(&bufs[0][8..])?; - let bufs = bufs[1..].into(); - use crate::futures::FutureExt; - let fut = op_fn(state.clone(), args, bufs).map(move |result| { - json_serialize_op_result( - Some(promise_id), - result, - state.borrow().get_error_class_fn, - ) - }); - Ok(Op::Async(Box::pin(fut))) - }; - - Box::new(move |state: Rc<RefCell<OpState>>, bufs: BufVec| -> Op { - match try_dispatch_op(state.clone(), bufs) { - Ok(op) => op, - Err(err) => Op::Sync(json_serialize_op_result( - None, - Err::<(), AnyError>(err), - state.borrow().get_error_class_fn, - )), - } - }) -} - -fn json_serialize_op_result<R: Serialize>( - promise_id: Option<u64>, - result: Result<R, AnyError>, - get_error_class_fn: crate::runtime::GetErrorClassFn, -) -> Box<[u8]> { - let value = match result { - Ok(v) => serde_json::json!({ "ok": v, "promiseId": promise_id }), - Err(err) => serde_json::json!({ - "promiseId": promise_id , - "err": { - "className": (get_error_class_fn)(&err), - "message": err.to_string(), - } - }), - }; - serde_json::to_vec(&value).unwrap().into_boxed_slice() -} - /// Return map of resources with id as key /// and string representation as value. /// |