forked from denoland/deno
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit a4dc4ef
Showing
14 changed files
with
1,831 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[package] | ||
name = "serde_v8" | ||
version = "0.0.0" | ||
authors = ["Aaron O'Mullan <aaron.omullan@gmail.com>"] | ||
edition = "2018" | ||
|
||
|
||
[dependencies] | ||
serde = { version = "1.0.123", features = ["derive"] } | ||
rusty_v8 = "0.21.0" | ||
|
||
[dev-dependencies] | ||
serde_json = "1.0.62" | ||
|
||
[[example]] | ||
name = "basic" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# serde_v8 | ||
|
||
Serde support for encoding/decoding (rusty_)v8 values. | ||
|
||
Broadly `serde_v8` aims to provide an expressive but ~maximally efficient | ||
encoding layer to biject rust & v8/js values. It's a core component of deno's | ||
op-layer and is used to encode/decode all non-buffer values. | ||
|
||
**Original issue:** | ||
[denoland/deno#9540](https://github.com/denoland/deno/issues/9540) | ||
|
||
## Quickstart | ||
|
||
`serde_v8` fits naturally into the serde ecosystem, so if you've already used | ||
`serde` or `serde_json`, `serde_v8`'s API should be very familiar. | ||
|
||
`serde_v8` exposes two key-functions: | ||
|
||
- `to_v8`: maps `rust->v8`, similar to `serde_json::to_string`, ... | ||
- `from_v8`: maps `v8->rust`, similar to `serde_json::from_str`, ... | ||
|
||
## Best practices | ||
|
||
Whilst `serde_v8` is compatible with `serde_json::Value` it's important to keep | ||
in mind that `serde_json::Value` is essentially a loosely-typed value (think | ||
nested HashMaps), so when writing ops we recommend directly using rust | ||
structs/tuples or primitives, since mapping to `serde_json::Value` will add | ||
extra overhead and result in slower ops. | ||
|
||
I also recommend avoiding unecessary "wrappers", if your op takes a single-keyed | ||
struct, consider unwrapping that as a plain value unless you plan to add fields | ||
in the near-future. | ||
|
||
Instead of returning "nothing" via `Ok(json!({}))`, change your return type to | ||
rust's unit type `()` and returning `Ok(())`, `serde_v8` will efficiently encode | ||
that as a JS `null`. | ||
|
||
## Advanced features | ||
|
||
If you need to mix rust & v8 values in structs/tuples, you can use the special | ||
`serde_v8::Value` type, which will passthrough the original v8 value untouched | ||
when encoding/decoding. | ||
|
||
## TODO | ||
|
||
- [ ] Experiment with KeyCache to optimize struct keys | ||
- [ ] Experiment with external v8 strings | ||
- [ ] Explore using | ||
[json-stringifier.cc](https://chromium.googlesource.com/v8/v8/+/refs/heads/master/src/json/json-stringifier.cc)'s | ||
fast-paths for arrays | ||
- [ ] Improve tests to test parity with `serde_json` (should be mostly | ||
interchangeable) | ||
- [ ] Consider a `Payload` type that's deserializable by itself (holds scope & | ||
value) | ||
- [ ] Ensure we return errors instead of panicking on `.unwrap()`s |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
use rusty_v8 as v8; | ||
|
||
use serde::Deserialize; | ||
|
||
#[derive(Debug, Deserialize)] | ||
struct MathOp { | ||
pub a: u64, | ||
pub b: u64, | ||
pub operator: Option<String>, | ||
} | ||
|
||
fn main() { | ||
let platform = v8::new_default_platform().unwrap(); | ||
v8::V8::initialize_platform(platform); | ||
v8::V8::initialize(); | ||
|
||
{ | ||
let isolate = &mut v8::Isolate::new(v8::CreateParams::default()); | ||
let handle_scope = &mut v8::HandleScope::new(isolate); | ||
let context = v8::Context::new(handle_scope); | ||
let scope = &mut v8::ContextScope::new(handle_scope, context); | ||
|
||
fn exec<'s>( | ||
scope: &mut v8::HandleScope<'s>, | ||
src: &str, | ||
) -> v8::Local<'s, v8::Value> { | ||
let code = v8::String::new(scope, src).unwrap(); | ||
let script = v8::Script::compile(scope, code, None).unwrap(); | ||
script.run(scope).unwrap() | ||
} | ||
|
||
let v = exec(scope, "32"); | ||
let x32: u64 = serde_v8::from_v8(scope, v).unwrap(); | ||
println!("x32 = {}", x32); | ||
|
||
let v = exec(scope, "({a: 1, b: 3, c: 'ignored'})"); | ||
let mop: MathOp = serde_v8::from_v8(scope, v).unwrap(); | ||
println!("mop = {:?}", mop); | ||
|
||
let v = exec(scope, "[1,2,3,4,5]"); | ||
let arr: Vec<u64> = serde_v8::from_v8(scope, v).unwrap(); | ||
println!("arr = {:?}", arr); | ||
|
||
let v = exec(scope, "['hello', 'world']"); | ||
let hi: Vec<String> = serde_v8::from_v8(scope, v).unwrap(); | ||
println!("hi = {:?}", hi); | ||
|
||
let v: v8::Local<v8::Value> = v8::Number::new(scope, 12345.0).into(); | ||
let x: f64 = serde_v8::from_v8(scope, v).unwrap(); | ||
println!("x = {}", x); | ||
} | ||
|
||
unsafe { | ||
v8::V8::dispose(); | ||
} | ||
v8::V8::shutdown_platform(); | ||
} |
Oops, something went wrong.