summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--serde_v8/src/de.rs33
-rw-r--r--serde_v8/src/error.rs1
-rw-r--r--serde_v8/src/magic/buffer.rs32
-rw-r--r--serde_v8/src/magic/zero_copy_buf.rs57
-rw-r--r--serde_v8/src/payload.rs3
-rw-r--r--serde_v8/tests/de.rs24
6 files changed, 110 insertions, 40 deletions
diff --git a/serde_v8/src/de.rs b/serde_v8/src/de.rs
index 69e618cb3..2deb5da39 100644
--- a/serde_v8/src/de.rs
+++ b/serde_v8/src/de.rs
@@ -134,9 +134,20 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
ValueType::ArrayBufferView => {
v8::Local::<v8::ArrayBufferView>::try_from(self.input)
.and_then(|view| {
- magic::zero_copy_buf::ZeroCopyBuf::try_new(self.scope, view)
+ magic::zero_copy_buf::ZeroCopyBuf::try_from((
+ &mut *self.scope,
+ view,
+ ))
})
- .map_err(|_| Error::ExpectedInteger)
+ .map_err(|_| Error::ExpectedBuffer)
+ .and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
+ }
+ ValueType::ArrayBuffer => {
+ v8::Local::<v8::ArrayBuffer>::try_from(self.input)
+ .and_then(|buffer| {
+ magic::zero_copy_buf::ZeroCopyBuf::try_from(buffer)
+ })
+ .map_err(|_| Error::ExpectedBuffer)
.and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
}
}
@@ -339,12 +350,20 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
// Magic Buffer
if name == magic::buffer::BUF_NAME {
- let zero_copy_buf =
- v8::Local::<v8::ArrayBufferView>::try_from(self.input)
+ let zero_copy_buf = match self.input.is_array_buffer() {
+ // ArrayBuffer
+ true => v8::Local::<v8::ArrayBuffer>::try_from(self.input)
+ .and_then(magic::zero_copy_buf::ZeroCopyBuf::try_from),
+ // maybe ArrayBufferView
+ false => v8::Local::<v8::ArrayBufferView>::try_from(self.input)
.and_then(|view| {
- magic::zero_copy_buf::ZeroCopyBuf::try_new(self.scope, view)
- })
- .map_err(|_| Error::ExpectedArray)?;
+ magic::zero_copy_buf::ZeroCopyBuf::try_from((
+ &mut *self.scope,
+ view,
+ ))
+ }),
+ }
+ .map_err(|_| Error::ExpectedBuffer)?;
let data: [u8; 32] = unsafe { std::mem::transmute(zero_copy_buf) };
return visitor.visit_bytes(&data);
}
diff --git a/serde_v8/src/error.rs b/serde_v8/src/error.rs
index 523dd62b0..6f4305536 100644
--- a/serde_v8/src/error.rs
+++ b/serde_v8/src/error.rs
@@ -16,6 +16,7 @@ pub enum Error {
ExpectedMap,
ExpectedEnum,
ExpectedObject,
+ ExpectedBuffer,
ExpectedUtf8,
diff --git a/serde_v8/src/magic/buffer.rs b/serde_v8/src/magic/buffer.rs
index 80f2f8bc7..e6f85324e 100644
--- a/serde_v8/src/magic/buffer.rs
+++ b/serde_v8/src/magic/buffer.rs
@@ -1,5 +1,6 @@
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+use std::convert::TryFrom;
use std::fmt;
use std::ops::Deref;
use std::ops::DerefMut;
@@ -15,22 +16,29 @@ pub enum MagicBuffer {
}
impl MagicBuffer {
- pub fn new<'s>(
- scope: &mut v8::HandleScope<'s>,
- view: v8::Local<v8::ArrayBufferView>,
- ) -> Self {
- Self::try_new(scope, view).unwrap()
+ pub fn empty() -> Self {
+ MagicBuffer::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice())))
}
+}
- pub fn try_new<'s>(
- scope: &mut v8::HandleScope<'s>,
- view: v8::Local<v8::ArrayBufferView>,
- ) -> Result<Self, v8::DataError> {
- Ok(Self::FromV8(ZeroCopyBuf::try_new(scope, view)?))
+impl<'s> TryFrom<v8::Local<'s, v8::ArrayBuffer>> for MagicBuffer {
+ type Error = v8::DataError;
+ fn try_from(buffer: v8::Local<v8::ArrayBuffer>) -> Result<Self, Self::Error> {
+ Ok(Self::FromV8(ZeroCopyBuf::try_from(buffer)?))
}
+}
- pub fn empty() -> Self {
- MagicBuffer::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice())))
+// TODO(@AaronO): consider streamlining this as "ScopedValue" ?
+type ScopedView<'a, 'b, 's> = (
+ &'s mut v8::HandleScope<'a>,
+ v8::Local<'b, v8::ArrayBufferView>,
+);
+impl<'a, 'b, 's> TryFrom<ScopedView<'a, 'b, 's>> for MagicBuffer {
+ type Error = v8::DataError;
+ fn try_from(
+ scoped_view: ScopedView<'a, 'b, 's>,
+ ) -> Result<Self, Self::Error> {
+ Ok(Self::FromV8(ZeroCopyBuf::try_from(scoped_view)?))
}
}
diff --git a/serde_v8/src/magic/zero_copy_buf.rs b/serde_v8/src/magic/zero_copy_buf.rs
index b536f5859..30acd8137 100644
--- a/serde_v8/src/magic/zero_copy_buf.rs
+++ b/serde_v8/src/magic/zero_copy_buf.rs
@@ -25,31 +25,46 @@ pub struct ZeroCopyBuf {
unsafe impl Send for ZeroCopyBuf {}
impl ZeroCopyBuf {
- pub fn new<'s>(
- scope: &mut v8::HandleScope<'s>,
- view: v8::Local<v8::ArrayBufferView>,
- ) -> Self {
- Self::try_new(scope, view).unwrap()
- }
-
- pub fn try_new<'s>(
- scope: &mut v8::HandleScope<'s>,
- view: v8::Local<v8::ArrayBufferView>,
+ pub fn from_buffer(
+ buffer: v8::Local<v8::ArrayBuffer>,
+ byte_offset: usize,
+ byte_length: usize,
) -> Result<Self, v8::DataError> {
- let backing_store = view.buffer(scope).unwrap().get_backing_store();
- if backing_store.is_shared() {
- return Err(v8::DataError::BadType {
+ let backing_store = buffer.get_backing_store();
+ match backing_store.is_shared() {
+ true => Err(v8::DataError::BadType {
actual: "shared ArrayBufferView",
expected: "non-shared ArrayBufferView",
- });
+ }),
+ false => Ok(Self {
+ backing_store,
+ byte_offset,
+ byte_length,
+ }),
}
- let byte_offset = view.byte_offset();
- let byte_length = view.byte_length();
- Ok(Self {
- backing_store,
- byte_offset,
- byte_length,
- })
+ }
+}
+
+impl<'s> TryFrom<v8::Local<'s, v8::ArrayBuffer>> for ZeroCopyBuf {
+ type Error = v8::DataError;
+ fn try_from(buffer: v8::Local<v8::ArrayBuffer>) -> Result<Self, Self::Error> {
+ Self::from_buffer(buffer, 0, buffer.byte_length())
+ }
+}
+
+// TODO(@AaronO): consider streamlining this as "ScopedValue" ?
+type ScopedView<'a, 'b, 's> = (
+ &'s mut v8::HandleScope<'a>,
+ v8::Local<'b, v8::ArrayBufferView>,
+);
+impl<'a, 'b, 's> TryFrom<ScopedView<'a, 'b, 's>> for ZeroCopyBuf {
+ type Error = v8::DataError;
+ fn try_from(
+ scoped_view: ScopedView<'a, 'b, 's>,
+ ) -> Result<Self, Self::Error> {
+ let (scope, view) = scoped_view;
+ let buffer = view.buffer(scope).unwrap();
+ Self::from_buffer(buffer, view.byte_offset(), view.byte_length())
}
}
diff --git a/serde_v8/src/payload.rs b/serde_v8/src/payload.rs
index 145066403..c9f3e85aa 100644
--- a/serde_v8/src/payload.rs
+++ b/serde_v8/src/payload.rs
@@ -11,6 +11,7 @@ pub enum ValueType {
Number,
String,
Array,
+ ArrayBuffer,
ArrayBufferView,
Object,
}
@@ -25,6 +26,8 @@ impl ValueType {
return Self::String;
} else if v.is_array() {
return Self::Array;
+ } else if v.is_array_buffer() {
+ return Self::ArrayBuffer;
} else if v.is_array_buffer_view() {
return Self::ArrayBufferView;
} else if v.is_object() {
diff --git a/serde_v8/tests/de.rs b/serde_v8/tests/de.rs
index 2b85d8839..1253ea92b 100644
--- a/serde_v8/tests/de.rs
+++ b/serde_v8/tests/de.rs
@@ -2,6 +2,7 @@
use serde::Deserialize;
use serde_v8::utils::{js_exec, v8_do};
+use serde_v8::Buffer;
use serde_v8::Error;
#[derive(Debug, Deserialize, PartialEq)]
@@ -192,6 +193,29 @@ fn de_string_or_buffer() {
);
}
+#[test]
+fn de_buffers() {
+ // ArrayBufferView
+ dedo("new Uint8Array([97])", |scope, v| {
+ let buf: Buffer = 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();
+ assert_eq!(&*buf, &[97]);
+ });
+
+ dedo(
+ "(Uint8Array.from([0x68, 0x65, 0x6C, 0x6C, 0x6F]))",
+ |scope, v| {
+ let buf: Buffer = serde_v8::from_v8(scope, v).unwrap();
+ assert_eq!(&*buf, &[0x68, 0x65, 0x6C, 0x6C, 0x6F]);
+ },
+ );
+}
+
////
// JSON tests: serde_json::Value compatibility
////