From 4b7d306a198d020ce2b6fa1c758c71714bfd036c Mon Sep 17 00:00:00 2001 From: Aaron O'Mullan Date: Sun, 24 Apr 2022 09:28:46 -0300 Subject: perf(serde_v8): zero-copy StringOrBuffer (#14381) --- serde_v8/magic/string_or_buffer.rs | 67 ++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-) (limited to 'serde_v8/magic/string_or_buffer.rs') diff --git a/serde_v8/magic/string_or_buffer.rs b/serde_v8/magic/string_or_buffer.rs index edde2adcd..e04cb1a93 100644 --- a/serde_v8/magic/string_or_buffer.rs +++ b/serde_v8/magic/string_or_buffer.rs @@ -1,45 +1,50 @@ +// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license. +use super::buffer::MagicBuffer; +use super::transl8::{FromV8, ToV8}; +use crate::magic::transl8::impl_magic; +use crate::Error; use std::ops::Deref; #[derive(Debug)] -pub struct StringOrBuffer(Vec); - -impl Deref for StringOrBuffer { - type Target = Vec; - fn deref(&self) -> &Vec { - &self.0 - } +pub enum StringOrBuffer { + Buffer(MagicBuffer), + String(String), } -impl StringOrBuffer { - pub fn into_bytes(self) -> Vec { - self.0 - } -} +impl_magic!(StringOrBuffer); -impl<'de> serde::Deserialize<'de> for StringOrBuffer { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - StringOrBufferInner::deserialize(deserializer) - .map(|x| StringOrBuffer(x.into_bytes())) +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(), + } } } -// TODO(@AaronO): explore if we can make this work with ZeroCopyBuf -#[derive(serde::Deserialize)] -#[serde(untagged)] -enum StringOrBufferInner { - #[serde(with = "serde_bytes")] - Buffer(Vec), - String(String), +impl ToV8 for StringOrBuffer { + fn to_v8<'a>( + &self, + scope: &mut v8::HandleScope<'a>, + ) -> Result, crate::Error> { + match self { + Self::Buffer(buf) => crate::to_v8(scope, buf), + Self::String(s) => crate::to_v8(scope, s), + } + } } -impl StringOrBufferInner { - fn into_bytes(self) -> Vec { - match self { - Self::String(s) => s.into_bytes(), - Self::Buffer(b) => b, +impl FromV8 for StringOrBuffer { + fn from_v8( + scope: &mut v8::HandleScope, + value: v8::Local, + ) -> Result { + if let Ok(buf) = MagicBuffer::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) } } -- cgit v1.2.3