Skip to content

Commit

Permalink
update docs/comments and fix issue internal error kind mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
afinch7 committed Mar 19, 2020
1 parent a39af25 commit 97a0187
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 11 deletions.
32 changes: 22 additions & 10 deletions core/dispatch_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,19 @@ use std::fmt::Debug;
use std::future::Future;
use std::pin::Pin;

/// Error kind representation for error returned by dispatch json ops.
/// Error kind representation for all errors.
/// For encoding kinds are split into three distinct regions:
/// internal(<0), external(>0), and UnKind/other(==0).
/// ========================================================================
/// i64 Min <--- Internal Kinds ---< -1|0|1 >--- External Kinds ---> i64 Max
/// ^
/// UnKind/Other
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum JsonErrorKind {
/// Normal error kind. These values are meaningless outside of
/// their respective implementation of dispatch json(see full explanation below).
///
/// A error kind value of 46 might represent "PermissonDenied" in TS/JS
/// for one op, but represent "ConnectionRefused" for another op.
/// Make sure this is correcty mapped between TS/JS and rust.
/// TODO(afinch7) expand on this once TS/JS implementation is done.
/// Normal error kind.
/// This value should always be greater than 0!
/// These values are meaningless outside of their respective implementation
/// of dispatch json(see full explanation in JsonError::kind).
Kind(u32),
/// No kind/not implemented. Corresponds to kind = 0.
UnKind,
Expand All @@ -34,9 +37,18 @@ impl From<u32> for JsonErrorKind {
}
}

/// Json error message and kind
/// Object that can be encoded to json and sent back to represent rust errors to TS/JS.
pub trait JsonError: Sync + Send {
/// Kind is specific to implementation.
/// Returns kind represented as a JsonErrorKind. The numeric values assoiacted
/// to each kind are arbitrary(see explaination below).
///
/// Their isn't a simple way to driectly share kind types between TS and rust.
/// It is up to the implementation to control how error kinds are mapped to
/// u32 values on the rust side and then converted back on the TS/JS side.
/// On the rust side this is pretty much free form, but I recommend using
/// a enum with discriminant values(see `InternalErrorKinds`). For the ts side
/// this is controlled by the "errorFactory":
/// (kind as u32, message) -> errorFactory -> Error
fn kind(&self) -> JsonErrorKind;
/// Error message as string value.
fn msg(&self) -> String;
Expand Down
18 changes: 17 additions & 1 deletion core/dispatch_json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ abstract class DispatchJsonOp {
protected unwrapResponse(res: JsonResponse): Ok {
if (res.err != null) {
if (res.err.kind < 0) {
throw new InternalDispatchJsonError(res.err!.kind, res.err!.message);
throw new InternalDispatchJsonError(
res.err!.kind * -1, // Transform kind back to positive
res.err!.message
);
} else if (res.err.kind > 0) {
throw this.errorFactory(res.err!.kind, res.err!.message);
} else {
Expand All @@ -127,6 +130,7 @@ abstract class DispatchJsonOp {
promise.resolve(res);
}

// Dispatch this op with a Sync call
dispatchSync(args: object = {}, zeroCopy?: Uint8Array): Ok {
const argsUi8 = encode(args);
const resUi8 = this.dispatch(argsUi8, zeroCopy);
Expand All @@ -137,6 +141,7 @@ abstract class DispatchJsonOp {
return this.unwrapResponse(res);
}

// Dispatch this op with a Async call
async dispatchAsync(args: object = {}, zeroCopy?: Uint8Array): Promise<Ok> {
const promiseId = this.nextPromiseId();
args = Object.assign(args, { promiseId });
Expand All @@ -158,6 +163,17 @@ abstract class DispatchJsonOp {
}
}

/** Json based dispatch wrapper for core ops.
*
* Error kind mapping is controlled by errorFactory. Async handler is automatically
* set during construction.
*
* const opId = Deno.ops()["json_op"];
* const jsonOp = new DispatchJsonCoreOp(opId, (kind, msg) => return new CustomError(kind, msg));
* const response = jsonOp.dispatchSync({ data });
* console.log(response.items[3].name);
*/

export class DispatchJsonCoreOp extends DispatchJsonOp {
constructor(private readonly opId: number, errorFactory: ErrorFactory) {
super((c, zc) => Deno["core"].dispatch(this.opId, c, zc), errorFactory);
Expand Down

0 comments on commit 97a0187

Please sign in to comment.