diff options
Diffstat (limited to 'serde_v8/src/magic')
-rw-r--r-- | serde_v8/src/magic/buffer.rs | 119 | ||||
-rw-r--r-- | serde_v8/src/magic/bytestring.rs | 122 | ||||
-rw-r--r-- | serde_v8/src/magic/mod.rs | 9 | ||||
-rw-r--r-- | serde_v8/src/magic/string_or_buffer.rs | 45 | ||||
-rw-r--r-- | serde_v8/src/magic/transl8.rs | 143 | ||||
-rw-r--r-- | serde_v8/src/magic/u16string.rs | 83 | ||||
-rw-r--r-- | serde_v8/src/magic/value.rs | 48 | ||||
-rw-r--r-- | serde_v8/src/magic/zero_copy_buf.rs | 136 |
8 files changed, 0 insertions, 705 deletions
diff --git a/serde_v8/src/magic/buffer.rs b/serde_v8/src/magic/buffer.rs deleted file mode 100644 index 484984ac5..000000000 --- a/serde_v8/src/magic/buffer.rs +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::ops::Deref; -use std::ops::DerefMut; -use std::sync::Mutex; - -use super::transl8::FromV8; -use super::transl8::ToV8; -use super::zero_copy_buf::ZeroCopyBuf; -use crate::magic::transl8::impl_magic; - -// An asymmetric wrapper around ZeroCopyBuf, -// allowing us to use a single type for familiarity -pub enum MagicBuffer { - FromV8(ZeroCopyBuf), - ToV8(Mutex<Option<Box<[u8]>>>), -} -impl_magic!(MagicBuffer); - -impl MagicBuffer { - pub fn empty() -> Self { - MagicBuffer::ToV8(Mutex::new(Some(vec![0_u8; 0].into_boxed_slice()))) - } -} - -impl Clone for MagicBuffer { - fn clone(&self) -> Self { - match self { - Self::FromV8(zbuf) => Self::FromV8(zbuf.clone()), - Self::ToV8(_) => panic!("Don't Clone a MagicBuffer sent to v8"), - } - } -} - -impl AsRef<[u8]> for MagicBuffer { - fn as_ref(&self) -> &[u8] { - &*self - } -} - -impl AsMut<[u8]> for MagicBuffer { - fn as_mut(&mut self) -> &mut [u8] { - &mut *self - } -} - -impl Deref for MagicBuffer { - type Target = [u8]; - fn deref(&self) -> &[u8] { - match self { - Self::FromV8(buf) => &*buf, - Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"), - } - } -} - -impl DerefMut for MagicBuffer { - fn deref_mut(&mut self) -> &mut [u8] { - match self { - Self::FromV8(buf) => &mut *buf, - Self::ToV8(_) => panic!("Don't Deref a MagicBuffer sent to v8"), - } - } -} - -impl From<Box<[u8]>> for MagicBuffer { - fn from(buf: Box<[u8]>) -> Self { - MagicBuffer::ToV8(Mutex::new(Some(buf))) - } -} - -impl From<Vec<u8>> for MagicBuffer { - fn from(vec: Vec<u8>) -> Self { - vec.into_boxed_slice().into() - } -} - -impl ToV8 for MagicBuffer { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let buf: Box<[u8]> = match self { - Self::FromV8(buf) => { - let value: &[u8] = buf; - value.into() - } - Self::ToV8(x) => x.lock().unwrap().take().expect("MagicBuffer was empty"), - }; - - if buf.is_empty() { - let ab = v8::ArrayBuffer::new(scope, 0); - return Ok( - v8::Uint8Array::new(scope, ab, 0, 0) - .expect("Failed to create Uint8Array") - .into(), - ); - } - let buf_len = buf.len(); - let backing_store = - v8::ArrayBuffer::new_backing_store_from_boxed_slice(buf); - let backing_store_shared = backing_store.make_shared(); - let ab = v8::ArrayBuffer::with_backing_store(scope, &backing_store_shared); - Ok( - v8::Uint8Array::new(scope, ab, 0, buf_len) - .expect("Failed to create Uint8Array") - .into(), - ) - } -} - -impl FromV8 for MagicBuffer { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - Ok(Self::FromV8(ZeroCopyBuf::from_v8(scope, value)?)) - } -} diff --git a/serde_v8/src/magic/bytestring.rs b/serde_v8/src/magic/bytestring.rs deleted file mode 100644 index 43ac54b97..000000000 --- a/serde_v8/src/magic/bytestring.rs +++ /dev/null @@ -1,122 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::ops::{Deref, DerefMut}; - -use super::transl8::{FromV8, ToV8}; -use crate::magic::transl8::impl_magic; -use crate::Error; - -#[derive(PartialEq, Eq, Clone, Debug)] -pub struct ByteString(pub Vec<u8>); -impl_magic!(ByteString); - -impl ByteString { - pub fn new() -> ByteString { - ByteString(Vec::new()) - } - - pub fn with_capacity(capacity: usize) -> ByteString { - ByteString(Vec::with_capacity(capacity)) - } - - pub fn capacity(&self) -> usize { - self.0.capacity() - } - - pub fn reserve(&mut self, additional: usize) { - self.0.reserve(additional) - } - - pub fn reserve_exact(&mut self, additional: usize) { - self.0.reserve_exact(additional) - } - - pub fn shrink_to_fit(&mut self) { - self.0.shrink_to_fit() - } - - pub fn truncate(&mut self, len: usize) { - self.0.truncate(len) - } - - pub fn push(&mut self, value: u8) { - self.0.push(value) - } - - pub fn pop(&mut self) -> Option<u8> { - self.0.pop() - } -} - -impl Default for ByteString { - fn default() -> Self { - ByteString::new() - } -} - -impl Deref for ByteString { - type Target = [u8]; - - fn deref(&self) -> &[u8] { - self.0.deref() - } -} - -impl DerefMut for ByteString { - fn deref_mut(&mut self) -> &mut [u8] { - self.0.deref_mut() - } -} - -impl AsRef<[u8]> for ByteString { - fn as_ref(&self) -> &[u8] { - self.0.as_ref() - } -} - -impl AsMut<[u8]> for ByteString { - fn as_mut(&mut self) -> &mut [u8] { - self.0.as_mut() - } -} - -impl ToV8 for ByteString { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let v = - v8::String::new_from_one_byte(scope, self, v8::NewStringType::Normal) - .unwrap(); - Ok(v.into()) - } -} - -impl FromV8 for ByteString { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; - if !v8str.contains_only_onebyte() { - return Err(Error::ExpectedLatin1); - } - let len = v8str.length(); - let mut buffer = Vec::with_capacity(len); - // SAFETY: we set length == capacity (see previous line), - // before immediately writing into that buffer and sanity check with an assert - #[allow(clippy::uninit_vec)] - unsafe { - buffer.set_len(len); - let written = v8str.write_one_byte( - scope, - &mut buffer, - 0, - v8::WriteOptions::NO_NULL_TERMINATION, - ); - assert!(written == len); - } - Ok(ByteString(buffer)) - } -} diff --git a/serde_v8/src/magic/mod.rs b/serde_v8/src/magic/mod.rs deleted file mode 100644 index bc86c6a7c..000000000 --- a/serde_v8/src/magic/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. -pub mod buffer; -pub mod bytestring; -pub mod string_or_buffer; -pub mod transl8; -pub mod u16string; -mod value; -pub mod zero_copy_buf; -pub use value::Value; diff --git a/serde_v8/src/magic/string_or_buffer.rs b/serde_v8/src/magic/string_or_buffer.rs deleted file mode 100644 index edde2adcd..000000000 --- a/serde_v8/src/magic/string_or_buffer.rs +++ /dev/null @@ -1,45 +0,0 @@ -use std::ops::Deref; - -#[derive(Debug)] -pub struct StringOrBuffer(Vec<u8>); - -impl Deref for StringOrBuffer { - type Target = Vec<u8>; - fn deref(&self) -> &Vec<u8> { - &self.0 - } -} - -impl StringOrBuffer { - pub fn into_bytes(self) -> Vec<u8> { - self.0 - } -} - -impl<'de> serde::Deserialize<'de> for StringOrBuffer { - fn deserialize<D>(deserializer: D) -> Result<StringOrBuffer, D::Error> - where - D: serde::Deserializer<'de>, - { - StringOrBufferInner::deserialize(deserializer) - .map(|x| StringOrBuffer(x.into_bytes())) - } -} - -// TODO(@AaronO): explore if we can make this work with ZeroCopyBuf -#[derive(serde::Deserialize)] -#[serde(untagged)] -enum StringOrBufferInner { - #[serde(with = "serde_bytes")] - Buffer(Vec<u8>), - String(String), -} - -impl StringOrBufferInner { - fn into_bytes(self) -> Vec<u8> { - match self { - Self::String(s) => s.into_bytes(), - Self::Buffer(b) => b, - } - } -} diff --git a/serde_v8/src/magic/transl8.rs b/serde_v8/src/magic/transl8.rs deleted file mode 100644 index 458b82129..000000000 --- a/serde_v8/src/magic/transl8.rs +++ /dev/null @@ -1,143 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -//! Transerialization extends the set of serde-compatible types (for given de/serializers). -//! By "hackishly" transmuting references across serde boundaries as u64s. -//! Type-safety is enforced using special struct names for each "magic type". -//! Memory-safety relies on transerialized values being "pinned" during de/serialization. - -pub(crate) const MAGIC_FIELD: &str = "$__v8_magic_field"; - -pub(crate) trait MagicType { - const NAME: &'static str; - const MAGIC_NAME: &'static str; -} - -pub(crate) trait ToV8 { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error>; -} - -pub(crate) trait FromV8: Sized { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error>; -} - -pub(crate) fn magic_serialize<T, S>( - serializer: S, - x: &T, -) -> Result<S::Ok, S::Error> -where - S: serde::Serializer, - T: MagicType, -{ - use serde::ser::SerializeStruct; - - let mut s = serializer.serialize_struct(T::MAGIC_NAME, 1)?; - let ptr = opaque_send(x); - s.serialize_field(MAGIC_FIELD, &ptr)?; - s.end() -} - -pub(crate) fn magic_deserialize<'de, T, D>( - deserializer: D, -) -> Result<T, D::Error> -where - D: serde::Deserializer<'de>, - T: MagicType, -{ - struct ValueVisitor<T> { - p1: std::marker::PhantomData<T>, - } - - impl<'de, T: MagicType> serde::de::Visitor<'de> for ValueVisitor<T> { - type Value = T; - - fn expecting( - &self, - formatter: &mut std::fmt::Formatter, - ) -> std::fmt::Result { - formatter.write_str("a ")?; - formatter.write_str(T::NAME) - } - - fn visit_u64<E>(self, ptr: u64) -> Result<Self::Value, E> - where - E: serde::de::Error, - { - // SAFETY: opaque ptr originates from visit_magic, which forgets ownership so we can take it - Ok(unsafe { opaque_take(ptr) }) - } - } - - deserializer.deserialize_struct( - T::MAGIC_NAME, - &[MAGIC_FIELD], - ValueVisitor::<T> { - p1: std::marker::PhantomData, - }, - ) -} - -pub(crate) fn visit_magic<'de, T, V, E>(visitor: V, x: T) -> Result<V::Value, E> -where - V: serde::de::Visitor<'de>, - E: serde::de::Error, -{ - let y = visitor.visit_u64::<E>(opaque_send(&x)); - std::mem::forget(x); - y -} - -/// Constructs an "opaque" ptr from a reference to transerialize -pub(crate) fn opaque_send<T: Sized>(x: &T) -> u64 { - (x as *const T) as u64 -} - -/// Copies an "opaque" ptr from a reference to an opaque ptr (transerialized) -/// NOTE: ptr-to-ptr, extra indirection -pub(crate) unsafe fn opaque_recv<T: ?Sized>(ptr: &T) -> u64 { - *(ptr as *const T as *const u64) -} - -/// Transmutes an "opaque" ptr back into a reference -pub(crate) unsafe fn opaque_deref<'a, T>(ptr: u64) -> &'a T { - std::mem::transmute(ptr) -} - -/// Transmutes & copies the value from the "opaque" ptr -/// NOTE: takes ownership & requires other end to forget its ownership -pub(crate) unsafe fn opaque_take<T>(ptr: u64) -> T { - std::mem::transmute_copy::<T, T>(std::mem::transmute(ptr)) -} - -macro_rules! impl_magic { - ($t:ty) => { - impl crate::magic::transl8::MagicType for $t { - const NAME: &'static str = stringify!($t); - const MAGIC_NAME: &'static str = concat!("$__v8_magic_", stringify!($t)); - } - - impl serde::Serialize for $t { - fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> - where - S: serde::Serializer, - { - crate::magic::transl8::magic_serialize(serializer, self) - } - } - - impl<'de> serde::Deserialize<'de> for $t { - fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> - where - D: serde::Deserializer<'de>, - { - crate::magic::transl8::magic_deserialize(deserializer) - } - } - }; -} -pub(crate) use impl_magic; diff --git a/serde_v8/src/magic/u16string.rs b/serde_v8/src/magic/u16string.rs deleted file mode 100644 index 39ebf88d9..000000000 --- a/serde_v8/src/magic/u16string.rs +++ /dev/null @@ -1,83 +0,0 @@ -use crate::magic::transl8::impl_magic; -use crate::Error; -use std::ops::{Deref, DerefMut}; - -use super::transl8::{FromV8, ToV8}; - -#[derive(Default, PartialEq, Eq, Debug)] -pub struct U16String(pub Vec<u16>); -impl_magic!(U16String); - -impl U16String { - pub fn with_zeroes(length: usize) -> U16String { - U16String(vec![0u16; length]) - } - - pub fn truncate(&mut self, new_length: usize) { - self.0.truncate(new_length); - self.0.shrink_to_fit() - } -} - -impl Deref for U16String { - type Target = [u16]; - fn deref(&self) -> &[u16] { - self.0.deref() - } -} - -impl DerefMut for U16String { - fn deref_mut(&mut self) -> &mut [u16] { - self.0.deref_mut() - } -} - -impl AsRef<[u16]> for U16String { - fn as_ref(&self) -> &[u16] { - self.0.as_ref() - } -} - -impl AsMut<[u16]> for U16String { - fn as_mut(&mut self) -> &mut [u16] { - self.0.as_mut() - } -} - -impl ToV8 for U16String { - fn to_v8<'a>( - &self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - let v = - v8::String::new_from_two_byte(scope, self, v8::NewStringType::Normal) - .unwrap(); - Ok(v.into()) - } -} - -impl FromV8 for U16String { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - let v8str = v8::Local::<v8::String>::try_from(value) - .map_err(|_| Error::ExpectedString)?; - let len = v8str.length(); - let mut buffer = Vec::with_capacity(len); - // SAFETY: we set length == capacity (see previous line), - // before immediately writing into that buffer and sanity check with an assert - #[allow(clippy::uninit_vec)] - unsafe { - buffer.set_len(len); - let written = v8str.write( - scope, - &mut buffer, - 0, - v8::WriteOptions::NO_NULL_TERMINATION, - ); - assert!(written == len); - } - Ok(U16String(buffer)) - } -} diff --git a/serde_v8/src/magic/value.rs b/serde_v8/src/magic/value.rs deleted file mode 100644 index 5d844fbda..000000000 --- a/serde_v8/src/magic/value.rs +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use crate::magic::transl8::impl_magic; -use crate::magic::transl8::FromV8; -use crate::magic::transl8::ToV8; -use std::mem::transmute; - -/// serde_v8::Value allows passing through `v8::Value`s untouched -/// when de/serializing & allows mixing rust & v8 values in structs, tuples... -// -// SAFETY: caveat emptor, the rust-compiler can no longer link lifetimes to their -// original scope, you must take special care in ensuring your handles don't outlive their scope -pub struct Value<'s> { - pub v8_value: v8::Local<'s, v8::Value>, -} -impl_magic!(Value<'_>); - -impl<'s> From<v8::Local<'s, v8::Value>> for Value<'s> { - fn from(v8_value: v8::Local<'s, v8::Value>) -> Self { - Self { v8_value } - } -} - -impl<'s> From<Value<'s>> for v8::Local<'s, v8::Value> { - fn from(v: Value<'s>) -> Self { - v.v8_value - } -} - -impl ToV8 for Value<'_> { - fn to_v8<'a>( - &self, - _scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - // SAFETY: not fully safe, since lifetimes are detached from original scope - Ok(unsafe { transmute(self.v8_value) }) - } -} - -impl FromV8 for Value<'_> { - fn from_v8( - _scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - // SAFETY: not fully safe, since lifetimes are detached from original scope - Ok(unsafe { transmute::<Value, Value>(value.into()) }) - } -} diff --git a/serde_v8/src/magic/zero_copy_buf.rs b/serde_v8/src/magic/zero_copy_buf.rs deleted file mode 100644 index c63d4ba66..000000000 --- a/serde_v8/src/magic/zero_copy_buf.rs +++ /dev/null @@ -1,136 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::cell::Cell; -use std::ops::Deref; -use std::ops::DerefMut; - -use super::transl8::FromV8; - -/// A ZeroCopyBuf 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 -/// behaves much like an Arc<[u8]>. -/// -/// # Cloning -/// Cloning a ZeroCopyBuf 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 { - backing_store: v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -} - -unsafe impl Send for ZeroCopyBuf {} - -impl ZeroCopyBuf { - pub fn from_buffer( - buffer: v8::Local<v8::ArrayBuffer>, - byte_offset: usize, - byte_length: usize, - ) -> Result<Self, v8::DataError> { - 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, - }), - } - } - - pub fn from_view( - scope: &mut v8::HandleScope, - view: v8::Local<v8::ArrayBufferView>, - ) -> Result<Self, v8::DataError> { - let buffer = view.buffer(scope).ok_or(v8::DataError::NoData { - expected: "view to have a buffer", - })?; - Self::from_buffer(buffer, view.byte_offset(), view.byte_length()) - } -} - -impl FromV8 for ZeroCopyBuf { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - if value.is_array_buffer() { - value - .try_into() - .and_then(|b| Self::from_buffer(b, 0, b.byte_length())) - } else { - value - .try_into() - .and_then(|view| Self::from_view(scope, view)) - } - .map_err(|_| crate::Error::ExpectedBuffer) - } -} - -impl Deref for ZeroCopyBuf { - type Target = [u8]; - fn deref(&self) -> &[u8] { - unsafe { - get_backing_store_slice( - &self.backing_store, - self.byte_offset, - self.byte_length, - ) - } - } -} - -impl DerefMut for ZeroCopyBuf { - fn deref_mut(&mut self) -> &mut [u8] { - unsafe { - get_backing_store_slice_mut( - &self.backing_store, - self.byte_offset, - self.byte_length, - ) - } - } -} - -impl AsRef<[u8]> for ZeroCopyBuf { - fn as_ref(&self) -> &[u8] { - &*self - } -} - -impl AsMut<[u8]> for ZeroCopyBuf { - fn as_mut(&mut self) -> &mut [u8] { - &mut *self - } -} - -unsafe fn get_backing_store_slice( - backing_store: &v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -) -> &[u8] { - let cells: *const [Cell<u8>] = - &backing_store[byte_offset..byte_offset + byte_length]; - let bytes = cells as *const [u8]; - &*bytes -} - -#[allow(clippy::mut_from_ref)] -unsafe fn get_backing_store_slice_mut( - backing_store: &v8::SharedRef<v8::BackingStore>, - byte_offset: usize, - byte_length: usize, -) -> &mut [u8] { - let cells: *const [Cell<u8>] = - &backing_store[byte_offset..byte_offset + byte_length]; - let bytes = cells as *const _ as *mut [u8]; - &mut *bytes -} |