diff options
| author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2023-06-22 23:37:56 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-06-22 23:37:56 +0200 |
| commit | dda0f1c343bfb3196ce6a7c7e8c2acccfd5c2e5b (patch) | |
| tree | 10fc273a620949ccf63826363499f8f39056896d /serde_v8/magic | |
| parent | b319fa7f4965af3d3d576ea528248a31c96a4053 (diff) | |
refactor(serde_v8): split ZeroCopyBuf into JsBuffer and ToJsBuffer (#19566)
`ZeroCopyBuf` was convenient to use, but sometimes it did hide details
that some copies were necessary in certain cases. Also it made it way to easy
for the caller to pass around and convert into different values. This commit
splits `ZeroCopyBuf` into `JsBuffer` (an array buffer coming from V8) and
`ToJsBuffer` (a Rust buffer that will be converted into a V8 array buffer).
As a result some magical conversions were removed (they were never used)
limiting the API surface and preparing for changes in #19534.
Diffstat (limited to 'serde_v8/magic')
| -rw-r--r-- | serde_v8/magic/any_value.rs | 13 | ||||
| -rw-r--r-- | serde_v8/magic/buffer.rs | 114 | ||||
| -rw-r--r-- | serde_v8/magic/string_or_buffer.rs | 35 |
3 files changed, 59 insertions, 103 deletions
diff --git a/serde_v8/magic/any_value.rs b/serde_v8/magic/any_value.rs index 31a74cfde..9ae39bb2e 100644 --- a/serde_v8/magic/any_value.rs +++ b/serde_v8/magic/any_value.rs @@ -1,17 +1,19 @@ use num_bigint::BigInt; // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use super::buffer::ZeroCopyBuf; +use super::buffer::JsBuffer; use super::transl8::FromV8; use super::transl8::ToV8; use crate::magic::transl8::impl_magic; use crate::Error; +use crate::ToJsBuffer; /// An untagged enum type that can be any of number, string, bool, bigint, or /// buffer. #[derive(Debug)] pub enum AnyValue { - Buffer(ZeroCopyBuf), + RustBuffer(ToJsBuffer), + V8Buffer(JsBuffer), String(String), Number(f64), BigInt(BigInt), @@ -26,7 +28,8 @@ impl ToV8 for AnyValue { scope: &mut v8::HandleScope<'a>, ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { match self { - Self::Buffer(buf) => buf.to_v8(scope), + 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) => { @@ -52,8 +55,8 @@ impl FromV8 for AnyValue { let bigint = crate::BigInt::from_v8(scope, value)?; Ok(AnyValue::BigInt(bigint.into())) } else if value.is_array_buffer_view() { - let buf = ZeroCopyBuf::from_v8(scope, value)?; - Ok(AnyValue::Buffer(buf)) + 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)) diff --git a/serde_v8/magic/buffer.rs b/serde_v8/magic/buffer.rs index d0f0909bc..032a3be33 100644 --- a/serde_v8/magic/buffer.rs +++ b/serde_v8/magic/buffer.rs @@ -9,91 +9,93 @@ use super::transl8::ToV8; use super::v8slice::V8Slice; use crate::magic::transl8::impl_magic; -// An asymmetric wrapper around V8Slice, -// allowing us to use a single type for familiarity -pub enum ZeroCopyBuf { - FromV8(V8Slice), - ToV8(Option<Box<[u8]>>), -} +pub struct JsBuffer(V8Slice); -impl_magic!(ZeroCopyBuf); +impl_magic!(JsBuffer); -impl Debug for ZeroCopyBuf { +impl Debug for JsBuffer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.debug_list().entries(self.as_ref().iter()).finish() - } -} - -impl ZeroCopyBuf { - pub fn empty() -> Self { - ZeroCopyBuf::ToV8(Some(vec![0_u8; 0].into_boxed_slice())) + f.debug_list().entries(self.0.as_ref().iter()).finish() } } -impl Clone for ZeroCopyBuf { +impl Clone for JsBuffer { fn clone(&self) -> Self { - match self { - Self::FromV8(zbuf) => Self::FromV8(zbuf.clone()), - Self::ToV8(_) => panic!("Don't Clone a ZeroCopyBuf sent to v8"), - } + Self(self.0.clone()) } } -impl AsRef<[u8]> for ZeroCopyBuf { +impl AsRef<[u8]> for JsBuffer { fn as_ref(&self) -> &[u8] { - self + &self.0 } } -impl AsMut<[u8]> for ZeroCopyBuf { +impl AsMut<[u8]> for JsBuffer { fn as_mut(&mut self) -> &mut [u8] { - &mut *self + &mut self.0 } } -impl Deref for ZeroCopyBuf { +impl Deref for JsBuffer { type Target = [u8]; fn deref(&self) -> &[u8] { - match self { - Self::FromV8(buf) => buf, - Self::ToV8(_) => panic!("Don't Deref a ZeroCopyBuf sent to v8"), - } + &self.0 } } -impl DerefMut for ZeroCopyBuf { +impl DerefMut for JsBuffer { fn deref_mut(&mut self) -> &mut [u8] { - match self { - Self::FromV8(buf) => &mut *buf, - Self::ToV8(_) => panic!("Don't Deref a ZeroCopyBuf sent to v8"), - } + &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() } } -impl From<Box<[u8]>> for ZeroCopyBuf { +// 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 { - ZeroCopyBuf::ToV8(Some(buf)) + ToJsBuffer(Some(buf)) } } -impl From<Vec<u8>> for ZeroCopyBuf { +impl From<Vec<u8>> for ToJsBuffer { fn from(vec: Vec<u8>) -> Self { vec.into_boxed_slice().into() } } -impl ToV8 for ZeroCopyBuf { +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]> = match self { - Self::FromV8(buf) => { - let value: &[u8] = buf; - value.into() - } - Self::ToV8(ref mut x) => x.take().expect("ZeroCopyBuf was empty"), - }; + let buf: Box<[u8]> = self.0.take().expect("RustToV8Buf was empty"); if buf.is_empty() { let ab = v8::ArrayBuffer::new(scope, 0); @@ -103,7 +105,7 @@ impl ToV8 for ZeroCopyBuf { .into(), ); } - let buf_len = buf.len(); + 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(); @@ -115,23 +117,3 @@ impl ToV8 for ZeroCopyBuf { ) } } - -impl FromV8 for ZeroCopyBuf { - fn from_v8( - scope: &mut v8::HandleScope, - value: v8::Local<v8::Value>, - ) -> Result<Self, crate::Error> { - Ok(Self::FromV8(V8Slice::from_v8(scope, value)?)) - } -} - -impl From<ZeroCopyBuf> for bytes::Bytes { - fn from(zbuf: ZeroCopyBuf) -> bytes::Bytes { - match zbuf { - ZeroCopyBuf::FromV8(v) => v.into(), - ZeroCopyBuf::ToV8(mut v) => { - v.take().expect("ZeroCopyBuf was empty").into() - } - } - } -} diff --git a/serde_v8/magic/string_or_buffer.rs b/serde_v8/magic/string_or_buffer.rs index 02571f669..986f7d32a 100644 --- a/serde_v8/magic/string_or_buffer.rs +++ b/serde_v8/magic/string_or_buffer.rs @@ -1,7 +1,6 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use super::buffer::ZeroCopyBuf; +use super::buffer::JsBuffer; use super::transl8::FromV8; -use super::transl8::ToV8; use crate::error::value_to_type_str; use crate::magic::transl8::impl_magic; use crate::Error; @@ -9,7 +8,7 @@ use std::ops::Deref; #[derive(Debug)] pub enum StringOrBuffer { - Buffer(ZeroCopyBuf), + Buffer(JsBuffer), String(String), } @@ -35,40 +34,12 @@ impl<'a> TryFrom<&'a StringOrBuffer> for &'a str { } } -impl ToV8 for StringOrBuffer { - fn to_v8<'a>( - &mut self, - scope: &mut v8::HandleScope<'a>, - ) -> Result<v8::Local<'a, v8::Value>, crate::Error> { - match self { - Self::Buffer(buf) => { - let buf: Box<[u8]> = match buf { - ZeroCopyBuf::FromV8(buf) => { - let value: &[u8] = buf; - value.into() - } - ZeroCopyBuf::ToV8(ref mut x) => { - x.take().expect("ZeroCopyBuf was empty") - } - }; - let backing_store = - v8::ArrayBuffer::new_backing_store_from_boxed_slice(buf); - Ok( - v8::ArrayBuffer::with_backing_store(scope, &backing_store.into()) - .into(), - ) - } - Self::String(s) => crate::to_v8(scope, s), - } - } -} - impl FromV8 for StringOrBuffer { fn from_v8( scope: &mut v8::HandleScope, value: v8::Local<v8::Value>, ) -> Result<Self, crate::Error> { - if let Ok(buf) = ZeroCopyBuf::from_v8(scope, value) { + 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)); |
