summaryrefslogtreecommitdiff
path: root/serde_v8/magic
diff options
context:
space:
mode:
Diffstat (limited to 'serde_v8/magic')
-rw-r--r--serde_v8/magic/any_value.rs68
-rw-r--r--serde_v8/magic/bigint.rs77
-rw-r--r--serde_v8/magic/buffer.rs119
-rw-r--r--serde_v8/magic/bytestring.rs109
-rw-r--r--serde_v8/magic/detached_buffer.rs70
-rw-r--r--serde_v8/magic/external_pointer.rs58
-rw-r--r--serde_v8/magic/global.rs41
-rw-r--r--serde_v8/magic/mod.rs17
-rw-r--r--serde_v8/magic/rawbytes.rs122
-rw-r--r--serde_v8/magic/string_or_buffer.rs58
-rw-r--r--serde_v8/magic/transl8.rs165
-rw-r--r--serde_v8/magic/u16string.rs59
-rw-r--r--serde_v8/magic/v8slice.rs181
-rw-r--r--serde_v8/magic/value.rs48
14 files changed, 0 insertions, 1192 deletions
diff --git a/serde_v8/magic/any_value.rs b/serde_v8/magic/any_value.rs
deleted file mode 100644
index df85f90d8..000000000
--- a/serde_v8/magic/any_value.rs
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use super::buffer::JsBuffer;
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-use crate::magic::transl8::impl_magic;
-use crate::Error;
-use crate::ToJsBuffer;
-use num_bigint::BigInt;
-
-/// An untagged enum type that can be any of number, string, bool, bigint, or
-/// buffer.
-#[derive(Debug)]
-pub enum AnyValue {
- RustBuffer(ToJsBuffer),
- V8Buffer(JsBuffer),
- String(String),
- Number(f64),
- BigInt(BigInt),
- Bool(bool),
-}
-
-impl_magic!(AnyValue);
-
-impl ToV8 for AnyValue {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- match self {
- Self::RustBuffer(buf) => crate::to_v8(scope, buf),
- Self::V8Buffer(_) => unreachable!(),
- Self::String(s) => crate::to_v8(scope, s),
- Self::Number(num) => crate::to_v8(scope, num),
- Self::BigInt(bigint) => {
- crate::to_v8(scope, crate::BigInt::from(bigint.clone()))
- }
- Self::Bool(b) => crate::to_v8(scope, b),
- }
- }
-}
-
-impl FromV8 for AnyValue {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- if value.is_string() {
- let string = crate::from_v8(scope, value)?;
- Ok(AnyValue::String(string))
- } else if value.is_number() {
- let string = crate::from_v8(scope, value)?;
- Ok(AnyValue::Number(string))
- } else if value.is_big_int() {
- let bigint = crate::BigInt::from_v8(scope, value)?;
- Ok(AnyValue::BigInt(bigint.into()))
- } else if value.is_array_buffer_view() {
- let buf = JsBuffer::from_v8(scope, value)?;
- Ok(AnyValue::V8Buffer(buf))
- } else if value.is_boolean() {
- let string = crate::from_v8(scope, value)?;
- Ok(AnyValue::Bool(string))
- } else {
- Err(Error::Message(
- "expected string, number, bigint, ArrayBufferView, boolean".into(),
- ))
- }
- }
-}
diff --git a/serde_v8/magic/bigint.rs b/serde_v8/magic/bigint.rs
deleted file mode 100644
index 330803daf..000000000
--- a/serde_v8/magic/bigint.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use smallvec::smallvec;
-use smallvec::SmallVec;
-
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-use crate::error::value_to_type_str;
-use crate::magic::transl8::impl_magic;
-use crate::Error;
-
-#[derive(
- PartialEq,
- Eq,
- Clone,
- Debug,
- Default,
- derive_more::Deref,
- derive_more::DerefMut,
- derive_more::AsRef,
- derive_more::AsMut,
-)]
-#[as_mut(forward)]
-#[as_ref(forward)]
-pub struct BigInt(num_bigint::BigInt);
-impl_magic!(BigInt);
-
-impl ToV8 for BigInt {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- let (sign, words) = self.0.to_u64_digits();
- let sign_bit = sign == num_bigint::Sign::Minus;
- let v = v8::BigInt::new_from_words(scope, sign_bit, &words).unwrap();
- Ok(v.into())
- }
-}
-
-impl FromV8 for BigInt {
- fn from_v8(
- _scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- let v8bigint = v8::Local::<v8::BigInt>::try_from(value)
- .map_err(|_| Error::ExpectedBigInt(value_to_type_str(value)))?;
- let word_count = v8bigint.word_count();
- let mut words: SmallVec<[u64; 1]> = smallvec![0u64; word_count];
- let (sign_bit, _words) = v8bigint.to_words_array(&mut words);
- let sign = match sign_bit {
- true => num_bigint::Sign::Minus,
- false => num_bigint::Sign::Plus,
- };
- // SAFETY: Because the alignment of u64 is 8, the alignment of u32 is 4, and
- // the size of u64 is 8, the size of u32 is 4, the alignment of u32 is a
- // factor of the alignment of u64, and the size of u32 is a factor of the
- // size of u64, we can safely transmute the slice of u64 to a slice of u32.
- let (prefix, slice, suffix) = unsafe { words.align_to::<u32>() };
- assert!(prefix.is_empty());
- assert!(suffix.is_empty());
- assert_eq!(slice.len(), words.len() * 2);
- let big_int = num_bigint::BigInt::from_slice(sign, slice);
- Ok(Self(big_int))
- }
-}
-
-impl From<num_bigint::BigInt> for BigInt {
- fn from(big_int: num_bigint::BigInt) -> Self {
- Self(big_int)
- }
-}
-
-impl From<BigInt> for num_bigint::BigInt {
- fn from(big_int: BigInt) -> Self {
- big_int.0
- }
-}
diff --git a/serde_v8/magic/buffer.rs b/serde_v8/magic/buffer.rs
deleted file mode 100644
index 032a3be33..000000000
--- a/serde_v8/magic/buffer.rs
+++ /dev/null
@@ -1,119 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use std::fmt::Debug;
-use std::ops::Deref;
-use std::ops::DerefMut;
-
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-use super::v8slice::V8Slice;
-use crate::magic::transl8::impl_magic;
-
-pub struct JsBuffer(V8Slice);
-
-impl_magic!(JsBuffer);
-
-impl Debug for JsBuffer {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.debug_list().entries(self.0.as_ref().iter()).finish()
- }
-}
-
-impl Clone for JsBuffer {
- fn clone(&self) -> Self {
- Self(self.0.clone())
- }
-}
-
-impl AsRef<[u8]> for JsBuffer {
- fn as_ref(&self) -> &[u8] {
- &self.0
- }
-}
-
-impl AsMut<[u8]> for JsBuffer {
- fn as_mut(&mut self) -> &mut [u8] {
- &mut self.0
- }
-}
-
-impl Deref for JsBuffer {
- type Target = [u8];
- fn deref(&self) -> &[u8] {
- &self.0
- }
-}
-
-impl DerefMut for JsBuffer {
- fn deref_mut(&mut self) -> &mut [u8] {
- &mut self.0
- }
-}
-
-impl FromV8 for JsBuffer {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- Ok(Self(V8Slice::from_v8(scope, value)?))
- }
-}
-
-impl From<JsBuffer> for bytes::Bytes {
- fn from(zbuf: JsBuffer) -> bytes::Bytes {
- zbuf.0.into()
- }
-}
-
-// NOTE(bartlomieju): we use Option here, because `to_v8()` uses `&mut self`
-// instead of `self` which is dictated by the `serde` API.
-#[derive(Debug)]
-pub struct ToJsBuffer(Option<Box<[u8]>>);
-
-impl_magic!(ToJsBuffer);
-
-impl ToJsBuffer {
- pub fn empty() -> Self {
- ToJsBuffer(Some(vec![0_u8; 0].into_boxed_slice()))
- }
-}
-
-impl From<Box<[u8]>> for ToJsBuffer {
- fn from(buf: Box<[u8]>) -> Self {
- ToJsBuffer(Some(buf))
- }
-}
-
-impl From<Vec<u8>> for ToJsBuffer {
- fn from(vec: Vec<u8>) -> Self {
- vec.into_boxed_slice().into()
- }
-}
-
-impl ToV8 for ToJsBuffer {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- let buf: Box<[u8]> = self.0.take().expect("RustToV8Buf 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: usize = 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(),
- )
- }
-}
diff --git a/serde_v8/magic/bytestring.rs b/serde_v8/magic/bytestring.rs
deleted file mode 100644
index 3baa704e5..000000000
--- a/serde_v8/magic/bytestring.rs
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-use crate::error::value_to_type_str;
-use crate::magic::transl8::impl_magic;
-use crate::Error;
-use smallvec::SmallVec;
-use std::mem::size_of;
-
-const USIZE2X: usize = size_of::<usize>() * 2;
-
-#[derive(
- PartialEq,
- Eq,
- Clone,
- Debug,
- Default,
- derive_more::Deref,
- derive_more::DerefMut,
- derive_more::AsRef,
- derive_more::AsMut,
-)]
-#[as_mut(forward)]
-#[as_ref(forward)]
-pub struct ByteString(SmallVec<[u8; USIZE2X]>);
-impl_magic!(ByteString);
-
-// const-assert that Vec<u8> and SmallVec<[u8; size_of::<usize>() * 2]> have a same size.
-// Note from https://docs.rs/smallvec/latest/smallvec/#union -
-// smallvec can still be larger than Vec if the inline buffer is
-// larger than two machine words.
-const _: () =
- assert!(size_of::<Vec<u8>>() == size_of::<SmallVec<[u8; USIZE2X]>>());
-
-impl ToV8 for ByteString {
- fn to_v8<'a>(
- &mut 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(value_to_type_str(value)))?;
- if !v8str.contains_only_onebyte() {
- return Err(Error::ExpectedLatin1);
- }
- let len = v8str.length();
- let mut buffer = SmallVec::with_capacity(len);
- #[allow(clippy::uninit_vec)]
- // SAFETY: we set length == capacity (see previous line),
- // before immediately writing into that buffer and sanity check with an assert
- unsafe {
- buffer.set_len(len);
- let written = v8str.write_one_byte(
- scope,
- &mut buffer,
- 0,
- v8::WriteOptions::NO_NULL_TERMINATION,
- );
- assert!(written == len);
- }
- Ok(Self(buffer))
- }
-}
-
-// smallvec does not impl From/Into traits
-// like Vec<u8> does. So here we are.
-
-impl From<Vec<u8>> for ByteString {
- fn from(vec: Vec<u8>) -> Self {
- ByteString(SmallVec::from_vec(vec))
- }
-}
-
-#[allow(clippy::from_over_into)]
-impl Into<Vec<u8>> for ByteString {
- fn into(self) -> Vec<u8> {
- self.0.into_vec()
- }
-}
-
-impl From<&[u8]> for ByteString {
- fn from(s: &[u8]) -> Self {
- ByteString(SmallVec::from_slice(s))
- }
-}
-
-impl From<&str> for ByteString {
- fn from(s: &str) -> Self {
- let v: Vec<u8> = s.into();
- ByteString::from(v)
- }
-}
-
-impl From<String> for ByteString {
- fn from(s: String) -> Self {
- ByteString::from(s.into_bytes())
- }
-}
diff --git a/serde_v8/magic/detached_buffer.rs b/serde_v8/magic/detached_buffer.rs
deleted file mode 100644
index bc4b3de67..000000000
--- a/serde_v8/magic/detached_buffer.rs
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use core::ops::Range;
-use std::ops::Deref;
-use std::ops::DerefMut;
-
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-use super::v8slice::to_ranged_buffer;
-use super::v8slice::V8Slice;
-use crate::error::value_to_type_str;
-use crate::magic::transl8::impl_magic;
-
-// A buffer that detaches when deserialized from JS
-pub struct DetachedBuffer(V8Slice);
-impl_magic!(DetachedBuffer);
-
-impl AsRef<[u8]> for DetachedBuffer {
- fn as_ref(&self) -> &[u8] {
- self.0.as_ref()
- }
-}
-
-impl AsMut<[u8]> for DetachedBuffer {
- fn as_mut(&mut self) -> &mut [u8] {
- self.0.as_mut()
- }
-}
-
-impl Deref for DetachedBuffer {
- type Target = [u8];
- fn deref(&self) -> &[u8] {
- self.0.deref()
- }
-}
-
-impl DerefMut for DetachedBuffer {
- fn deref_mut(&mut self) -> &mut [u8] {
- self.0.deref_mut()
- }
-}
-
-impl ToV8 for DetachedBuffer {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- let buffer = v8::ArrayBuffer::with_backing_store(scope, &self.0.store);
- let Range { start, end } = self.0.range;
- let (off, len) = (start, end - start);
- let v = v8::Uint8Array::new(scope, buffer, off, len).unwrap();
- Ok(v.into())
- }
-}
-
-impl FromV8 for DetachedBuffer {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- let (b, range) = to_ranged_buffer(scope, value)
- .map_err(|_| crate::Error::ExpectedBuffer(value_to_type_str(value)))?;
- if !b.is_detachable() {
- return Err(crate::Error::ExpectedDetachable(value_to_type_str(value)));
- }
- let store = b.get_backing_store();
- b.detach(None); // Detach
- Ok(Self(V8Slice { store, range }))
- }
-}
diff --git a/serde_v8/magic/external_pointer.rs b/serde_v8/magic/external_pointer.rs
deleted file mode 100644
index e22e41a01..000000000
--- a/serde_v8/magic/external_pointer.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use std::ffi::c_void;
-
-use crate::error::value_to_type_str;
-
-use super::transl8::impl_magic;
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-
-pub struct ExternalPointer(*mut c_void);
-
-// SAFETY: Nonblocking FFI is user controller and we must trust user to have it right.
-unsafe impl Send for ExternalPointer {}
-// SAFETY: Nonblocking FFI is user controller and we must trust user to have it right.
-unsafe impl Sync for ExternalPointer {}
-
-impl_magic!(ExternalPointer);
-
-impl ToV8 for ExternalPointer {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- if self.0.is_null() {
- Ok(v8::null(scope).into())
- } else {
- Ok(v8::External::new(scope, self.0).into())
- }
- }
-}
-
-impl FromV8 for ExternalPointer {
- fn from_v8(
- _scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- if value.is_null() {
- Ok(ExternalPointer(std::ptr::null_mut()))
- } else if let Ok(external) = v8::Local::<v8::External>::try_from(value) {
- Ok(ExternalPointer(external.value()))
- } else {
- Err(crate::Error::ExpectedExternal(value_to_type_str(value)))
- }
- }
-}
-
-impl From<*mut c_void> for ExternalPointer {
- fn from(value: *mut c_void) -> Self {
- ExternalPointer(value)
- }
-}
-
-impl From<*const c_void> for ExternalPointer {
- fn from(value: *const c_void) -> Self {
- ExternalPointer(value as *mut c_void)
- }
-}
diff --git a/serde_v8/magic/global.rs b/serde_v8/magic/global.rs
deleted file mode 100644
index 52b316fa5..000000000
--- a/serde_v8/magic/global.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use crate::magic::transl8::impl_magic;
-use crate::magic::transl8::FromV8;
-use crate::magic::transl8::ToV8;
-
-pub struct Global {
- pub v8_value: v8::Global<v8::Value>,
-}
-impl_magic!(Global);
-
-impl From<v8::Global<v8::Value>> for Global {
- fn from(v8_value: v8::Global<v8::Value>) -> Self {
- Self { v8_value }
- }
-}
-
-impl From<Global> for v8::Global<v8::Value> {
- fn from(v: Global) -> Self {
- v.v8_value
- }
-}
-
-impl ToV8 for Global {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- Ok(v8::Local::new(scope, self.v8_value.clone()))
- }
-}
-
-impl FromV8 for Global {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- let global = v8::Global::new(scope, value);
- Ok(global.into())
- }
-}
diff --git a/serde_v8/magic/mod.rs b/serde_v8/magic/mod.rs
deleted file mode 100644
index 3e984527d..000000000
--- a/serde_v8/magic/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-pub mod any_value;
-pub mod bigint;
-pub mod buffer;
-pub mod bytestring;
-pub mod detached_buffer;
-mod external_pointer;
-mod global;
-pub(super) mod rawbytes;
-pub mod string_or_buffer;
-pub mod transl8;
-pub mod u16string;
-pub mod v8slice;
-mod value;
-pub use external_pointer::ExternalPointer;
-pub use global::Global;
-pub use value::Value;
diff --git a/serde_v8/magic/rawbytes.rs b/serde_v8/magic/rawbytes.rs
deleted file mode 100644
index 2703c7756..000000000
--- a/serde_v8/magic/rawbytes.rs
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-pub(crate) type AtomicPtr<T> = *mut T;
-#[allow(unused)]
-pub(crate) struct RawBytes {
- ptr: *const u8,
- len: usize,
- // inlined "trait object"
- data: AtomicPtr<()>,
- vtable: &'static Vtable,
-}
-
-impl RawBytes {
- pub fn new_raw(
- ptr: *const u8,
- len: usize,
- data: AtomicPtr<()>,
- vtable: &'static Vtable,
- ) -> bytes::Bytes {
- RawBytes {
- ptr,
- len,
- data,
- vtable,
- }
- .into()
- }
-}
-
-// Validate some bytes::Bytes layout assumptions at compile time.
-const _: () = {
- assert!(
- core::mem::size_of::<RawBytes>() == core::mem::size_of::<bytes::Bytes>(),
- );
- assert!(
- core::mem::align_of::<RawBytes>() == core::mem::align_of::<bytes::Bytes>(),
- );
-};
-
-#[allow(unused)]
-pub(crate) struct Vtable {
- /// fn(data, ptr, len)
- pub clone: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> bytes::Bytes,
- /// fn(data, ptr, len)
- ///
- /// takes `Bytes` to value
- pub to_vec: unsafe fn(&AtomicPtr<()>, *const u8, usize) -> Vec<u8>,
- /// fn(data, ptr, len)
- pub drop: unsafe fn(&mut AtomicPtr<()>, *const u8, usize),
-}
-
-impl From<RawBytes> for bytes::Bytes {
- fn from(b: RawBytes) -> Self {
- // SAFETY: RawBytes has the same layout as bytes::Bytes
- // this is tested below, both are composed of usize-d ptrs/values
- // thus aren't currently subject to rust's field re-ordering to minimize padding
- unsafe { std::mem::transmute(b) }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use std::mem;
-
- const HELLO: &str = "hello";
-
- // ===== impl StaticVtable =====
-
- const STATIC_VTABLE: Vtable = Vtable {
- clone: static_clone,
- drop: static_drop,
- to_vec: static_to_vec,
- };
-
- unsafe fn static_clone(
- _: &AtomicPtr<()>,
- ptr: *const u8,
- len: usize,
- ) -> bytes::Bytes {
- from_static(std::slice::from_raw_parts(ptr, len)).into()
- }
-
- unsafe fn static_to_vec(
- _: &AtomicPtr<()>,
- ptr: *const u8,
- len: usize,
- ) -> Vec<u8> {
- let slice = std::slice::from_raw_parts(ptr, len);
- slice.to_vec()
- }
-
- unsafe fn static_drop(_: &mut AtomicPtr<()>, _: *const u8, _: usize) {
- // nothing to drop for &'static [u8]
- }
-
- fn from_static(bytes: &'static [u8]) -> RawBytes {
- RawBytes {
- ptr: bytes.as_ptr(),
- len: bytes.len(),
- data: std::ptr::null_mut(),
- vtable: &STATIC_VTABLE,
- }
- }
-
- #[test]
- fn bytes_identity() {
- let b1: bytes::Bytes = from_static(HELLO.as_bytes()).into();
- let b2 = bytes::Bytes::from_static(HELLO.as_bytes());
- assert_eq!(b1, b2); // Values are equal
- }
-
- #[test]
- fn bytes_layout() {
- let u1: [usize; 4] =
- // SAFETY: ensuring layout is the same
- unsafe { mem::transmute(from_static(HELLO.as_bytes())) };
- let u2: [usize; 4] =
- // SAFETY: ensuring layout is the same
- unsafe { mem::transmute(bytes::Bytes::from_static(HELLO.as_bytes())) };
- assert_eq!(u1[..3], u2[..3]); // Struct bytes are equal besides Vtables
- }
-}
diff --git a/serde_v8/magic/string_or_buffer.rs b/serde_v8/magic/string_or_buffer.rs
deleted file mode 100644
index 986f7d32a..000000000
--- a/serde_v8/magic/string_or_buffer.rs
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-use super::buffer::JsBuffer;
-use super::transl8::FromV8;
-use crate::error::value_to_type_str;
-use crate::magic::transl8::impl_magic;
-use crate::Error;
-use std::ops::Deref;
-
-#[derive(Debug)]
-pub enum StringOrBuffer {
- Buffer(JsBuffer),
- String(String),
-}
-
-impl_magic!(StringOrBuffer);
-
-impl Deref for StringOrBuffer {
- type Target = [u8];
- fn deref(&self) -> &Self::Target {
- match self {
- Self::Buffer(b) => b.as_ref(),
- Self::String(s) => s.as_bytes(),
- }
- }
-}
-
-impl<'a> TryFrom<&'a StringOrBuffer> for &'a str {
- type Error = std::str::Utf8Error;
- fn try_from(value: &'a StringOrBuffer) -> Result<Self, Self::Error> {
- match value {
- StringOrBuffer::String(s) => Ok(s.as_str()),
- StringOrBuffer::Buffer(b) => std::str::from_utf8(b.as_ref()),
- }
- }
-}
-
-impl FromV8 for StringOrBuffer {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- if let Ok(buf) = JsBuffer::from_v8(scope, value) {
- return Ok(Self::Buffer(buf));
- } else if let Ok(s) = crate::from_v8(scope, value) {
- return Ok(Self::String(s));
- }
- Err(Error::ExpectedBuffer(value_to_type_str(value)))
- }
-}
-
-impl From<StringOrBuffer> for bytes::Bytes {
- fn from(sob: StringOrBuffer) -> Self {
- match sob {
- StringOrBuffer::Buffer(b) => b.into(),
- StringOrBuffer::String(s) => s.into_bytes().into(),
- }
- }
-}
diff --git a/serde_v8/magic/transl8.rs b/serde_v8/magic/transl8.rs
deleted file mode 100644
index 3a8d0c358..000000000
--- a/serde_v8/magic/transl8.rs
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2018-2023 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>(
- &mut 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_mut<'a, T>(ptr: u64) -> &'a mut T {
- std::mem::transmute(ptr as usize)
-}
-
-/// 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 as usize))
-}
-
-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;
-
-macro_rules! impl_wrapper {
- ($i:item) => {
- #[derive(
- PartialEq,
- Eq,
- Clone,
- Debug,
- Default,
- derive_more::Deref,
- derive_more::DerefMut,
- derive_more::AsRef,
- derive_more::AsMut,
- derive_more::From,
- )]
- #[as_mut(forward)]
- #[as_ref(forward)]
- #[from(forward)]
- $i
- };
-}
-pub(crate) use impl_wrapper;
diff --git a/serde_v8/magic/u16string.rs b/serde_v8/magic/u16string.rs
deleted file mode 100644
index 04d742da9..000000000
--- a/serde_v8/magic/u16string.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use crate::error::value_to_type_str;
-use crate::Error;
-
-use super::transl8::impl_magic;
-use super::transl8::impl_wrapper;
-use super::transl8::FromV8;
-use super::transl8::ToV8;
-
-impl_wrapper!(
- pub struct U16String(Vec<u16>);
-);
-impl_magic!(U16String);
-
-impl ToV8 for U16String {
- fn to_v8<'a>(
- &mut self,
- scope: &mut v8::HandleScope<'a>,
- ) -> Result<v8::Local<'a, v8::Value>, crate::Error> {
- let maybe_v =
- v8::String::new_from_two_byte(scope, self, v8::NewStringType::Normal);
-
- // 'new_from_two_byte' can return 'None' if buffer length > kMaxLength.
- if let Some(v) = maybe_v {
- Ok(v.into())
- } else {
- Err(Error::Message(String::from(
- "Cannot allocate String from UTF-16: buffer exceeds maximum length.",
- )))
- }
- }
-}
-
-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(value_to_type_str(value)))?;
- let len = v8str.length();
- let mut buffer = Vec::with_capacity(len);
- #[allow(clippy::uninit_vec)]
- // SAFETY: we set length == capacity (see previous line),
- // before immediately writing into that buffer and sanity check with an assert
- unsafe {
- buffer.set_len(len);
- let written = v8str.write(
- scope,
- &mut buffer,
- 0,
- v8::WriteOptions::NO_NULL_TERMINATION,
- );
- assert!(written == len);
- }
- Ok(buffer.into())
- }
-}
diff --git a/serde_v8/magic/v8slice.rs b/serde_v8/magic/v8slice.rs
deleted file mode 100644
index 2b103f1c9..000000000
--- a/serde_v8/magic/v8slice.rs
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use std::ops::Deref;
-use std::ops::DerefMut;
-use std::ops::Range;
-use std::rc::Rc;
-
-use crate::error::value_to_type_str;
-
-use super::rawbytes;
-use super::transl8::FromV8;
-
-/// 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 V8Slice inhibits this until it is dropped. It
-/// behaves much like an Arc<[u8]>.
-///
-/// # Cloning
-/// 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 V8Slice {
- pub(crate) store: v8::SharedRef<v8::BackingStore>,
- pub(crate) range: Range<usize>,
-}
-
-// SAFETY: unsafe trait must have unsafe implementation
-unsafe impl Send for V8Slice {}
-
-impl V8Slice {
- fn as_slice(&self) -> &[u8] {
- // SAFETY: v8::SharedRef<v8::BackingStore> is similar to Arc<[u8]>,
- // it points to a fixed continuous slice of bytes on the heap.
- // We assume it's initialized and thus safe to read (though may not contain meaningful data)
- unsafe { &*(&self.store[self.range.clone()] as *const _ as *const [u8]) }
- }
-
- fn as_slice_mut(&mut self) -> &mut [u8] {
- #[allow(clippy::cast_ref_to_mut)]
- // SAFETY: v8::SharedRef<v8::BackingStore> is similar to Arc<[u8]>,
- // it points to a fixed continuous slice of bytes on the heap.
- // It's safe-ish to mutate concurrently because it can not be
- // shrunk/grown/moved/reallocated, thus avoiding dangling refs (unlike a Vec).
- // Concurrent writes can't lead to meaningful structural invalidation
- // since we treat them as opaque buffers / "bags of bytes",
- // concurrent mutation is simply an accepted fact of life.
- // And in practice V8Slices also do not have overallping read/write phases.
- // TLDR: permissive interior mutability on slices of bytes is "fine"
- unsafe {
- &mut *(&self.store[self.range.clone()] as *const _ as *mut [u8])
- }
- }
-}
-
-pub(crate) fn to_ranged_buffer<'s>(
- scope: &mut v8::HandleScope<'s>,
- value: v8::Local<v8::Value>,
-) -> Result<(v8::Local<'s, v8::ArrayBuffer>, Range<usize>), v8::DataError> {
- if let Ok(view) = v8::Local::<v8::ArrayBufferView>::try_from(value) {
- let (offset, len) = (view.byte_offset(), view.byte_length());
- let buffer = view.buffer(scope).ok_or(v8::DataError::NoData {
- expected: "view to have a buffer",
- })?;
- let buffer = v8::Local::new(scope, buffer); // recreate handle to avoid lifetime issues
- return Ok((buffer, offset..offset + len));
- }
- let b: v8::Local<v8::ArrayBuffer> = value.try_into()?;
- let b = v8::Local::new(scope, b); // recreate handle to avoid lifetime issues
- Ok((b, 0..b.byte_length()))
-}
-
-impl FromV8 for V8Slice {
- fn from_v8(
- scope: &mut v8::HandleScope,
- value: v8::Local<v8::Value>,
- ) -> Result<Self, crate::Error> {
- match to_ranged_buffer(scope, value) {
- Ok((b, range)) => {
- let store = b.get_backing_store();
- if store.is_resizable_by_user_javascript() {
- Err(crate::Error::ResizableBackingStoreNotSupported)
- } else if store.is_shared() {
- Err(crate::Error::ExpectedBuffer(value_to_type_str(value)))
- } else {
- Ok(V8Slice { store, range })
- }
- }
- Err(_) => Err(crate::Error::ExpectedBuffer(value_to_type_str(value))),
- }
- }
-}
-
-impl Deref for V8Slice {
- type Target = [u8];
- fn deref(&self) -> &[u8] {
- self.as_slice()
- }
-}
-
-impl DerefMut for V8Slice {
- fn deref_mut(&mut self) -> &mut [u8] {
- self.as_slice_mut()
- }
-}
-
-impl AsRef<[u8]> for V8Slice {
- fn as_ref(&self) -> &[u8] {
- self.as_slice()
- }
-}
-
-impl AsMut<[u8]> for V8Slice {
- fn as_mut(&mut self) -> &mut [u8] {
- self.as_slice_mut()
- }
-}
-
-// Implement V8Slice -> bytes::Bytes
-impl V8Slice {
- fn rc_into_byte_parts(self: Rc<Self>) -> (*const u8, usize, *mut V8Slice) {
- let (ptr, len) = {
- let slice = self.as_ref();
- (slice.as_ptr(), slice.len())
- };
- let rc_raw = Rc::into_raw(self);
- let data = rc_raw as *mut V8Slice;
- (ptr, len, data)
- }
-}
-
-impl From<V8Slice> for bytes::Bytes {
- fn from(v8slice: V8Slice) -> Self {
- let (ptr, len, data) = Rc::new(v8slice).rc_into_byte_parts();
- rawbytes::RawBytes::new_raw(ptr, len, data.cast(), &V8SLICE_VTABLE)
- }
-}
-
-// NOTE: in the limit we could avoid extra-indirection and use the C++ shared_ptr
-// but we can't store both the underlying data ptr & ctrl ptr ... so instead we
-// use a shared rust ptr (Rc/Arc) that itself controls the C++ shared_ptr
-const V8SLICE_VTABLE: rawbytes::Vtable = rawbytes::Vtable {
- clone: v8slice_clone,
- drop: v8slice_drop,
- to_vec: v8slice_to_vec,
-};
-
-unsafe fn v8slice_clone(
- data: &rawbytes::AtomicPtr<()>,
- ptr: *const u8,
- len: usize,
-) -> bytes::Bytes {
- let rc = Rc::from_raw(*data as *const V8Slice);
- let (_, _, data) = rc.clone().rc_into_byte_parts();
- std::mem::forget(rc);
- // NOTE: `bytes::Bytes` does bounds checking so we trust its ptr, len inputs
- // and must use them to allow cloning Bytes it has sliced
- rawbytes::RawBytes::new_raw(ptr, len, data.cast(), &V8SLICE_VTABLE)
-}
-
-unsafe fn v8slice_to_vec(
- data: &rawbytes::AtomicPtr<()>,
- ptr: *const u8,
- len: usize,
-) -> Vec<u8> {
- let rc = Rc::from_raw(*data as *const V8Slice);
- std::mem::forget(rc);
- // NOTE: `bytes::Bytes` does bounds checking so we trust its ptr, len inputs
- // and must use them to allow cloning Bytes it has sliced
- Vec::from_raw_parts(ptr as _, len, len)
-}
-
-unsafe fn v8slice_drop(
- data: &mut rawbytes::AtomicPtr<()>,
- _: *const u8,
- _: usize,
-) {
- drop(Rc::from_raw(*data as *const V8Slice))
-}
diff --git a/serde_v8/magic/value.rs b/serde_v8/magic/value.rs
deleted file mode 100644
index 0333d75bc..000000000
--- a/serde_v8/magic/value.rs
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2018-2023 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>(
- &mut 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()) })
- }
-}