From 12f7581ed9ee5324a425074d30aedd38b89d4838 Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Mon, 25 Apr 2022 09:56:47 -0500 Subject: cleanup(serde_v8): disambiguate ZeroCopyBuf (#14380) --- serde_v8/magic/buffer.rs | 52 +++++++++--------- serde_v8/magic/detached_buffer.rs | 8 +-- serde_v8/magic/mod.rs | 2 +- serde_v8/magic/string_or_buffer.rs | 6 +-- serde_v8/magic/v8slice.rs | 105 +++++++++++++++++++++++++++++++++++++ serde_v8/magic/zero_copy_buf.rs | 105 ------------------------------------- 6 files changed, 139 insertions(+), 139 deletions(-) create mode 100644 serde_v8/magic/v8slice.rs delete mode 100644 serde_v8/magic/zero_copy_buf.rs (limited to 'serde_v8/magic') diff --git a/serde_v8/magic/buffer.rs b/serde_v8/magic/buffer.rs index dfa6928fb..81f550bcb 100644 --- a/serde_v8/magic/buffer.rs +++ b/serde_v8/magic/buffer.rs @@ -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>>), - // 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 backed buffers to resource methods. Temp(Vec), } -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) -> Self { - MagicBuffer::Temp(vec) + ZeroCopyBuf::Temp(vec) } // TODO(@littledivy): Temporary, this needs a refactor. pub fn to_temp(self) -> Vec { 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> for MagicBuffer { +impl From> for ZeroCopyBuf { fn from(buf: Box<[u8]>) -> Self { - MagicBuffer::ToV8(Mutex::new(Some(buf))) + ZeroCopyBuf::ToV8(Mutex::new(Some(buf))) } } -impl From> for MagicBuffer { +impl From> for ZeroCopyBuf { fn from(vec: Vec) -> 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, ) -> Result { - Ok(Self::FromV8(ZeroCopyBuf::from_v8(scope, value)?)) + Ok(Self::FromV8(V8Slice::from_v8(scope, value)?)) } } diff --git a/serde_v8/magic/detached_buffer.rs b/serde_v8/magic/detached_buffer.rs index 1435a0fa6..4e33de32c 100644 --- a/serde_v8/magic/detached_buffer.rs +++ b/serde_v8/magic/detached_buffer.rs @@ -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 })) } } diff --git a/serde_v8/magic/mod.rs b/serde_v8/magic/mod.rs index 4f5398bda..076699302 100644 --- a/serde_v8/magic/mod.rs +++ b/serde_v8/magic/mod.rs @@ -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; diff --git a/serde_v8/magic/string_or_buffer.rs b/serde_v8/magic/string_or_buffer.rs index e04cb1a93..a48378b52 100644 --- a/serde_v8/magic/string_or_buffer.rs +++ b/serde_v8/magic/string_or_buffer.rs @@ -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, ) -> Result { - 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)); diff --git a/serde_v8/magic/v8slice.rs b/serde_v8/magic/v8slice.rs new file mode 100644 index 000000000..d4101847e --- /dev/null +++ b/serde_v8/magic/v8slice.rs @@ -0,0 +1,105 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. + +use std::ops::Deref; +use std::ops::DerefMut; +use std::ops::Range; + +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, + pub(crate) range: Range, +} + +unsafe impl Send for V8Slice {} + +impl V8Slice { + pub fn from_buffer( + buffer: v8::Local, + range: Range, + ) -> Result { + let store = buffer.get_backing_store(); + if store.is_shared() { + return Err(v8::DataError::BadType { + actual: "shared ArrayBufferView", + expected: "non-shared ArrayBufferView", + }); + } + Ok(Self { store, range }) + } + + fn as_slice(&self) -> &[u8] { + unsafe { &*(&self.store[self.range.clone()] as *const _ as *const [u8]) } + } + + #[allow(clippy::cast_ref_to_mut)] + fn as_slice_mut(&mut self) -> &mut [u8] { + 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, +) -> Result<(v8::Local<'s, v8::ArrayBuffer>, Range), v8::DataError> { + if value.is_array_buffer_view() { + let view: v8::Local = value.try_into()?; + 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 = 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, + ) -> Result { + to_ranged_buffer(scope, value) + .and_then(|(b, r)| Self::from_buffer(b, r)) + .map_err(|_| crate::Error::ExpectedBuffer) + } +} + +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() + } +} diff --git a/serde_v8/magic/zero_copy_buf.rs b/serde_v8/magic/zero_copy_buf.rs deleted file mode 100644 index a9dc6334c..000000000 --- a/serde_v8/magic/zero_copy_buf.rs +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. - -use std::ops::Deref; -use std::ops::DerefMut; -use std::ops::Range; - -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 { - pub(crate) store: v8::SharedRef, - pub(crate) range: Range, -} - -unsafe impl Send for ZeroCopyBuf {} - -impl ZeroCopyBuf { - pub fn from_buffer( - buffer: v8::Local, - range: Range, - ) -> Result { - let store = buffer.get_backing_store(); - if store.is_shared() { - return Err(v8::DataError::BadType { - actual: "shared ArrayBufferView", - expected: "non-shared ArrayBufferView", - }); - } - Ok(Self { store, range }) - } - - fn as_slice(&self) -> &[u8] { - unsafe { &*(&self.store[self.range.clone()] as *const _ as *const [u8]) } - } - - #[allow(clippy::cast_ref_to_mut)] - fn as_slice_mut(&mut self) -> &mut [u8] { - 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, -) -> Result<(v8::Local<'s, v8::ArrayBuffer>, Range), v8::DataError> { - if value.is_array_buffer_view() { - let view: v8::Local = value.try_into()?; - 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 = 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 ZeroCopyBuf { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local, - ) -> Result { - to_ranged_buffer(scope, value) - .and_then(|(b, r)| Self::from_buffer(b, r)) - .map_err(|_| crate::Error::ExpectedBuffer) - } -} - -impl Deref for ZeroCopyBuf { - type Target = [u8]; - fn deref(&self) -> &[u8] { - self.as_slice() - } -} - -impl DerefMut for ZeroCopyBuf { - fn deref_mut(&mut self) -> &mut [u8] { - self.as_slice_mut() - } -} - -impl AsRef<[u8]> for ZeroCopyBuf { - fn as_ref(&self) -> &[u8] { - self.as_slice() - } -} - -impl AsMut<[u8]> for ZeroCopyBuf { - fn as_mut(&mut self) -> &mut [u8] { - self.as_slice_mut() - } -} -- cgit v1.2.3