1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-22 07:14:47 -05:00

cleanup(serde_v8): disambiguate ZeroCopyBuf (#14380)

This commit is contained in:
Aaron O'Mullan 2022-04-25 09:56:47 -05:00 committed by GitHub
parent ddbfa1418c
commit 12f7581ed9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 77 additions and 75 deletions

View file

@ -25,10 +25,10 @@ pub use parking_lot;
pub use serde;
pub use serde_json;
pub use serde_v8;
pub use serde_v8::Buffer as ZeroCopyBuf;
pub use serde_v8::ByteString;
pub use serde_v8::StringOrBuffer;
pub use serde_v8::U16String;
pub use serde_v8::ZeroCopyBuf;
pub use sourcemap;
pub use url;
pub use v8;

View file

@ -8,7 +8,7 @@ use crate::magic::transl8::FromV8;
use crate::magic::transl8::{visit_magic, MagicType};
use crate::payload::ValueType;
use crate::{
magic, Buffer, ByteString, DetachedBuffer, StringOrBuffer, U16String,
magic, ByteString, DetachedBuffer, StringOrBuffer, U16String, ZeroCopyBuf,
};
pub struct Deserializer<'a, 'b, 's> {
@ -145,7 +145,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
// Map to Vec<u8> when deserialized via deserialize_any
// e.g: for untagged enums or StringOrBuffer
ValueType::ArrayBufferView | ValueType::ArrayBuffer => {
magic::zero_copy_buf::ZeroCopyBuf::from_v8(&mut *self.scope, self.input)
magic::v8slice::V8Slice::from_v8(&mut *self.scope, self.input)
.and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
}
}
@ -349,8 +349,8 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
V: Visitor<'de>,
{
match name {
Buffer::MAGIC_NAME => {
visit_magic(visitor, Buffer::from_v8(self.scope, self.input)?)
ZeroCopyBuf::MAGIC_NAME => {
visit_magic(visitor, ZeroCopyBuf::from_v8(self.scope, self.input)?)
}
DetachedBuffer::MAGIC_NAME => {
visit_magic(visitor, DetachedBuffer::from_v8(self.scope, self.input)?)

View file

@ -11,7 +11,7 @@ pub mod utils;
pub use de::{from_v8, from_v8_cached, Deserializer};
pub use error::{Error, Result};
pub use keys::KeyCache;
pub use magic::buffer::MagicBuffer as Buffer;
pub use magic::buffer::ZeroCopyBuf;
pub use magic::bytestring::ByteString;
pub use magic::detached_buffer::DetachedBuffer;
pub use magic::string_or_buffer::StringOrBuffer;

View file

@ -7,101 +7,101 @@ use std::sync::Mutex;
use super::transl8::FromV8;
use super::transl8::ToV8;
use super::zero_copy_buf::ZeroCopyBuf;
use super::v8slice::V8Slice;
use crate::magic::transl8::impl_magic;
// An asymmetric wrapper around ZeroCopyBuf,
// An asymmetric wrapper around V8Slice,
// allowing us to use a single type for familiarity
pub enum MagicBuffer {
FromV8(ZeroCopyBuf),
pub enum ZeroCopyBuf {
FromV8(V8Slice),
ToV8(Mutex<Option<Box<[u8]>>>),
// Variant of the MagicBuffer than is never exposed to the JS.
// Variant of the ZeroCopyBuf than is never exposed to the JS.
// Generally used to pass Vec<u8> backed buffers to resource methods.
Temp(Vec<u8>),
}
impl_magic!(MagicBuffer);
impl_magic!(ZeroCopyBuf);
impl Debug for MagicBuffer {
impl Debug for ZeroCopyBuf {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_list().entries(self.as_ref().iter()).finish()
}
}
impl MagicBuffer {
impl ZeroCopyBuf {
pub fn empty() -> Self {
MagicBuffer::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice())))
ZeroCopyBuf::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice())))
}
pub fn new_temp(vec: Vec<u8>) -> Self {
MagicBuffer::Temp(vec)
ZeroCopyBuf::Temp(vec)
}
// TODO(@littledivy): Temporary, this needs a refactor.
pub fn to_temp(self) -> Vec<u8> {
match self {
MagicBuffer::Temp(vec) => vec,
ZeroCopyBuf::Temp(vec) => vec,
_ => unreachable!(),
}
}
}
impl Clone for MagicBuffer {
impl Clone for ZeroCopyBuf {
fn clone(&self) -> Self {
match self {
Self::FromV8(zbuf) => Self::FromV8(zbuf.clone()),
Self::Temp(vec) => Self::Temp(vec.clone()),
Self::ToV8(_) => panic!("Don't Clone a MagicBuffer sent to v8"),
Self::ToV8(_) => panic!("Don't Clone a ZeroCopyBuf sent to v8"),
}
}
}
impl AsRef<[u8]> for MagicBuffer {
impl AsRef<[u8]> for ZeroCopyBuf {
fn as_ref(&self) -> &[u8] {
&*self
}
}
impl AsMut<[u8]> for MagicBuffer {
impl AsMut<[u8]> for ZeroCopyBuf {
fn as_mut(&mut self) -> &mut [u8] {
&mut *self
}
}
impl Deref for MagicBuffer {
impl Deref for ZeroCopyBuf {
type Target = [u8];
fn deref(&self) -> &[u8] {
match self {
Self::FromV8(buf) => &*buf,
Self::Temp(vec) => &*vec,
Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"),
Self::ToV8(_) => panic!("Don't Deref a ZeroCopyBuf sent to v8"),
}
}
}
impl DerefMut for MagicBuffer {
impl DerefMut for ZeroCopyBuf {
fn deref_mut(&mut self) -> &mut [u8] {
match self {
Self::FromV8(buf) => &mut *buf,
Self::Temp(vec) => &mut *vec,
Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"),
Self::ToV8(_) => panic!("Don't Deref a ZeroCopyBuf sent to v8"),
}
}
}
impl From<Box<[u8]>> for MagicBuffer {
impl From<Box<[u8]>> for ZeroCopyBuf {
fn from(buf: Box<[u8]>) -> Self {
MagicBuffer::ToV8(Mutex::new(Some(buf)))
ZeroCopyBuf::ToV8(Mutex::new(Some(buf)))
}
}
impl From<Vec<u8>> for MagicBuffer {
impl From<Vec<u8>> for ZeroCopyBuf {
fn from(vec: Vec<u8>) -> Self {
vec.into_boxed_slice().into()
}
}
impl ToV8 for MagicBuffer {
impl ToV8 for ZeroCopyBuf {
fn to_v8<'a>(
&self,
scope: &mut v8::HandleScope<'a>,
@ -112,7 +112,7 @@ impl ToV8 for MagicBuffer {
value.into()
}
Self::Temp(_) => unreachable!(),
Self::ToV8(x) => x.lock().unwrap().take().expect("MagicBuffer was empty"),
Self::ToV8(x) => x.lock().unwrap().take().expect("ZeroCopyBuf was empty"),
};
if buf.is_empty() {
@ -136,11 +136,11 @@ impl ToV8 for MagicBuffer {
}
}
impl FromV8 for MagicBuffer {
impl FromV8 for ZeroCopyBuf {
fn from_v8(
scope: &mut v8::HandleScope,
value: v8::Local<v8::Value>,
) -> Result<Self, crate::Error> {
Ok(Self::FromV8(ZeroCopyBuf::from_v8(scope, value)?))
Ok(Self::FromV8(V8Slice::from_v8(scope, value)?))
}
}

View file

@ -6,12 +6,12 @@ use std::ops::DerefMut;
use super::transl8::FromV8;
use super::transl8::ToV8;
use super::zero_copy_buf::to_ranged_buffer;
use super::zero_copy_buf::ZeroCopyBuf;
use super::v8slice::to_ranged_buffer;
use super::v8slice::V8Slice;
use crate::magic::transl8::impl_magic;
// A buffer that detaches when deserialized from JS
pub struct DetachedBuffer(ZeroCopyBuf);
pub struct DetachedBuffer(V8Slice);
impl_magic!(DetachedBuffer);
impl AsRef<[u8]> for DetachedBuffer {
@ -64,6 +64,6 @@ impl FromV8 for DetachedBuffer {
}
let store = b.get_backing_store();
b.detach(); // Detach
Ok(Self(ZeroCopyBuf { store, range }))
Ok(Self(V8Slice { store, range }))
}
}

View file

@ -5,6 +5,6 @@ pub mod detached_buffer;
pub mod string_or_buffer;
pub mod transl8;
pub mod u16string;
pub mod v8slice;
mod value;
pub mod zero_copy_buf;
pub use value::Value;

View file

@ -1,5 +1,5 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
use super::buffer::MagicBuffer;
use super::buffer::ZeroCopyBuf;
use super::transl8::{FromV8, ToV8};
use crate::magic::transl8::impl_magic;
use crate::Error;
@ -7,7 +7,7 @@ use std::ops::Deref;
#[derive(Debug)]
pub enum StringOrBuffer {
Buffer(MagicBuffer),
Buffer(ZeroCopyBuf),
String(String),
}
@ -40,7 +40,7 @@ impl FromV8 for StringOrBuffer {
scope: &mut v8::HandleScope,
value: v8::Local<v8::Value>,
) -> Result<Self, crate::Error> {
if let Ok(buf) = MagicBuffer::from_v8(scope, value) {
if let Ok(buf) = ZeroCopyBuf::from_v8(scope, value) {
return Ok(Self::Buffer(buf));
} else if let Ok(s) = crate::from_v8(scope, value) {
return Ok(Self::String(s));

View file

@ -6,26 +6,26 @@ use std::ops::Range;
use super::transl8::FromV8;
/// A ZeroCopyBuf encapsulates a slice that's been borrowed from a JavaScript
/// A V8Slice encapsulates a slice that's been borrowed from a JavaScript
/// ArrayBuffer object. JavaScript objects can normally be garbage collected,
/// but the existence of a ZeroCopyBuf inhibits this until it is dropped. It
/// but the existence of a V8Slice inhibits this until it is dropped. It
/// behaves much like an Arc<[u8]>.
///
/// # Cloning
/// Cloning a ZeroCopyBuf does not clone the contents of the buffer,
/// Cloning a V8Slice does not clone the contents of the buffer,
/// it creates a new reference to that buffer.
///
/// To actually clone the contents of the buffer do
/// `let copy = Vec::from(&*zero_copy_buf);`
#[derive(Clone)]
pub struct ZeroCopyBuf {
pub struct V8Slice {
pub(crate) store: v8::SharedRef<v8::BackingStore>,
pub(crate) range: Range<usize>,
}
unsafe impl Send for ZeroCopyBuf {}
unsafe impl Send for V8Slice {}
impl ZeroCopyBuf {
impl V8Slice {
pub fn from_buffer(
buffer: v8::Local<v8::ArrayBuffer>,
range: Range<usize>,
@ -68,7 +68,7 @@ pub(crate) fn to_ranged_buffer<'s>(
Ok((b, 0..b.byte_length()))
}
impl FromV8 for ZeroCopyBuf {
impl FromV8 for V8Slice {
fn from_v8(
scope: &mut v8::HandleScope,
value: v8::Local<v8::Value>,
@ -79,26 +79,26 @@ impl FromV8 for ZeroCopyBuf {
}
}
impl Deref for ZeroCopyBuf {
impl Deref for V8Slice {
type Target = [u8];
fn deref(&self) -> &[u8] {
self.as_slice()
}
}
impl DerefMut for ZeroCopyBuf {
impl DerefMut for V8Slice {
fn deref_mut(&mut self) -> &mut [u8] {
self.as_slice_mut()
}
}
impl AsRef<[u8]> for ZeroCopyBuf {
impl AsRef<[u8]> for V8Slice {
fn as_ref(&self) -> &[u8] {
self.as_slice()
}
}
impl AsMut<[u8]> for ZeroCopyBuf {
impl AsMut<[u8]> for V8Slice {
fn as_mut(&mut self) -> &mut [u8] {
self.as_slice_mut()
}

View file

@ -9,7 +9,7 @@ use crate::keys::v8_struct_key;
use crate::magic::transl8::MAGIC_FIELD;
use crate::magic::transl8::{opaque_deref, opaque_recv, MagicType, ToV8};
use crate::{
magic, Buffer, ByteString, DetachedBuffer, StringOrBuffer, U16String,
magic, ByteString, DetachedBuffer, StringOrBuffer, U16String, ZeroCopyBuf,
};
type JsValue<'s> = v8::Local<'s, v8::Value>;
@ -262,7 +262,7 @@ impl<'a, 'b, 'c, T: MagicType + ToV8> ser::SerializeStruct
// Dispatches between magic and regular struct serializers
pub enum StructSerializers<'a, 'b, 'c> {
Magic(MagicalSerializer<'a, 'b, 'c, magic::Value<'a>>),
MagicBuffer(MagicalSerializer<'a, 'b, 'c, Buffer>),
ZeroCopyBuf(MagicalSerializer<'a, 'b, 'c, ZeroCopyBuf>),
MagicDetached(MagicalSerializer<'a, 'b, 'c, DetachedBuffer>),
MagicByteString(MagicalSerializer<'a, 'b, 'c, ByteString>),
MagicU16String(MagicalSerializer<'a, 'b, 'c, U16String>),
@ -281,7 +281,7 @@ impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> {
) -> Result<()> {
match self {
StructSerializers::Magic(s) => s.serialize_field(key, value),
StructSerializers::MagicBuffer(s) => s.serialize_field(key, value),
StructSerializers::ZeroCopyBuf(s) => s.serialize_field(key, value),
StructSerializers::MagicDetached(s) => s.serialize_field(key, value),
StructSerializers::MagicByteString(s) => s.serialize_field(key, value),
StructSerializers::MagicU16String(s) => s.serialize_field(key, value),
@ -295,7 +295,7 @@ impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> {
fn end(self) -> JsResult<'a> {
match self {
StructSerializers::Magic(s) => s.end(),
StructSerializers::MagicBuffer(s) => s.end(),
StructSerializers::ZeroCopyBuf(s) => s.end(),
StructSerializers::MagicDetached(s) => s.end(),
StructSerializers::MagicByteString(s) => s.end(),
StructSerializers::MagicU16String(s) => s.end(),
@ -534,9 +534,9 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
let m = MagicalSerializer::<U16String>::new(self.scope);
Ok(StructSerializers::MagicU16String(m))
}
Buffer::MAGIC_NAME => {
let m = MagicalSerializer::<Buffer>::new(self.scope);
Ok(StructSerializers::MagicBuffer(m))
ZeroCopyBuf::MAGIC_NAME => {
let m = MagicalSerializer::<ZeroCopyBuf>::new(self.scope);
Ok(StructSerializers::ZeroCopyBuf(m))
}
DetachedBuffer::MAGIC_NAME => {
let m = MagicalSerializer::<DetachedBuffer>::new(self.scope);

View file

@ -2,9 +2,9 @@
use std::any::TypeId;
use std::mem::transmute_copy;
use crate::Buffer;
use crate::ByteString;
use crate::U16String;
use crate::ZeroCopyBuf;
/// Serializable exists to allow boxing values as "objects" to be serialized later,
/// this is particularly useful for async op-responses. This trait is a more efficient
@ -62,7 +62,7 @@ pub enum Primitive {
Float32(f32),
Float64(f64),
String(String),
Buffer(Buffer),
ZeroCopyBuf(ZeroCopyBuf),
ByteString(ByteString),
U16String(U16String),
}
@ -86,7 +86,7 @@ impl serde::Serialize for Primitive {
Self::Float32(x) => x.serialize(s),
Self::Float64(x) => x.serialize(s),
Self::String(x) => x.serialize(s),
Self::Buffer(x) => x.serialize(s),
Self::ZeroCopyBuf(x) => x.serialize(s),
Self::ByteString(x) => x.serialize(s),
Self::U16String(x) => x.serialize(s),
}
@ -129,8 +129,8 @@ impl<T: serde::Serialize + 'static> From<T> for SerializablePkg {
Self::Primitive(Primitive::Float64(tc(x)))
} else if tid == TypeId::of::<String>() {
Self::Primitive(Primitive::String(tc(x)))
} else if tid == TypeId::of::<Buffer>() {
Self::Primitive(Primitive::Buffer(tc(x)))
} else if tid == TypeId::of::<ZeroCopyBuf>() {
Self::Primitive(Primitive::ZeroCopyBuf(tc(x)))
} else if tid == TypeId::of::<ByteString>() {
Self::Primitive(Primitive::ByteString(tc(x)))
} else if tid == TypeId::of::<U16String>() {

View file

@ -4,7 +4,7 @@ use serde::Deserialize;
use serde_v8::utils::{js_exec, v8_do};
use serde_v8::ByteString;
use serde_v8::Error;
use serde_v8::{Buffer, U16String};
use serde_v8::{U16String, ZeroCopyBuf};
#[derive(Debug, Deserialize, PartialEq)]
struct MathOp {
@ -204,20 +204,20 @@ fn de_string_or_buffer() {
fn de_buffers() {
// ArrayBufferView
dedo("new Uint8Array([97])", |scope, v| {
let buf: Buffer = serde_v8::from_v8(scope, v).unwrap();
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[97]);
});
// ArrayBuffer
dedo("(new Uint8Array([97])).buffer", |scope, v| {
let buf: Buffer = serde_v8::from_v8(scope, v).unwrap();
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[97]);
});
dedo(
"(Uint8Array.from([0x68, 0x65, 0x6C, 0x6C, 0x6F]))",
|scope, v| {
let buf: Buffer = serde_v8::from_v8(scope, v).unwrap();
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[0x68, 0x65, 0x6C, 0x6C, 0x6F]);
},
);

View file

@ -66,26 +66,27 @@ fn magic_buffer() {
// Simple buffer
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let zbuf: serde_v8::Buffer = serde_v8::from_v8(scope, v8_array).unwrap();
let zbuf: serde_v8::ZeroCopyBuf =
serde_v8::from_v8(scope, v8_array).unwrap();
assert_eq!(&*zbuf, &[1, 2, 3, 4, 5]);
// Multi buffers
let v8_arrays =
js_exec(scope, "[new Uint8Array([1,2]), new Uint8Array([3,4,5])]");
let (z1, z2): (serde_v8::Buffer, serde_v8::Buffer) =
let (z1, z2): (serde_v8::ZeroCopyBuf, serde_v8::ZeroCopyBuf) =
serde_v8::from_v8(scope, v8_arrays).unwrap();
assert_eq!(&*z1, &[1, 2]);
assert_eq!(&*z2, &[3, 4, 5]);
// Wrapped in option, like our current op-ABI
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let zbuf: Option<serde_v8::Buffer> =
let zbuf: Option<serde_v8::ZeroCopyBuf> =
serde_v8::from_v8(scope, v8_array).unwrap();
assert_eq!(&*zbuf.unwrap(), &[1, 2, 3, 4, 5]);
// Observe mutation in JS
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let mut zbuf: serde_v8::Buffer =
let mut zbuf: serde_v8::ZeroCopyBuf =
serde_v8::from_v8(scope, v8_array).unwrap();
let key = serde_v8::to_v8(scope, "t1").unwrap();
global.set(scope, key, v8_array);
@ -96,12 +97,13 @@ fn magic_buffer() {
// Shared buffers
let v8_array =
js_exec(scope, "new Uint8Array(new SharedArrayBuffer([1,2,3,4,5]))");
let zbuf: Result<serde_v8::Buffer> = serde_v8::from_v8(scope, v8_array);
let zbuf: Result<serde_v8::ZeroCopyBuf> =
serde_v8::from_v8(scope, v8_array);
assert!(zbuf.is_err());
// Serialization
let buf: Vec<u8> = vec![1, 2, 3, 99, 5];
let zbuf: serde_v8::Buffer = buf.into();
let zbuf: serde_v8::ZeroCopyBuf = buf.into();
let v8_value = serde_v8::to_v8(scope, zbuf).unwrap();
let key = serde_v8::to_v8(scope, "t2").unwrap();
global.set(scope, key, v8_value);
@ -111,8 +113,8 @@ fn magic_buffer() {
// Composite Serialization
#[derive(serde::Serialize)]
struct Wrapper {
a: serde_v8::Buffer,
b: serde_v8::Buffer,
a: serde_v8::ZeroCopyBuf,
b: serde_v8::ZeroCopyBuf,
}
let buf1: Vec<u8> = vec![1, 2, 33, 4, 5];
let buf2: Vec<u8> = vec![5, 4, 3, 2, 11];