summaryrefslogtreecommitdiff
path: root/serde_v8/src/magic
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/src/magic')
-rw-r--r--serde_v8/src/magic/buffer.rs119
-rw-r--r--serde_v8/src/magic/bytestring.rs122
-rw-r--r--serde_v8/src/magic/mod.rs9
-rw-r--r--serde_v8/src/magic/string_or_buffer.rs45
-rw-r--r--serde_v8/src/magic/transl8.rs143
-rw-r--r--serde_v8/src/magic/u16string.rs83
-rw-r--r--serde_v8/src/magic/value.rs48
-rw-r--r--serde_v8/src/magic/zero_copy_buf.rs136
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
-}