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.
This commit is contained in:
Bartek Iwańczuk 2023-06-22 23:37:56 +02:00 committed by GitHub
parent b319fa7f49
commit dda0f1c343
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
39 changed files with 353 additions and 382 deletions

View file

@ -3,11 +3,11 @@ use deno_core::anyhow::Error;
use deno_core::op;
use deno_core::AsyncRefCell;
use deno_core::AsyncResult;
use deno_core::JsBuffer;
use deno_core::JsRuntimeForSnapshot;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use std::cell::RefCell;
use std::env;
use std::net::SocketAddr;
@ -116,7 +116,7 @@ fn create_js_runtime() -> JsRuntimeForSnapshot {
async fn op_read_socket(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
mut data: ZeroCopyBuf,
mut data: JsBuffer,
) -> Result<u32, Error> {
let resource = state.borrow_mut().resource_table.get::<TcpStream>(rid)?;
let nread = resource.read(&mut data).await?;

View file

@ -4,7 +4,7 @@ use std::ops::Deref;
use std::ops::DerefMut;
use bytes::Buf;
use serde_v8::ZeroCopyBuf;
use serde_v8::JsBuffer;
/// BufView is a wrapper around an underlying contiguous chunk of bytes. It can
/// be created from a [ZeroCopyBuf], [bytes::Bytes], or [Vec<u8>] and implements
@ -22,7 +22,7 @@ pub struct BufView {
enum BufViewInner {
Empty,
Bytes(bytes::Bytes),
ZeroCopy(ZeroCopyBuf),
ZeroCopy(JsBuffer),
Vec(Vec<u8>),
}
@ -100,8 +100,8 @@ impl AsRef<[u8]> for BufView {
}
}
impl From<ZeroCopyBuf> for BufView {
fn from(buf: ZeroCopyBuf) -> Self {
impl From<JsBuffer> for BufView {
fn from(buf: JsBuffer) -> Self {
Self::from_inner(BufViewInner::ZeroCopy(buf))
}
}
@ -145,7 +145,7 @@ pub struct BufMutView {
}
enum BufMutViewInner {
ZeroCopy(ZeroCopyBuf),
ZeroCopy(JsBuffer),
Vec(Vec<u8>),
}
@ -273,8 +273,8 @@ impl AsMut<[u8]> for BufMutView {
}
}
impl From<ZeroCopyBuf> for BufMutView {
fn from(buf: ZeroCopyBuf) -> Self {
impl From<JsBuffer> for BufMutView {
fn from(buf: JsBuffer) -> Self {
Self::from_inner(BufMutViewInner::ZeroCopy(buf))
}
}

View file

@ -32,9 +32,10 @@ pub use serde_json;
pub use serde_v8;
pub use serde_v8::ByteString;
pub use serde_v8::DetachedBuffer;
pub use serde_v8::JsBuffer;
pub use serde_v8::StringOrBuffer;
pub use serde_v8::ToJsBuffer;
pub use serde_v8::U16String;
pub use serde_v8::ZeroCopyBuf;
pub use sourcemap;
pub use url;
pub use v8;

View file

@ -6,11 +6,12 @@ use crate::io::BufView;
use crate::ops_builtin_v8;
use crate::ops_metrics::OpMetrics;
use crate::resources::ResourceId;
use crate::JsBuffer;
use crate::OpState;
use crate::Resource;
use crate::ZeroCopyBuf;
use anyhow::Error;
use deno_ops::op;
use serde_v8::ToJsBuffer;
use std::cell::RefCell;
use std::io::stderr;
use std::io::stdout;
@ -218,7 +219,7 @@ pub fn op_wasm_streaming_set_url(
async fn op_read(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
buf: ZeroCopyBuf,
buf: JsBuffer,
) -> Result<u32, Error> {
let resource = state.borrow().resource_table.get_any(rid)?;
let view = BufMutView::from(buf);
@ -229,7 +230,7 @@ async fn op_read(
async fn op_read_all(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
) -> Result<ZeroCopyBuf, Error> {
) -> Result<ToJsBuffer, Error> {
let resource = state.borrow().resource_table.get_any(rid)?;
// The number of bytes we attempt to grow the buffer by each time it fills
@ -291,14 +292,14 @@ async fn op_read_all(
vec.truncate(nread);
}
Ok(ZeroCopyBuf::from(vec))
Ok(ToJsBuffer::from(vec))
}
#[op]
async fn op_write(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
buf: ZeroCopyBuf,
buf: JsBuffer,
) -> Result<u32, Error> {
let resource = state.borrow().resource_table.get_any(rid)?;
let view = BufView::from(buf);
@ -331,7 +332,7 @@ fn op_write_sync(
async fn op_write_all(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
buf: ZeroCopyBuf,
buf: JsBuffer,
) -> Result<(), Error> {
let resource = state.borrow().resource_table.get_any(rid)?;
let view = BufView::from(buf);

View file

@ -9,9 +9,10 @@ use crate::resolve_url;
use crate::runtime::script_origin;
use crate::serde_v8::from_v8;
use crate::source_map::apply_source_map;
use crate::JsBuffer;
use crate::JsRealm;
use crate::JsRuntime;
use crate::ZeroCopyBuf;
use crate::ToJsBuffer;
use anyhow::Error;
use deno_ops::op;
use serde::Deserialize;
@ -375,7 +376,7 @@ fn op_serialize(
value: serde_v8::Value,
options: Option<SerializeDeserializeOptions>,
error_callback: Option<serde_v8::Value>,
) -> Result<ZeroCopyBuf, Error> {
) -> Result<ToJsBuffer, Error> {
let options = options.unwrap_or_default();
let error_callback = match error_callback {
Some(cb) => Some(
@ -448,7 +449,7 @@ fn op_serialize(
if scope.has_caught() || scope.has_terminated() {
scope.rethrow();
// Dummy value, this result will be discarded because an error was thrown.
Ok(ZeroCopyBuf::empty())
Ok(ToJsBuffer::empty())
} else if let Some(true) = ret {
let vector = value_serializer.release();
Ok(vector.into())
@ -460,7 +461,7 @@ fn op_serialize(
#[op(v8)]
fn op_deserialize<'a>(
scope: &mut v8::HandleScope<'a>,
zero_copy: ZeroCopyBuf,
zero_copy: JsBuffer,
options: Option<SerializeDeserializeOptions>,
) -> Result<serde_v8::Value<'a>, Error> {
let options = options.unwrap_or_default();

View file

@ -18,7 +18,7 @@ use crate::modules::ModuleType;
use crate::modules::ResolutionKind;
use crate::modules::SymbolicModule;
use crate::Extension;
use crate::ZeroCopyBuf;
use crate::JsBuffer;
use crate::*;
use anyhow::Error;
use deno_ops::op;
@ -55,7 +55,7 @@ struct TestState {
async fn op_test(
rc_op_state: Rc<RefCell<OpState>>,
control: u8,
buf: Option<ZeroCopyBuf>,
buf: Option<JsBuffer>,
) -> Result<u8, AnyError> {
#![allow(clippy::await_holding_refcell_ref)] // False positive.
let op_state_ = rc_op_state.borrow();
@ -1977,15 +1977,15 @@ fn js_realm_init_snapshot() {
#[test]
fn js_realm_sync_ops() {
// Test that returning a ZeroCopyBuf and throwing an exception from a sync
// Test that returning a RustToV8Buf and throwing an exception from a sync
// op result in objects with prototypes from the right realm. Note that we
// don't test the result of returning structs, because they will be
// serialized to objects with null prototype.
#[op]
fn op_test(fail: bool) -> Result<ZeroCopyBuf, Error> {
fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
if !fail {
Ok(ZeroCopyBuf::empty())
Ok(ToJsBuffer::empty())
} else {
Err(crate::error::type_error("Test"))
}
@ -2025,15 +2025,15 @@ fn js_realm_sync_ops() {
#[tokio::test]
async fn js_realm_async_ops() {
// Test that returning a ZeroCopyBuf and throwing an exception from a async
// Test that returning a RustToV8Buf and throwing an exception from a async
// op result in objects with prototypes from the right realm. Note that we
// don't test the result of returning structs, because they will be
// serialized to objects with null prototype.
#[op]
async fn op_test(fail: bool) -> Result<ZeroCopyBuf, Error> {
async fn op_test(fail: bool) -> Result<ToJsBuffer, Error> {
if !fail {
Ok(ZeroCopyBuf::empty())
Ok(ToJsBuffer::empty())
} else {
Err(crate::error::type_error("Test"))
}

View file

@ -12,10 +12,10 @@ use std::rc::Rc;
use async_trait::async_trait;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
#[async_trait]
pub trait BroadcastChannel: Clone {
@ -81,7 +81,7 @@ pub async fn op_broadcast_send<BC>(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
name: String,
buf: ZeroCopyBuf,
buf: JsBuffer,
) -> Result<(), AnyError>
where
BC: BroadcastChannel + 'static,

View file

@ -21,7 +21,8 @@ use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::task::spawn_blocking;
use deno_core::ZeroCopyBuf;
use deno_core::JsBuffer;
use deno_core::ToJsBuffer;
use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::PaddingScheme;
use serde::Deserialize;
@ -36,7 +37,7 @@ use crate::shared::*;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DecryptOptions {
key: RawKeyData,
key: V8RawKeyData,
#[serde(flatten)]
algorithm: DecryptAlgorithm,
}
@ -77,8 +78,8 @@ pub enum DecryptAlgorithm {
#[op]
pub async fn op_crypto_decrypt(
opts: DecryptOptions,
data: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
data: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let key = opts.key;
let fun = move || match opts.algorithm {
DecryptAlgorithm::RsaOaep { hash, label } => {
@ -104,7 +105,7 @@ pub async fn op_crypto_decrypt(
}
fn decrypt_rsa_oaep(
key: RawKeyData,
key: V8RawKeyData,
hash: ShaHash,
label: Vec<u8>,
data: &[u8],
@ -143,7 +144,7 @@ fn decrypt_rsa_oaep(
}
fn decrypt_aes_cbc(
key: RawKeyData,
key: V8RawKeyData,
length: usize,
iv: Vec<u8>,
data: &[u8],
@ -281,7 +282,7 @@ fn decrypt_aes_gcm_gen<N: ArrayLength<u8>>(
}
fn decrypt_aes_ctr(
key: RawKeyData,
key: V8RawKeyData,
key_length: usize,
counter: &[u8],
ctr_length: usize,
@ -315,7 +316,7 @@ fn decrypt_aes_ctr(
}
fn decrypt_aes_gcm(
key: RawKeyData,
key: V8RawKeyData,
length: usize,
tag_length: usize,
iv: Vec<u8>,

View file

@ -2,7 +2,7 @@
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use elliptic_curve::pkcs8::PrivateKeyInfo;
use rand::rngs::OsRng;
use rand::RngCore;
@ -105,7 +105,7 @@ pub fn op_crypto_import_pkcs8_ed25519(key_data: &[u8], out: &mut [u8]) -> bool {
#[op]
pub fn op_crypto_export_spki_ed25519(
pubkey: &[u8],
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let key_info = spki::SubjectPublicKeyInfo {
algorithm: spki::AlgorithmIdentifier {
// id-Ed25519
@ -120,7 +120,7 @@ pub fn op_crypto_export_spki_ed25519(
#[op]
pub fn op_crypto_export_pkcs8_ed25519(
pkey: &[u8],
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
// This should probably use OneAsymmetricKey instead
let pk_info = rsa::pkcs8::PrivateKeyInfo {
public_key: None,

View file

@ -20,7 +20,8 @@ use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::task::spawn_blocking;
use deno_core::ZeroCopyBuf;
use deno_core::JsBuffer;
use deno_core::ToJsBuffer;
use rand::rngs::OsRng;
use rsa::pkcs1::DecodeRsaPublicKey;
use rsa::PaddingScheme;
@ -37,7 +38,7 @@ use crate::shared::*;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EncryptOptions {
key: RawKeyData,
key: V8RawKeyData,
#[serde(flatten)]
algorithm: EncryptAlgorithm,
}
@ -78,8 +79,8 @@ pub enum EncryptAlgorithm {
#[op]
pub async fn op_crypto_encrypt(
opts: EncryptOptions,
data: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
data: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let key = opts.key;
let fun = move || match opts.algorithm {
EncryptAlgorithm::RsaOaep { hash, label } => {
@ -105,7 +106,7 @@ pub async fn op_crypto_encrypt(
}
fn encrypt_rsa_oaep(
key: RawKeyData,
key: V8RawKeyData,
hash: ShaHash,
label: Vec<u8>,
data: &[u8],
@ -145,7 +146,7 @@ fn encrypt_rsa_oaep(
}
fn encrypt_aes_cbc(
key: RawKeyData,
key: V8RawKeyData,
length: usize,
iv: Vec<u8>,
data: &[u8],
@ -218,7 +219,7 @@ fn encrypt_aes_gcm_general<N: ArrayLength<u8>>(
}
fn encrypt_aes_gcm(
key: RawKeyData,
key: V8RawKeyData,
length: usize,
tag_length: usize,
iv: Vec<u8>,
@ -277,7 +278,7 @@ where
}
fn encrypt_aes_ctr(
key: RawKeyData,
key: V8RawKeyData,
key_length: usize,
counter: &[u8],
ctr_length: usize,

View file

@ -5,7 +5,7 @@ use const_oid::ObjectIdentifier;
use deno_core::error::custom_error;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use elliptic_curve::sec1::ToEncodedPoint;
use p256::pkcs8::DecodePrivateKey;
use rsa::pkcs1::UIntRef;
@ -59,9 +59,9 @@ pub enum ExportKeyAlgorithm {
#[derive(Serialize)]
#[serde(untagged)]
pub enum ExportKeyResult {
Raw(ZeroCopyBuf),
Pkcs8(ZeroCopyBuf),
Spki(ZeroCopyBuf),
Raw(ToJsBuffer),
Pkcs8(ToJsBuffer),
Spki(ToJsBuffer),
JwkSecret {
k: String,
},
@ -93,7 +93,7 @@ pub enum ExportKeyResult {
#[op]
pub fn op_crypto_export_key(
opts: ExportKeyOptions,
key_data: RawKeyData,
key_data: V8RawKeyData,
) -> Result<ExportKeyResult, AnyError> {
match opts.algorithm {
ExportKeyAlgorithm::RsassaPkcs1v15 {}
@ -119,7 +119,7 @@ fn bytes_to_b64(bytes: &[u8]) -> String {
fn export_key_rsa(
format: ExportKeyFormat,
key_data: RawKeyData,
key_data: V8RawKeyData,
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {
match format {
ExportKeyFormat::Spki => {
@ -212,7 +212,7 @@ fn export_key_rsa(
fn export_key_symmetric(
format: ExportKeyFormat,
key_data: RawKeyData,
key_data: V8RawKeyData,
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {
match format {
ExportKeyFormat::JwkSecret => {
@ -228,7 +228,7 @@ fn export_key_symmetric(
fn export_key_ec(
format: ExportKeyFormat,
key_data: RawKeyData,
key_data: V8RawKeyData,
algorithm: ExportKeyAlgorithm,
named_curve: EcNamedCurve,
) -> Result<ExportKeyResult, deno_core::anyhow::Error> {

View file

@ -3,7 +3,7 @@
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::task::spawn_blocking;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use elliptic_curve::rand_core::OsRng;
use num_traits::FromPrimitive;
use once_cell::sync::Lazy;
@ -45,7 +45,7 @@ pub enum GenerateKeyOptions {
#[op]
pub async fn op_crypto_generate_key(
opts: GenerateKeyOptions,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let fun = || match opts {
GenerateKeyOptions::Rsa {
modulus_length,

View file

@ -2,7 +2,8 @@
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf;
use deno_core::JsBuffer;
use deno_core::ToJsBuffer;
use elliptic_curve::pkcs8::PrivateKeyInfo;
use p256::pkcs8::EncodePrivateKey;
use ring::signature::EcdsaKeyPair;
@ -18,9 +19,9 @@ use crate::shared::*;
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum KeyData {
Spki(ZeroCopyBuf),
Pkcs8(ZeroCopyBuf),
Raw(ZeroCopyBuf),
Spki(JsBuffer),
Pkcs8(JsBuffer),
Raw(JsBuffer),
JwkSecret {
k: String,
},
@ -73,17 +74,17 @@ pub enum ImportKeyOptions {
pub enum ImportKeyResult {
#[serde(rename_all = "camelCase")]
Rsa {
raw_data: RawKeyData,
raw_data: RustRawKeyData,
modulus_length: usize,
public_exponent: ZeroCopyBuf,
public_exponent: ToJsBuffer,
},
#[serde(rename_all = "camelCase")]
Ec { raw_data: RawKeyData },
Ec { raw_data: RustRawKeyData },
#[serde(rename_all = "camelCase")]
#[allow(dead_code)]
Aes { raw_data: RawKeyData },
Aes { raw_data: RustRawKeyData },
#[serde(rename_all = "camelCase")]
Hmac { raw_data: RawKeyData },
Hmac { raw_data: RustRawKeyData },
}
#[op]
@ -136,7 +137,7 @@ fn import_key_rsa_jwk(
let modulus_length = public_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Public(data.into()),
raw_data: RustRawKeyData::Public(data.into()),
modulus_length,
public_exponent,
})
@ -181,7 +182,7 @@ fn import_key_rsa_jwk(
let modulus_length = private_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Private(data.into()),
raw_data: RustRawKeyData::Private(data.into()),
modulus_length,
public_exponent,
})
@ -228,7 +229,7 @@ fn import_key_rsassa(
let modulus_length = public_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Public(data),
raw_data: RustRawKeyData::Public(data),
modulus_length,
public_exponent,
})
@ -267,7 +268,7 @@ fn import_key_rsassa(
let modulus_length = private_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Private(data),
raw_data: RustRawKeyData::Private(data),
modulus_length,
public_exponent,
})
@ -317,7 +318,7 @@ fn import_key_rsapss(
let modulus_length = public_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Public(data),
raw_data: RustRawKeyData::Public(data),
modulus_length,
public_exponent,
})
@ -356,7 +357,7 @@ fn import_key_rsapss(
let modulus_length = private_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Private(data),
raw_data: RustRawKeyData::Private(data),
modulus_length,
public_exponent,
})
@ -406,7 +407,7 @@ fn import_key_rsaoaep(
let modulus_length = public_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Public(data),
raw_data: RustRawKeyData::Public(data),
modulus_length,
public_exponent,
})
@ -445,7 +446,7 @@ fn import_key_rsaoaep(
let modulus_length = private_key.modulus.as_bytes().len() * 8;
Ok(ImportKeyResult::Rsa {
raw_data: RawKeyData::Private(data),
raw_data: RustRawKeyData::Private(data),
modulus_length,
public_exponent,
})
@ -513,7 +514,7 @@ fn import_key_ec_jwk(
let point_bytes = import_key_ec_jwk_to_point(x, y, named_curve)?;
Ok(ImportKeyResult::Ec {
raw_data: RawKeyData::Public(point_bytes.into()),
raw_data: RustRawKeyData::Public(point_bytes.into()),
})
}
KeyData::JwkPrivateEc { d, x, y } => {
@ -553,7 +554,7 @@ fn import_key_ec_jwk(
);
Ok(ImportKeyResult::Ec {
raw_data: RawKeyData::Private(pkcs8_der.as_bytes().to_vec().into()),
raw_data: RustRawKeyData::Private(pkcs8_der.as_bytes().to_vec().into()),
})
}
_ => unreachable!(),
@ -606,7 +607,7 @@ fn import_key_ec(
_ => return Err(not_supported_error("Unsupported named curve")),
};
Ok(ImportKeyResult::Ec {
raw_data: RawKeyData::Public(data),
raw_data: RustRawKeyData::Public(data.to_vec().into()),
})
}
KeyData::Pkcs8(data) => {
@ -660,7 +661,7 @@ fn import_key_ec(
}
Ok(ImportKeyResult::Ec {
raw_data: RawKeyData::Private(data),
raw_data: RustRawKeyData::Private(data.to_vec().into()),
})
}
KeyData::Spki(data) => {
@ -744,7 +745,7 @@ fn import_key_ec(
}
Ok(ImportKeyResult::Ec {
raw_data: RawKeyData::Public(encoded_key.into()),
raw_data: RustRawKeyData::Public(encoded_key.into()),
})
}
KeyData::JwkPublicEc { .. } | KeyData::JwkPrivateEc { .. } => {
@ -760,7 +761,7 @@ fn import_key_aes(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
let data = base64::decode_config(k, URL_SAFE_FORGIVING)
.map_err(|_| data_error("invalid key data"))?;
ImportKeyResult::Hmac {
raw_data: RawKeyData::Secret(data.into()),
raw_data: RustRawKeyData::Secret(data.into()),
}
}
_ => return Err(unsupported_format()),
@ -773,7 +774,7 @@ fn import_key_hmac(key_data: KeyData) -> Result<ImportKeyResult, AnyError> {
let data = base64::decode_config(k, URL_SAFE_FORGIVING)
.map_err(|_| data_error("invalid key data"))?;
ImportKeyResult::Hmac {
raw_data: RawKeyData::Secret(data.into()),
raw_data: RustRawKeyData::Secret(data.into()),
}
}
_ => return Err(unsupported_format()),

View file

@ -9,10 +9,11 @@ use deno_core::error::not_supported;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ToJsBuffer;
use deno_core::task::spawn_blocking;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use serde::Deserialize;
use shared::operation_error;
@ -69,7 +70,7 @@ use crate::key::Algorithm;
use crate::key::CryptoHash;
use crate::key::CryptoNamedCurve;
use crate::key::HkdfOutput;
use crate::shared::RawKeyData;
use crate::shared::V8RawKeyData;
deno_core::extension!(deno_crypto,
deps = [ deno_webidl, deno_web ],
@ -118,13 +119,13 @@ deno_core::extension!(deno_crypto,
#[op]
pub fn op_crypto_base64url_decode(
data: String,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let data: Vec<u8> = base64::decode_config(data, base64::URL_SAFE_NO_PAD)?;
Ok(data.into())
}
#[op]
pub fn op_crypto_base64url_encode(data: ZeroCopyBuf) -> String {
pub fn op_crypto_base64url_encode(data: JsBuffer) -> String {
let data: String = base64::encode_config(data, base64::URL_SAFE_NO_PAD);
data
}
@ -172,7 +173,7 @@ pub enum KeyType {
#[serde(rename_all = "lowercase")]
pub struct KeyData {
r#type: KeyType,
data: ZeroCopyBuf,
data: JsBuffer,
}
#[derive(Deserialize)]
@ -188,8 +189,8 @@ pub struct SignArg {
#[op]
pub async fn op_crypto_sign_key(
args: SignArg,
zero_copy: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
zero_copy: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let data = &*zero_copy;
let algorithm = args.algorithm;
@ -297,14 +298,14 @@ pub struct VerifyArg {
key: KeyData,
algorithm: Algorithm,
hash: Option<CryptoHash>,
signature: ZeroCopyBuf,
signature: JsBuffer,
named_curve: Option<CryptoNamedCurve>,
}
#[op]
pub async fn op_crypto_verify_key(
args: VerifyArg,
zero_copy: ZeroCopyBuf,
zero_copy: JsBuffer,
) -> Result<bool, AnyError> {
let data = &*zero_copy;
let algorithm = args.algorithm;
@ -414,14 +415,14 @@ pub struct DeriveKeyArg {
public_key: Option<KeyData>,
named_curve: Option<CryptoNamedCurve>,
// HKDF
info: Option<ZeroCopyBuf>,
info: Option<JsBuffer>,
}
#[op]
pub async fn op_crypto_derive_bits(
args: DeriveKeyArg,
zero_copy: Option<ZeroCopyBuf>,
) -> Result<ZeroCopyBuf, AnyError> {
zero_copy: Option<JsBuffer>,
) -> Result<ToJsBuffer, AnyError> {
let algorithm = args.algorithm;
match algorithm {
Algorithm::Pbkdf2 => {
@ -601,8 +602,8 @@ pub fn op_crypto_random_uuid(state: &mut OpState) -> Result<String, AnyError> {
#[op]
pub async fn op_crypto_subtle_digest(
algorithm: CryptoHash,
data: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
data: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let output = spawn_blocking(move || {
digest::digest(algorithm.into(), &data)
.as_ref()
@ -617,15 +618,15 @@ pub async fn op_crypto_subtle_digest(
#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct WrapUnwrapKeyArg {
key: RawKeyData,
key: V8RawKeyData,
algorithm: Algorithm,
}
#[op]
pub fn op_crypto_wrap_key(
args: WrapUnwrapKeyArg,
data: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
data: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let algorithm = args.algorithm;
match algorithm {
@ -653,8 +654,8 @@ pub fn op_crypto_wrap_key(
#[op]
pub fn op_crypto_unwrap_key(
args: WrapUnwrapKeyArg,
data: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
data: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let algorithm = args.algorithm;
match algorithm {
Algorithm::AesKw => {

View file

@ -5,7 +5,8 @@ use std::borrow::Cow;
use deno_core::error::custom_error;
use deno_core::error::type_error;
use deno_core::error::AnyError;
use deno_core::ZeroCopyBuf;
use deno_core::JsBuffer;
use deno_core::ToJsBuffer;
use elliptic_curve::sec1::ToEncodedPoint;
use rsa::pkcs1::DecodeRsaPrivateKey;
use rsa::pkcs1::EncodeRsaPublicKey;
@ -46,19 +47,27 @@ pub enum EcNamedCurve {
P521,
}
#[derive(Serialize, Deserialize)]
#[derive(Deserialize)]
#[serde(rename_all = "lowercase", tag = "type", content = "data")]
pub enum RawKeyData {
Secret(ZeroCopyBuf),
Private(ZeroCopyBuf),
Public(ZeroCopyBuf),
pub enum V8RawKeyData {
Secret(JsBuffer),
Private(JsBuffer),
Public(JsBuffer),
}
impl RawKeyData {
#[derive(Serialize)]
#[serde(rename_all = "lowercase", tag = "type", content = "data")]
pub enum RustRawKeyData {
Secret(ToJsBuffer),
Private(ToJsBuffer),
Public(ToJsBuffer),
}
impl V8RawKeyData {
pub fn as_rsa_public_key(&self) -> Result<Cow<'_, [u8]>, AnyError> {
match self {
RawKeyData::Public(data) => Ok(Cow::Borrowed(data)),
RawKeyData::Private(data) => {
V8RawKeyData::Public(data) => Ok(Cow::Borrowed(data)),
V8RawKeyData::Private(data) => {
let private_key = RsaPrivateKey::from_pkcs1_der(data)
.map_err(|_| type_error("expected valid private key"))?;
@ -75,55 +84,55 @@ impl RawKeyData {
pub fn as_rsa_private_key(&self) -> Result<&[u8], AnyError> {
match self {
RawKeyData::Private(data) => Ok(data),
V8RawKeyData::Private(data) => Ok(data),
_ => Err(type_error("expected private key")),
}
}
pub fn as_secret_key(&self) -> Result<&[u8], AnyError> {
match self {
RawKeyData::Secret(data) => Ok(data),
V8RawKeyData::Secret(data) => Ok(data),
_ => Err(type_error("expected secret key")),
}
}
pub fn as_ec_public_key_p256(&self) -> Result<p256::EncodedPoint, AnyError> {
match self {
RawKeyData::Public(data) => {
V8RawKeyData::Public(data) => {
// public_key is a serialized EncodedPoint
p256::EncodedPoint::from_bytes(data)
.map_err(|_| type_error("expected valid public EC key"))
}
RawKeyData::Private(data) => {
V8RawKeyData::Private(data) => {
let signing_key = p256::SecretKey::from_pkcs8_der(data)
.map_err(|_| type_error("expected valid private EC key"))?;
Ok(signing_key.public_key().to_encoded_point(false))
}
// Should never reach here.
RawKeyData::Secret(_) => unreachable!(),
V8RawKeyData::Secret(_) => unreachable!(),
}
}
pub fn as_ec_public_key_p384(&self) -> Result<p384::EncodedPoint, AnyError> {
match self {
RawKeyData::Public(data) => {
V8RawKeyData::Public(data) => {
// public_key is a serialized EncodedPoint
p384::EncodedPoint::from_bytes(data)
.map_err(|_| type_error("expected valid public EC key"))
}
RawKeyData::Private(data) => {
V8RawKeyData::Private(data) => {
let signing_key = p384::SecretKey::from_pkcs8_der(data)
.map_err(|_| type_error("expected valid private EC key"))?;
Ok(signing_key.public_key().to_encoded_point(false))
}
// Should never reach here.
RawKeyData::Secret(_) => unreachable!(),
V8RawKeyData::Secret(_) => unreachable!(),
}
}
pub fn as_ec_private_key(&self) -> Result<&[u8], AnyError> {
match self {
RawKeyData::Private(data) => Ok(data),
V8RawKeyData::Private(data) => Ok(data),
_ => Err(type_error("expected private key")),
}
}

View file

@ -3,7 +3,7 @@
use curve25519_dalek::montgomery::MontgomeryPoint;
use deno_core::error::AnyError;
use deno_core::op;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use elliptic_curve::pkcs8::PrivateKeyInfo;
use elliptic_curve::subtle::ConstantTimeEq;
use rand::rngs::OsRng;
@ -101,7 +101,7 @@ pub fn op_crypto_import_pkcs8_x25519(key_data: &[u8], out: &mut [u8]) -> bool {
#[op]
pub fn op_crypto_export_spki_x25519(
pubkey: &[u8],
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let key_info = spki::SubjectPublicKeyInfo {
algorithm: spki::AlgorithmIdentifier {
// id-X25519
@ -116,7 +116,7 @@ pub fn op_crypto_export_spki_x25519(
#[op]
pub fn op_crypto_export_pkcs8_x25519(
pkey: &[u8],
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
// This should probably use OneAsymmetricKey instead
let pk_info = rsa::pkcs8::PrivateKeyInfo {
public_key: None,

View file

@ -32,11 +32,11 @@ use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::CancelTryFuture;
use deno_core::Canceled;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_tls::rustls::RootCertStore;
use deno_tls::Proxy;
use deno_tls::RootCertStoreProvider;
@ -232,7 +232,7 @@ pub fn op_fetch<FP>(
client_rid: Option<u32>,
has_body: bool,
body_length: Option<u64>,
data: Option<ZeroCopyBuf>,
data: Option<JsBuffer>,
) -> Result<FetchReturn, AnyError>
where
FP: FetchPermissions + 'static,

View file

@ -14,9 +14,10 @@ use deno_core::error::AnyError;
use deno_core::op;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use deno_io::fs::FileResource;
use deno_io::fs::FsError;
use deno_io::fs::FsStat;
@ -1077,7 +1078,7 @@ fn op_fs_write_file_sync<P>(
append: bool,
create: bool,
create_new: bool,
data: ZeroCopyBuf,
data: JsBuffer,
) -> Result<(), AnyError>
where
P: FsPermissions + 'static,
@ -1104,7 +1105,7 @@ async fn op_fs_write_file_async<P>(
append: bool,
create: bool,
create_new: bool,
data: ZeroCopyBuf,
data: JsBuffer,
cancel_rid: Option<ResourceId>,
) -> Result<(), AnyError>
where
@ -1144,7 +1145,7 @@ where
fn op_fs_read_file_sync<P>(
state: &mut OpState,
path: String,
) -> Result<ZeroCopyBuf, AnyError>
) -> Result<ToJsBuffer, AnyError>
where
P: FsPermissions + 'static,
{
@ -1164,7 +1165,7 @@ async fn op_fs_read_file_async<P>(
state: Rc<RefCell<OpState>>,
path: String,
cancel_rid: Option<ResourceId>,
) -> Result<ZeroCopyBuf, AnyError>
) -> Result<ToJsBuffer, AnyError>
where
P: FsPermissions + 'static,
{

View file

@ -28,12 +28,12 @@ use deno_core::ByteString;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::CancelTryFuture;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::StringOrBuffer;
use deno_core::ZeroCopyBuf;
use deno_net::raw::NetworkStream;
use deno_websocket::ws_create_server_stream;
use flate2::write::GzEncoder;
@ -880,7 +880,7 @@ async fn op_http_write_resource(
async fn op_http_write(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
buf: ZeroCopyBuf,
buf: JsBuffer,
) -> Result<(), AnyError> {
let stream = state
.borrow()

View file

@ -19,10 +19,11 @@ use deno_core::op;
use deno_core::serde_v8::AnyValue;
use deno_core::serde_v8::BigInt;
use deno_core::ByteString;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use serde::Deserialize;
use serde::Serialize;
@ -122,7 +123,8 @@ impl From<AnyValue> for KeyPart {
AnyValue::Number(n) => KeyPart::Float(n),
AnyValue::BigInt(n) => KeyPart::Int(n),
AnyValue::String(s) => KeyPart::String(s),
AnyValue::Buffer(buf) => KeyPart::Bytes(buf.to_vec()),
AnyValue::V8Buffer(buf) => KeyPart::Bytes(buf.to_vec()),
AnyValue::RustBuffer(_) => unreachable!(),
}
}
}
@ -135,51 +137,61 @@ impl From<KeyPart> for AnyValue {
KeyPart::Float(n) => AnyValue::Number(n),
KeyPart::Int(n) => AnyValue::BigInt(n),
KeyPart::String(s) => AnyValue::String(s),
KeyPart::Bytes(buf) => AnyValue::Buffer(buf.into()),
KeyPart::Bytes(buf) => AnyValue::RustBuffer(buf.into()),
}
}
}
#[derive(Debug, Deserialize, Serialize)]
#[derive(Debug, Deserialize)]
#[serde(tag = "kind", content = "value", rename_all = "snake_case")]
enum V8Value {
V8(ZeroCopyBuf),
Bytes(ZeroCopyBuf),
enum FromV8Value {
V8(JsBuffer),
Bytes(JsBuffer),
U64(BigInt),
}
impl TryFrom<V8Value> for Value {
#[derive(Debug, Serialize)]
#[serde(tag = "kind", content = "value", rename_all = "snake_case")]
enum ToV8Value {
V8(ToJsBuffer),
Bytes(ToJsBuffer),
U64(BigInt),
}
impl TryFrom<FromV8Value> for Value {
type Error = AnyError;
fn try_from(value: V8Value) -> Result<Self, AnyError> {
fn try_from(value: FromV8Value) -> Result<Self, AnyError> {
Ok(match value {
V8Value::V8(buf) => Value::V8(buf.to_vec()),
V8Value::Bytes(buf) => Value::Bytes(buf.to_vec()),
V8Value::U64(n) => Value::U64(num_bigint::BigInt::from(n).try_into()?),
FromV8Value::V8(buf) => Value::V8(buf.to_vec()),
FromV8Value::Bytes(buf) => Value::Bytes(buf.to_vec()),
FromV8Value::U64(n) => {
Value::U64(num_bigint::BigInt::from(n).try_into()?)
}
})
}
}
impl From<Value> for V8Value {
impl From<Value> for ToV8Value {
fn from(value: Value) -> Self {
match value {
Value::V8(buf) => V8Value::V8(buf.into()),
Value::Bytes(buf) => V8Value::Bytes(buf.into()),
Value::U64(n) => V8Value::U64(num_bigint::BigInt::from(n).into()),
Value::V8(buf) => ToV8Value::V8(buf.into()),
Value::Bytes(buf) => ToV8Value::Bytes(buf.into()),
Value::U64(n) => ToV8Value::U64(num_bigint::BigInt::from(n).into()),
}
}
}
#[derive(Deserialize, Serialize)]
struct V8KvEntry {
#[derive(Serialize)]
struct ToV8KvEntry {
key: KvKey,
value: V8Value,
value: ToV8Value,
versionstamp: ByteString,
}
impl TryFrom<KvEntry> for V8KvEntry {
impl TryFrom<KvEntry> for ToV8KvEntry {
type Error = AnyError;
fn try_from(entry: KvEntry) -> Result<Self, AnyError> {
Ok(V8KvEntry {
Ok(ToV8KvEntry {
key: decode_key(&entry.key)?
.0
.into_iter()
@ -223,7 +235,7 @@ async fn op_kv_snapshot_read<DBH>(
rid: ResourceId,
ranges: Vec<SnapshotReadRange>,
consistency: V8Consistency,
) -> Result<Vec<Vec<V8KvEntry>>, AnyError>
) -> Result<Vec<Vec<ToV8KvEntry>>, AnyError>
where
DBH: DatabaseHandler + 'static,
{
@ -301,7 +313,7 @@ impl<QMH: QueueMessageHandle + 'static> Resource for QueueMessageResource<QMH> {
async fn op_kv_dequeue_next_message<DBH>(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
) -> Result<(ZeroCopyBuf, ResourceId), AnyError>
) -> Result<(ToJsBuffer, ResourceId), AnyError>
where
DBH: DatabaseHandler + 'static,
{
@ -364,7 +376,7 @@ impl TryFrom<V8KvCheck> for KvCheck {
}
}
type V8KvMutation = (KvKey, String, Option<V8Value>);
type V8KvMutation = (KvKey, String, Option<FromV8Value>);
impl TryFrom<V8KvMutation> for KvMutation {
type Error = AnyError;
@ -389,7 +401,7 @@ impl TryFrom<V8KvMutation> for KvMutation {
}
}
type V8Enqueue = (ZeroCopyBuf, u64, Vec<KvKey>, Option<Vec<u32>>);
type V8Enqueue = (JsBuffer, u64, Vec<KvKey>, Option<Vec<u32>>);
impl TryFrom<V8Enqueue> for Enqueue {
type Error = AnyError;

View file

@ -15,11 +15,11 @@ use deno_core::AsyncRefCell;
use deno_core::ByteString;
use deno_core::CancelHandle;
use deno_core::CancelTryFuture;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use serde::Deserialize;
use serde::Serialize;
use socket2::Domain;
@ -109,7 +109,7 @@ async fn op_net_accept_tcp(
async fn op_net_recv_udp(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
mut buf: ZeroCopyBuf,
mut buf: JsBuffer,
) -> Result<(usize, IpAddr), AnyError> {
let resource = state
.borrow_mut()
@ -130,7 +130,7 @@ async fn op_net_send_udp<NP>(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
addr: IpAddr,
zero_copy: ZeroCopyBuf,
zero_copy: JsBuffer,
) -> Result<usize, AnyError>
where
NP: NetPermissions + 'static,

View file

@ -9,11 +9,11 @@ use deno_core::op;
use deno_core::AsyncRefCell;
use deno_core::CancelHandle;
use deno_core::CancelTryFuture;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use serde::Deserialize;
use serde::Serialize;
use std::borrow::Cow;
@ -138,7 +138,7 @@ where
pub async fn op_net_recv_unixpacket(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
mut buf: ZeroCopyBuf,
mut buf: JsBuffer,
) -> Result<(usize, Option<String>), AnyError> {
let resource = state
.borrow()
@ -160,7 +160,7 @@ async fn op_net_send_unixpacket<NP>(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
path: String,
zero_copy: ZeroCopyBuf,
zero_copy: JsBuffer,
) -> Result<usize, AnyError>
where
NP: NetPermissions + 'static,

View file

@ -5,10 +5,11 @@ use deno_core::error::AnyError;
use deno_core::op;
use deno_core::serde_v8;
use deno_core::task::spawn_blocking;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ResourceId;
use deno_core::StringOrBuffer;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use hkdf::Hkdf;
use num_bigint::BigInt;
use num_bigint_dig::BigUint;
@ -115,7 +116,7 @@ pub fn op_node_hash_update_str(
pub fn op_node_hash_digest(
state: &mut OpState,
rid: ResourceId,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let context = state.resource_table.take::<digest::Context>(rid)?;
let context = Rc::try_unwrap(context)
.map_err(|_| type_error("Hash context is already in use"))?;
@ -148,7 +149,7 @@ pub fn op_node_private_encrypt(
key: StringOrBuffer,
msg: StringOrBuffer,
padding: u32,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
let mut rng = rand::thread_rng();
@ -172,7 +173,7 @@ pub fn op_node_private_decrypt(
key: StringOrBuffer,
msg: StringOrBuffer,
padding: u32,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let key = RsaPrivateKey::from_pkcs8_pem((&key).try_into()?)?;
match padding {
@ -195,7 +196,7 @@ pub fn op_node_public_encrypt(
key: StringOrBuffer,
msg: StringOrBuffer,
padding: u32,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let key = RsaPublicKey::from_public_key_pem((&key).try_into()?)?;
let mut rng = rand::thread_rng();
@ -307,7 +308,7 @@ pub fn op_node_sign(
key: StringOrBuffer,
key_type: &str,
key_format: &str,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
match key_type {
"rsa" => {
use rsa::pkcs1v15::SigningKey;
@ -456,7 +457,7 @@ pub async fn op_node_pbkdf2_async(
iterations: u32,
digest: String,
keylen: usize,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
spawn_blocking(move || {
let mut derived_key = vec![0; keylen];
pbkdf2_sync(&password, &salt, iterations, &digest, &mut derived_key)
@ -471,7 +472,7 @@ pub fn op_node_generate_secret(buf: &mut [u8]) {
}
#[op]
pub async fn op_node_generate_secret_async(len: i32) -> ZeroCopyBuf {
pub async fn op_node_generate_secret_async(len: i32) -> ToJsBuffer {
spawn_blocking(move || {
let mut buf = vec![0u8; len as usize];
rand::thread_rng().fill(&mut buf[..]);
@ -525,11 +526,11 @@ pub fn op_node_hkdf(
#[op]
pub async fn op_node_hkdf_async(
hash: String,
ikm: ZeroCopyBuf,
salt: ZeroCopyBuf,
info: ZeroCopyBuf,
ikm: JsBuffer,
salt: JsBuffer,
info: JsBuffer,
okm_len: usize,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
spawn_blocking(move || {
let mut okm = vec![0u8; okm_len];
hkdf_sync(&hash, &ikm, &salt, &info, &mut okm)?;
@ -546,7 +547,7 @@ use self::primes::Prime;
fn generate_rsa(
modulus_length: usize,
public_exponent: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
let mut rng = rand::thread_rng();
let private_key = RsaPrivateKey::new_with_exp(
&mut rng,
@ -564,7 +565,7 @@ fn generate_rsa(
pub fn op_node_generate_rsa(
modulus_length: usize,
public_exponent: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
generate_rsa(modulus_length, public_exponent)
}
@ -572,14 +573,14 @@ pub fn op_node_generate_rsa(
pub async fn op_node_generate_rsa_async(
modulus_length: usize,
public_exponent: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(move || generate_rsa(modulus_length, public_exponent)).await?
}
fn dsa_generate(
modulus_length: usize,
divisor_length: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
let mut rng = rand::thread_rng();
use dsa::pkcs8::EncodePrivateKey;
use dsa::pkcs8::EncodePublicKey;
@ -618,7 +619,7 @@ fn dsa_generate(
pub fn op_node_dsa_generate(
modulus_length: usize,
divisor_length: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
dsa_generate(modulus_length, divisor_length)
}
@ -626,13 +627,13 @@ pub fn op_node_dsa_generate(
pub async fn op_node_dsa_generate_async(
modulus_length: usize,
divisor_length: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(move || dsa_generate(modulus_length, divisor_length)).await?
}
fn ec_generate(
named_curve: &str,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
use ring::signature::EcdsaKeyPair;
use ring::signature::KeyPair;
@ -658,18 +659,18 @@ fn ec_generate(
#[op]
pub fn op_node_ec_generate(
named_curve: &str,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
ec_generate(named_curve)
}
#[op]
pub async fn op_node_ec_generate_async(
named_curve: String,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(move || ec_generate(&named_curve)).await?
}
fn ed25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
fn ed25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
use ring::signature::Ed25519KeyPair;
use ring::signature::KeyPair;
@ -685,18 +686,18 @@ fn ed25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
}
#[op]
pub fn op_node_ed25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError>
pub fn op_node_ed25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError>
{
ed25519_generate()
}
#[op]
pub async fn op_node_ed25519_generate_async(
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(ed25519_generate).await?
}
fn x25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
fn x25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
// u-coordinate of the base point.
const X25519_BASEPOINT_BYTES: [u8; 32] = [
9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@ -720,20 +721,19 @@ fn x25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
}
#[op]
pub fn op_node_x25519_generate() -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError>
{
pub fn op_node_x25519_generate() -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
x25519_generate()
}
#[op]
pub async fn op_node_x25519_generate_async(
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(x25519_generate).await?
}
fn dh_generate_group(
group_name: &str,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
let dh = match group_name {
"modp5" => dh::DiffieHellman::group::<dh::Modp1536>(),
"modp14" => dh::DiffieHellman::group::<dh::Modp2048>(),
@ -753,14 +753,14 @@ fn dh_generate_group(
#[op]
pub fn op_node_dh_generate_group(
group_name: &str,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
dh_generate_group(group_name)
}
#[op]
pub async fn op_node_dh_generate_group_async(
group_name: String,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(move || dh_generate_group(&group_name)).await?
}
@ -768,7 +768,7 @@ fn dh_generate(
prime: Option<&[u8]>,
prime_len: usize,
generator: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
let prime = prime
.map(|p| p.into())
.unwrap_or_else(|| Prime::generate(prime_len));
@ -785,26 +785,26 @@ pub fn op_node_dh_generate(
prime: Option<&[u8]>,
prime_len: usize,
generator: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
dh_generate(prime, prime_len, generator)
}
// TODO(lev): This duplication should be avoided.
#[op]
pub fn op_node_dh_generate2(
prime: ZeroCopyBuf,
prime: JsBuffer,
prime_len: usize,
generator: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
dh_generate(Some(prime).as_deref(), prime_len, generator)
}
#[op]
pub fn op_node_dh_compute_secret(
prime: ZeroCopyBuf,
private_key: ZeroCopyBuf,
their_public_key: ZeroCopyBuf,
) -> Result<ZeroCopyBuf, AnyError> {
prime: JsBuffer,
private_key: JsBuffer,
their_public_key: JsBuffer,
) -> Result<ToJsBuffer, AnyError> {
let pubkey: BigUint = BigUint::from_bytes_be(their_public_key.as_ref());
let privkey: BigUint = BigUint::from_bytes_be(private_key.as_ref());
let primei: BigUint = BigUint::from_bytes_be(prime.as_ref());
@ -815,10 +815,10 @@ pub fn op_node_dh_compute_secret(
#[op]
pub async fn op_node_dh_generate_async(
prime: Option<ZeroCopyBuf>,
prime: Option<JsBuffer>,
prime_len: usize,
generator: usize,
) -> Result<(ZeroCopyBuf, ZeroCopyBuf), AnyError> {
) -> Result<(ToJsBuffer, ToJsBuffer), AnyError> {
spawn_blocking(move || dh_generate(prime.as_deref(), prime_len, generator))
.await?
}
@ -895,7 +895,7 @@ pub async fn op_node_scrypt_async(
block_size: u32,
parallelization: u32,
maxmem: u32,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
spawn_blocking(move || {
let mut output_buffer = vec![0u8; keylen as usize];
let res = scrypt(
@ -963,7 +963,7 @@ pub fn op_node_ecdh_generate_keys(
#[op]
pub fn op_node_ecdh_compute_secret(
curve: &str,
this_priv: Option<ZeroCopyBuf>,
this_priv: Option<JsBuffer>,
their_pub: &mut [u8],
secret: &mut [u8],
) -> Result<(), AnyError> {
@ -1079,18 +1079,18 @@ pub fn op_node_ecdh_compute_public_key(
}
#[inline]
fn gen_prime(size: usize) -> ZeroCopyBuf {
fn gen_prime(size: usize) -> ToJsBuffer {
primes::Prime::generate(size).0.to_bytes_be().into()
}
#[op]
pub fn op_node_gen_prime(size: usize) -> ZeroCopyBuf {
pub fn op_node_gen_prime(size: usize) -> ToJsBuffer {
gen_prime(size)
}
#[op]
pub async fn op_node_gen_prime_async(
size: usize,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
Ok(spawn_blocking(move || gen_prime(size)).await?)
}

View file

@ -8,8 +8,8 @@ use deno_core::op;
use deno_core::url::form_urlencoded;
use deno_core::url::quirks;
use deno_core::url::Url;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use std::path::PathBuf;
use crate::urlpattern::op_urlpattern_parse;
@ -220,7 +220,7 @@ pub fn op_url_reparse(
#[op]
pub fn op_url_parse_search_params(
args: Option<String>,
zero_copy: Option<ZeroCopyBuf>,
zero_copy: Option<JsBuffer>,
) -> Result<Vec<(String, String)>, AnyError> {
let params = match (args, zero_copy) {
(None, Some(zero_copy)) => form_urlencoded::parse(&zero_copy)

View file

@ -12,8 +12,9 @@ use deno_core::error::AnyError;
use deno_core::op;
use deno_core::parking_lot::Mutex;
use deno_core::url::Url;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use serde::Deserialize;
use serde::Serialize;
use uuid::Uuid;
@ -160,7 +161,7 @@ impl BlobPart for SlicedBlobPart {
}
#[op]
pub fn op_blob_create_part(state: &mut OpState, data: ZeroCopyBuf) -> Uuid {
pub fn op_blob_create_part(state: &mut OpState, data: JsBuffer) -> Uuid {
let blob_store = state.borrow::<BlobStore>();
let part = InMemoryBlobPart(data.to_vec());
blob_store.insert_part(Arc::new(part))
@ -203,7 +204,7 @@ pub fn op_blob_slice_part(
pub async fn op_blob_read_part(
state: Rc<RefCell<OpState>>,
id: Uuid,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let part = {
let state = state.borrow();
let blob_store = state.borrow::<BlobStore>();
@ -211,7 +212,7 @@ pub async fn op_blob_read_part(
}
.ok_or_else(|| type_error("Blob part not found"))?;
let buf = part.read().await?;
Ok(ZeroCopyBuf::from(buf.to_vec()))
Ok(ToJsBuffer::from(buf.to_vec()))
}
#[op]

View file

@ -5,7 +5,7 @@ use deno_core::op;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use flate2::write::DeflateDecoder;
use flate2::write::DeflateEncoder;
use flate2::write::GzDecoder;
@ -69,7 +69,7 @@ pub fn op_compression_write(
state: &mut OpState,
rid: ResourceId,
input: &[u8],
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let resource = state.resource_table.get::<CompressionResource>(rid)?;
let mut inner = resource.0.borrow_mut();
let out: Vec<u8> = match &mut *inner {
@ -112,7 +112,7 @@ pub fn op_compression_write(
pub fn op_compression_finish(
state: &mut OpState,
rid: ResourceId,
) -> Result<ZeroCopyBuf, AnyError> {
) -> Result<ToJsBuffer, AnyError> {
let resource = state.resource_table.take::<CompressionResource>(rid)?;
let resource = Rc::try_unwrap(resource).unwrap();
let inner = resource.0.into_inner();

View file

@ -18,8 +18,8 @@ use deno_core::CancelHandle;
use deno_core::OpState;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ToJsBuffer;
use deno_core::U16String;
use deno_core::ZeroCopyBuf;
use encoding_rs::CoderResult;
use encoding_rs::Decoder;
@ -123,7 +123,7 @@ deno_core::extension!(deno_web,
);
#[op]
fn op_base64_decode(input: String) -> Result<ZeroCopyBuf, AnyError> {
fn op_base64_decode(input: String) -> Result<ToJsBuffer, AnyError> {
let mut s = input.into_bytes();
let decoded_len = forgiving_base64_decode_inplace(&mut s)?;
s.truncate(decoded_len);

View file

@ -11,11 +11,12 @@ use deno_core::AsyncRefCell;
use deno_core::ByteString;
use deno_core::CancelFuture;
use deno_core::CancelHandle;
use deno_core::JsBuffer;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use deno_net::raw::NetworkStream;
use deno_tls::create_client_config;
use deno_tls::RootCertStoreProvider;
@ -406,11 +407,7 @@ pub fn ws_create_server_stream(
}
#[op(fast)]
pub fn op_ws_send_binary(
state: &mut OpState,
rid: ResourceId,
data: ZeroCopyBuf,
) {
pub fn op_ws_send_binary(state: &mut OpState, rid: ResourceId, data: JsBuffer) {
let resource = state.resource_table.get::<ServerWebSocket>(rid).unwrap();
let data = data.to_vec();
let len = data.len();
@ -454,7 +451,7 @@ pub fn op_ws_send_text(state: &mut OpState, rid: ResourceId, data: String) {
pub async fn op_ws_send_binary_async(
state: Rc<RefCell<OpState>>,
rid: ResourceId,
data: ZeroCopyBuf,
data: JsBuffer,
) -> Result<(), AnyError> {
let resource = state
.borrow_mut()
@ -547,7 +544,7 @@ pub async fn op_ws_close(
}
#[op]
pub fn op_ws_get_buffer(state: &mut OpState, rid: ResourceId) -> ZeroCopyBuf {
pub fn op_ws_get_buffer(state: &mut OpState, rid: ResourceId) -> ToJsBuffer {
let resource = state.resource_table.get::<ServerWebSocket>(rid).unwrap();
resource.buffer.take().unwrap().into()
}

View file

@ -11,7 +11,7 @@ use deno_core::op;
use deno_core::OpState;
use deno_core::RcRef;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use deno_http::http_create_conn_resource;
use deno_http::HttpRequestReader;
use deno_http::HttpStreamResource;
@ -93,7 +93,7 @@ fn op_http_start(
pub struct HttpUpgradeResult {
conn_rid: ResourceId,
conn_type: &'static str,
read_buf: ZeroCopyBuf,
read_buf: ToJsBuffer,
}
#[op]

View file

@ -12,7 +12,7 @@ use deno_core::OpState;
use deno_core::RcRef;
use deno_core::Resource;
use deno_core::ResourceId;
use deno_core::ZeroCopyBuf;
use deno_core::ToJsBuffer;
use deno_io::fs::FileResource;
use deno_io::ChildStderrResource;
use deno_io::ChildStdinResource;
@ -198,8 +198,8 @@ impl TryFrom<ExitStatus> for ChildStatus {
#[serde(rename_all = "camelCase")]
pub struct SpawnOutput {
status: ChildStatus,
stdout: Option<ZeroCopyBuf>,
stderr: Option<ZeroCopyBuf>,
stdout: Option<ToJsBuffer>,
stderr: Option<ToJsBuffer>,
}
fn create_command(

View file

@ -18,9 +18,9 @@ use crate::AnyValue;
use crate::BigInt;
use crate::ByteString;
use crate::DetachedBuffer;
use crate::JsBuffer;
use crate::StringOrBuffer;
use crate::U16String;
use crate::ZeroCopyBuf;
pub struct Deserializer<'a, 'b, 's> {
input: v8::Local<'a, v8::Value>,
@ -337,8 +337,8 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
V: Visitor<'de>,
{
match name {
ZeroCopyBuf::MAGIC_NAME => {
visit_magic(visitor, ZeroCopyBuf::from_v8(self.scope, self.input)?)
JsBuffer::MAGIC_NAME => {
visit_magic(visitor, JsBuffer::from_v8(self.scope, self.input)?)
}
DetachedBuffer::MAGIC_NAME => {
visit_magic(visitor, DetachedBuffer::from_v8(self.scope, self.input)?)
@ -452,7 +452,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
where
V: Visitor<'de>,
{
magic::buffer::ZeroCopyBuf::from_v8(self.scope, self.input)
magic::buffer::JsBuffer::from_v8(self.scope, self.input)
.and_then(|zb| visitor.visit_bytes(&zb))
}
@ -460,7 +460,7 @@ impl<'de, 'a, 'b, 's, 'x> de::Deserializer<'de>
where
V: Visitor<'de>,
{
magic::buffer::ZeroCopyBuf::from_v8(self.scope, self.input)
magic::buffer::JsBuffer::from_v8(self.scope, self.input)
.and_then(|zb| visitor.visit_byte_buf(Vec::from(&*zb)))
}
}

View file

@ -17,7 +17,8 @@ pub use error::Result;
pub use keys::KeyCache;
pub use magic::any_value::AnyValue;
pub use magic::bigint::BigInt;
pub use magic::buffer::ZeroCopyBuf;
pub use magic::buffer::JsBuffer;
pub use magic::buffer::ToJsBuffer;
pub use magic::bytestring::ByteString;
pub use magic::detached_buffer::DetachedBuffer;
pub use magic::string_or_buffer::StringOrBuffer;

View file

@ -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))

View file

@ -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()
f.debug_list().entries(self.0.as_ref().iter()).finish()
}
}
impl ZeroCopyBuf {
pub fn empty() -> Self {
ZeroCopyBuf::ToV8(Some(vec![0_u8; 0].into_boxed_slice()))
}
}
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 From<Box<[u8]>> for ZeroCopyBuf {
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 {
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()
}
}
}
}

View file

@ -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));

View file

@ -19,9 +19,8 @@ use crate::BigInt;
use crate::ByteString;
use crate::DetachedBuffer;
use crate::ExternalPointer;
use crate::StringOrBuffer;
use crate::ToJsBuffer;
use crate::U16String;
use crate::ZeroCopyBuf;
type JsValue<'s> = v8::Local<'s, v8::Value>;
type JsResult<'s> = Result<JsValue<'s>>;
@ -274,12 +273,11 @@ impl<'a, 'b, 'c, T: MagicType + ToV8> ser::SerializeStruct
pub enum StructSerializers<'a, 'b, 'c> {
ExternalPointer(MagicalSerializer<'a, 'b, 'c, magic::ExternalPointer>),
Magic(MagicalSerializer<'a, 'b, 'c, magic::Value<'a>>),
ZeroCopyBuf(MagicalSerializer<'a, 'b, 'c, ZeroCopyBuf>),
RustToV8Buf(MagicalSerializer<'a, 'b, 'c, ToJsBuffer>),
MagicAnyValue(MagicalSerializer<'a, 'b, 'c, AnyValue>),
MagicDetached(MagicalSerializer<'a, 'b, 'c, DetachedBuffer>),
MagicByteString(MagicalSerializer<'a, 'b, 'c, ByteString>),
MagicU16String(MagicalSerializer<'a, 'b, 'c, U16String>),
MagicStringOrBuffer(MagicalSerializer<'a, 'b, 'c, StringOrBuffer>),
MagicBigInt(MagicalSerializer<'a, 'b, 'c, BigInt>),
Regular(ObjectSerializer<'a, 'b, 'c>),
}
@ -296,14 +294,11 @@ impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> {
match self {
StructSerializers::ExternalPointer(s) => s.serialize_field(key, value),
StructSerializers::Magic(s) => s.serialize_field(key, value),
StructSerializers::ZeroCopyBuf(s) => s.serialize_field(key, value),
StructSerializers::RustToV8Buf(s) => s.serialize_field(key, value),
StructSerializers::MagicAnyValue(s) => s.serialize_field(key, value),
StructSerializers::MagicDetached(s) => s.serialize_field(key, value),
StructSerializers::MagicByteString(s) => s.serialize_field(key, value),
StructSerializers::MagicU16String(s) => s.serialize_field(key, value),
StructSerializers::MagicStringOrBuffer(s) => {
s.serialize_field(key, value)
}
StructSerializers::MagicBigInt(s) => s.serialize_field(key, value),
StructSerializers::Regular(s) => s.serialize_field(key, value),
}
@ -313,12 +308,11 @@ impl<'a, 'b, 'c> ser::SerializeStruct for StructSerializers<'a, 'b, 'c> {
match self {
StructSerializers::ExternalPointer(s) => s.end(),
StructSerializers::Magic(s) => s.end(),
StructSerializers::ZeroCopyBuf(s) => s.end(),
StructSerializers::RustToV8Buf(s) => s.end(),
StructSerializers::MagicAnyValue(s) => s.end(),
StructSerializers::MagicDetached(s) => s.end(),
StructSerializers::MagicByteString(s) => s.end(),
StructSerializers::MagicU16String(s) => s.end(),
StructSerializers::MagicStringOrBuffer(s) => s.end(),
StructSerializers::MagicBigInt(s) => s.end(),
StructSerializers::Regular(s) => s.end(),
}
@ -588,9 +582,9 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
let m = MagicalSerializer::<U16String>::new(self.scope);
Ok(StructSerializers::MagicU16String(m))
}
ZeroCopyBuf::MAGIC_NAME => {
let m = MagicalSerializer::<ZeroCopyBuf>::new(self.scope);
Ok(StructSerializers::ZeroCopyBuf(m))
ToJsBuffer::MAGIC_NAME => {
let m = MagicalSerializer::<ToJsBuffer>::new(self.scope);
Ok(StructSerializers::RustToV8Buf(m))
}
AnyValue::MAGIC_NAME => {
let m = MagicalSerializer::<AnyValue>::new(self.scope);
@ -600,10 +594,6 @@ impl<'a, 'b, 'c> ser::Serializer for Serializer<'a, 'b, 'c> {
let m = MagicalSerializer::<DetachedBuffer>::new(self.scope);
Ok(StructSerializers::MagicDetached(m))
}
StringOrBuffer::MAGIC_NAME => {
let m = MagicalSerializer::<StringOrBuffer>::new(self.scope);
Ok(StructSerializers::MagicStringOrBuffer(m))
}
BigInt::MAGIC_NAME => {
let m = MagicalSerializer::<BigInt>::new(self.scope);
Ok(StructSerializers::MagicBigInt(m))

View file

@ -4,8 +4,8 @@ use std::mem::transmute_copy;
use crate::BigInt;
use crate::ByteString;
use crate::ToJsBuffer;
use crate::U16String;
use crate::ZeroCopyBuf;
/// Serializable exists to allow boxing values as "objects" to be serialized later,
/// this is particularly useful for async op-responses. This trait is a more efficient
@ -63,7 +63,7 @@ pub enum Primitive {
Float32(f32),
Float64(f64),
String(String),
ZeroCopyBuf(ZeroCopyBuf),
RustToV8Buf(ToJsBuffer),
ByteString(ByteString),
U16String(U16String),
BigInt(BigInt),
@ -88,7 +88,7 @@ impl serde::Serialize for Primitive {
Self::Float32(x) => x.serialize(s),
Self::Float64(x) => x.serialize(s),
Self::String(x) => x.serialize(s),
Self::ZeroCopyBuf(x) => x.serialize(s),
Self::RustToV8Buf(x) => x.serialize(s),
Self::ByteString(x) => x.serialize(s),
Self::U16String(x) => x.serialize(s),
Self::BigInt(x) => x.serialize(s),
@ -134,8 +134,8 @@ impl<T: serde::Serialize + 'static> From<T> for SerializablePkg {
Self::Primitive(Primitive::Float64(tc(x)))
} else if tid == TypeId::of::<String>() {
Self::Primitive(Primitive::String(tc(x)))
} else if tid == TypeId::of::<ZeroCopyBuf>() {
Self::Primitive(Primitive::ZeroCopyBuf(tc(x)))
} else if tid == TypeId::of::<ToJsBuffer>() {
Self::Primitive(Primitive::RustToV8Buf(tc(x)))
} else if tid == TypeId::of::<ByteString>() {
Self::Primitive(Primitive::ByteString(tc(x)))
} else if tid == TypeId::of::<U16String>() {

View file

@ -7,8 +7,8 @@ use serde_v8::utils::v8_do;
use serde_v8::BigInt;
use serde_v8::ByteString;
use serde_v8::Error;
use serde_v8::JsBuffer;
use serde_v8::U16String;
use serde_v8::ZeroCopyBuf;
#[derive(Debug, Deserialize, PartialEq)]
struct MathOp {
@ -248,31 +248,31 @@ fn de_string_or_buffer() {
fn de_buffers() {
// ArrayBufferView
dedo("new Uint8Array([97])", |scope, v| {
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
let buf: JsBuffer = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[97]);
});
// ArrayBuffer
dedo("(new Uint8Array([97])).buffer", |scope, v| {
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
let buf: JsBuffer = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[97]);
});
dedo(
"(Uint8Array.from([0x68, 0x65, 0x6C, 0x6C, 0x6F]))",
|scope, v| {
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
let buf: JsBuffer = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[0x68, 0x65, 0x6C, 0x6C, 0x6F]);
},
);
dedo("(new ArrayBuffer(4))", |scope, v| {
let buf: ZeroCopyBuf = serde_v8::from_v8(scope, v).unwrap();
let buf: JsBuffer = serde_v8::from_v8(scope, v).unwrap();
assert_eq!(&*buf, &[0x0, 0x0, 0x0, 0x0]);
});
dedo("(new ArrayBuffer(8, { maxByteLength: 16}))", |scope, v| {
let result: Result<ZeroCopyBuf, Error> = serde_v8::from_v8(scope, v);
let result: Result<JsBuffer, Error> = serde_v8::from_v8(scope, v);
matches!(result, Err(Error::ResizableBackingStoreNotSupported));
});
}

View file

@ -68,27 +68,26 @@ fn magic_buffer() {
// Simple buffer
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let zbuf: serde_v8::ZeroCopyBuf =
serde_v8::from_v8(scope, v8_array).unwrap();
let zbuf: serde_v8::JsBuffer = serde_v8::from_v8(scope, v8_array).unwrap();
assert_eq!(&*zbuf, &[1, 2, 3, 4, 5]);
// Multi buffers
let v8_arrays =
js_exec(scope, "[new Uint8Array([1,2]), new Uint8Array([3,4,5])]");
let (z1, z2): (serde_v8::ZeroCopyBuf, serde_v8::ZeroCopyBuf) =
let (z1, z2): (serde_v8::JsBuffer, serde_v8::JsBuffer) =
serde_v8::from_v8(scope, v8_arrays).unwrap();
assert_eq!(&*z1, &[1, 2]);
assert_eq!(&*z2, &[3, 4, 5]);
// Wrapped in option, like our current op-ABI
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let zbuf: Option<serde_v8::ZeroCopyBuf> =
let zbuf: Option<serde_v8::JsBuffer> =
serde_v8::from_v8(scope, v8_array).unwrap();
assert_eq!(&*zbuf.unwrap(), &[1, 2, 3, 4, 5]);
// Observe mutation in JS
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let mut zbuf: serde_v8::ZeroCopyBuf =
let mut zbuf: serde_v8::JsBuffer =
serde_v8::from_v8(scope, v8_array).unwrap();
let key = serde_v8::to_v8(scope, "t1").unwrap();
global.set(scope, key, v8_array);
@ -99,13 +98,12 @@ fn magic_buffer() {
// Shared buffers
let v8_array =
js_exec(scope, "new Uint8Array(new SharedArrayBuffer([1,2,3,4,5]))");
let zbuf: Result<serde_v8::ZeroCopyBuf> =
serde_v8::from_v8(scope, v8_array);
let zbuf: Result<serde_v8::JsBuffer> = serde_v8::from_v8(scope, v8_array);
assert!(zbuf.is_err());
// Serialization
let buf: Vec<u8> = vec![1, 2, 3, 99, 5];
let zbuf: serde_v8::ZeroCopyBuf = buf.into();
let zbuf: serde_v8::ToJsBuffer = buf.into();
let v8_value = serde_v8::to_v8(scope, zbuf).unwrap();
let key = serde_v8::to_v8(scope, "t2").unwrap();
global.set(scope, key, v8_value);
@ -115,8 +113,8 @@ fn magic_buffer() {
// Composite Serialization
#[derive(serde::Serialize)]
struct Wrapper {
a: serde_v8::ZeroCopyBuf,
b: serde_v8::ZeroCopyBuf,
a: serde_v8::ToJsBuffer,
b: serde_v8::ToJsBuffer,
}
let buf1: Vec<u8> = vec![1, 2, 33, 4, 5];
let buf2: Vec<u8> = vec![5, 4, 3, 2, 11];
@ -134,8 +132,7 @@ fn magic_buffer() {
// ZeroCopyBuf as bytes::Bytes
let v8_array = js_exec(scope, "new Uint8Array([1,2,3,4,5])");
let zbuf: serde_v8::ZeroCopyBuf =
serde_v8::from_v8(scope, v8_array).unwrap();
let zbuf: serde_v8::JsBuffer = serde_v8::from_v8(scope, v8_array).unwrap();
let buf: bytes::Bytes = zbuf.into();
assert_eq!(buf, bytes::Bytes::from_static(&[1, 2, 3, 4, 5]));
assert_eq!(buf, bytes::Bytes::from_static(&[1, 2, 3, 4, 5]));