// 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>>), } 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> for MagicBuffer { fn from(buf: Box<[u8]>) -> Self { MagicBuffer::ToV8(Mutex::new(Some(buf))) } } impl From> for MagicBuffer { fn from(vec: Vec) -> Self { vec.into_boxed_slice().into() } } impl ToV8 for MagicBuffer { fn to_v8<'a>( &self, scope: &mut v8::HandleScope<'a>, ) -> Result, 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, ) -> Result { Ok(Self::FromV8(ZeroCopyBuf::from_v8(scope, value)?)) } }