mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
refactor(ext): remove use of brotli::ffi
(#24214)
This commit is contained in:
parent
6ab143335a
commit
88e3f465d3
5 changed files with 181 additions and 294 deletions
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -275,11 +275,11 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-compression"
|
name = "async-compression"
|
||||||
version = "0.4.8"
|
version = "0.4.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07dbbf24db18d609b1462965249abdf49129ccad073ec257da372adc83259c60"
|
checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"brotli 4.0.0",
|
"brotli",
|
||||||
"flate2",
|
"flate2",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
@ -506,41 +506,20 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli"
|
name = "brotli"
|
||||||
version = "3.5.0"
|
version = "6.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
|
checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
"alloc-stdlib",
|
"alloc-stdlib",
|
||||||
"brotli-decompressor 2.5.1",
|
"brotli-decompressor",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "brotli"
|
|
||||||
version = "4.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "125740193d7fee5cc63ab9e16c2fdc4e07c74ba755cc53b327d6ea029e9fc569"
|
|
||||||
dependencies = [
|
|
||||||
"alloc-no-stdlib",
|
|
||||||
"alloc-stdlib",
|
|
||||||
"brotli-decompressor 3.0.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "brotli-decompressor"
|
name = "brotli-decompressor"
|
||||||
version = "2.5.1"
|
version = "4.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
|
checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362"
|
||||||
dependencies = [
|
|
||||||
"alloc-no-stdlib",
|
|
||||||
"alloc-stdlib",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "brotli-decompressor"
|
|
||||||
version = "3.0.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "65622a320492e09b5e0ac436b14c54ff68199bac392d0e89a6832c4518eea525"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"alloc-no-stdlib",
|
"alloc-no-stdlib",
|
||||||
"alloc-stdlib",
|
"alloc-stdlib",
|
||||||
|
@ -1515,7 +1494,7 @@ dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.21.7",
|
"base64 0.21.7",
|
||||||
"bencher",
|
"bencher",
|
||||||
"brotli 3.5.0",
|
"brotli",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cache_control",
|
"cache_control",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
|
@ -1674,7 +1653,7 @@ dependencies = [
|
||||||
"aead-gcm-stream",
|
"aead-gcm-stream",
|
||||||
"aes",
|
"aes",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"brotli 3.5.0",
|
"brotli",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cbc",
|
"cbc",
|
||||||
"const-oid",
|
"const-oid",
|
||||||
|
|
|
@ -90,7 +90,7 @@ async-trait = "0.1.73"
|
||||||
base32 = "=0.4.0"
|
base32 = "=0.4.0"
|
||||||
base64 = "0.21.4"
|
base64 = "0.21.4"
|
||||||
bencher = "0.1"
|
bencher = "0.1"
|
||||||
brotli = "3.3.4"
|
brotli = "6.0.0"
|
||||||
bytes = "1.4.0"
|
bytes = "1.4.0"
|
||||||
cache_control = "=0.2.0"
|
cache_control = "=0.2.0"
|
||||||
cbc = { version = "=0.1.2", features = ["alloc"] }
|
cbc = { version = "=0.1.2", features = ["alloc"] }
|
||||||
|
|
|
@ -24,7 +24,7 @@ harness = false
|
||||||
async-compression = { version = "0.4", features = ["tokio", "brotli", "gzip"] }
|
async-compression = { version = "0.4", features = ["tokio", "brotli", "gzip"] }
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
base64.workspace = true
|
base64.workspace = true
|
||||||
brotli = "3.3.4"
|
brotli.workspace = true
|
||||||
bytes.workspace = true
|
bytes.workspace = true
|
||||||
cache_control.workspace = true
|
cache_control.workspace = true
|
||||||
deno_core.workspace = true
|
deno_core.workspace = true
|
||||||
|
|
|
@ -3,8 +3,10 @@ use std::io::Write;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
|
use brotli::enc::encode::BrotliEncoderOperation;
|
||||||
use brotli::enc::encode::BrotliEncoderParameter;
|
use brotli::enc::encode::BrotliEncoderParameter;
|
||||||
use brotli::ffi::compressor::BrotliEncoderState;
|
use brotli::enc::encode::BrotliEncoderStateStruct;
|
||||||
|
use brotli::writer::StandardAlloc;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use bytes::BytesMut;
|
use bytes::BytesMut;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -448,58 +450,24 @@ enum BrotliState {
|
||||||
EndOfStream,
|
EndOfStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BrotliEncoderStateWrapper {
|
|
||||||
stm: *mut BrotliEncoderState,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[pin_project]
|
#[pin_project]
|
||||||
pub struct BrotliResponseStream {
|
pub struct BrotliResponseStream {
|
||||||
state: BrotliState,
|
state: BrotliState,
|
||||||
stm: BrotliEncoderStateWrapper,
|
stm: BrotliEncoderStateStruct<StandardAlloc>,
|
||||||
current_cursor: usize,
|
|
||||||
output_written_so_far: usize,
|
|
||||||
#[pin]
|
#[pin]
|
||||||
underlying: ResponseStream,
|
underlying: ResponseStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for BrotliEncoderStateWrapper {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// SAFETY: since we are dropping, we can be sure that this instance will not
|
|
||||||
// be used again.
|
|
||||||
unsafe {
|
|
||||||
brotli::ffi::compressor::BrotliEncoderDestroyInstance(self.stm);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl BrotliResponseStream {
|
impl BrotliResponseStream {
|
||||||
pub fn new(underlying: ResponseStream) -> Self {
|
pub fn new(underlying: ResponseStream) -> Self {
|
||||||
// SAFETY: creating an FFI instance should be OK with these args.
|
let mut stm = BrotliEncoderStateStruct::new(StandardAlloc::default());
|
||||||
let stm = unsafe {
|
// Quality level 6 is based on google's nginx default value for on-the-fly compression
|
||||||
let stm = brotli::ffi::compressor::BrotliEncoderCreateInstance(
|
// https://github.com/google/ngx_brotli#brotli_comp_level
|
||||||
None,
|
// lgwin 22 is equivalent to brotli window size of (2**22)-16 bytes (~4MB)
|
||||||
None,
|
stm.set_parameter(BrotliEncoderParameter::BROTLI_PARAM_QUALITY, 6);
|
||||||
std::ptr::null_mut(),
|
stm.set_parameter(BrotliEncoderParameter::BROTLI_PARAM_LGWIN, 22);
|
||||||
);
|
|
||||||
// Quality level 6 is based on google's nginx default value for on-the-fly compression
|
|
||||||
// https://github.com/google/ngx_brotli#brotli_comp_level
|
|
||||||
// lgwin 22 is equivalent to brotli window size of (2**22)-16 bytes (~4MB)
|
|
||||||
brotli::ffi::compressor::BrotliEncoderSetParameter(
|
|
||||||
stm,
|
|
||||||
BrotliEncoderParameter::BROTLI_PARAM_QUALITY,
|
|
||||||
6,
|
|
||||||
);
|
|
||||||
brotli::ffi::compressor::BrotliEncoderSetParameter(
|
|
||||||
stm,
|
|
||||||
BrotliEncoderParameter::BROTLI_PARAM_LGWIN,
|
|
||||||
22,
|
|
||||||
);
|
|
||||||
BrotliEncoderStateWrapper { stm }
|
|
||||||
};
|
|
||||||
Self {
|
Self {
|
||||||
stm,
|
stm,
|
||||||
output_written_so_far: 0,
|
|
||||||
current_cursor: 0,
|
|
||||||
state: BrotliState::Streaming,
|
state: BrotliState::Streaming,
|
||||||
underlying,
|
underlying,
|
||||||
}
|
}
|
||||||
|
@ -546,71 +514,46 @@ impl PollFrame for BrotliResponseStream {
|
||||||
|
|
||||||
let res = match frame {
|
let res = match frame {
|
||||||
ResponseStreamResult::NonEmptyBuf(buf) => {
|
ResponseStreamResult::NonEmptyBuf(buf) => {
|
||||||
let mut output_written = 0;
|
let mut output_buffer = vec![0; max_compressed_size(buf.len())];
|
||||||
let mut total_output_written = 0;
|
let mut output_offset = 0;
|
||||||
let mut input_size = buf.len();
|
|
||||||
let input_buffer = buf.as_ref();
|
|
||||||
let mut len = max_compressed_size(input_size);
|
|
||||||
let mut output_buffer = vec![0u8; len];
|
|
||||||
let mut ob_ptr = output_buffer.as_mut_ptr();
|
|
||||||
|
|
||||||
// SAFETY: these are okay arguments to these FFI calls.
|
this.stm.compress_stream(
|
||||||
unsafe {
|
BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
|
||||||
brotli::ffi::compressor::BrotliEncoderCompressStream(
|
&mut buf.len(),
|
||||||
this.stm.stm,
|
&buf,
|
||||||
brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
|
&mut 0,
|
||||||
&mut input_size,
|
&mut output_buffer.len(),
|
||||||
&input_buffer.as_ptr() as *const *const u8 as *mut *const u8,
|
&mut output_buffer,
|
||||||
&mut len,
|
&mut output_offset,
|
||||||
&mut ob_ptr,
|
&mut None,
|
||||||
&mut output_written,
|
&mut |_, _, _, _| (),
|
||||||
);
|
);
|
||||||
total_output_written += output_written;
|
|
||||||
output_written = 0;
|
|
||||||
|
|
||||||
brotli::ffi::compressor::BrotliEncoderCompressStream(
|
output_buffer.truncate(output_offset);
|
||||||
this.stm.stm,
|
|
||||||
brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_FLUSH,
|
|
||||||
&mut input_size,
|
|
||||||
&input_buffer.as_ptr() as *const *const u8 as *mut *const u8,
|
|
||||||
&mut len,
|
|
||||||
&mut ob_ptr,
|
|
||||||
&mut output_written,
|
|
||||||
);
|
|
||||||
total_output_written += output_written;
|
|
||||||
};
|
|
||||||
|
|
||||||
output_buffer
|
|
||||||
.truncate(total_output_written - this.output_written_so_far);
|
|
||||||
this.output_written_so_far = total_output_written;
|
|
||||||
ResponseStreamResult::NonEmptyBuf(BufView::from(output_buffer))
|
ResponseStreamResult::NonEmptyBuf(BufView::from(output_buffer))
|
||||||
}
|
}
|
||||||
ResponseStreamResult::EndOfStream => {
|
ResponseStreamResult::EndOfStream => {
|
||||||
let mut len = 1024usize;
|
let mut output_buffer = vec![0; 1024];
|
||||||
let mut output_buffer = vec![0u8; len];
|
let mut output_offset = 0;
|
||||||
let mut input_size = 0;
|
|
||||||
let mut output_written = 0;
|
|
||||||
let ob_ptr = output_buffer.as_mut_ptr();
|
|
||||||
|
|
||||||
// SAFETY: these are okay arguments to these FFI calls.
|
this.stm.compress_stream(
|
||||||
unsafe {
|
BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
|
||||||
brotli::ffi::compressor::BrotliEncoderCompressStream(
|
&mut 0,
|
||||||
this.stm.stm,
|
&[],
|
||||||
brotli::ffi::compressor::BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
|
&mut 0,
|
||||||
&mut input_size,
|
&mut output_buffer.len(),
|
||||||
std::ptr::null_mut(),
|
&mut output_buffer,
|
||||||
&mut len,
|
&mut output_offset,
|
||||||
&ob_ptr as *const *mut u8 as *mut *mut u8,
|
&mut None,
|
||||||
&mut output_written,
|
&mut |_, _, _, _| (),
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
if output_written == 0 {
|
if output_offset == 0 {
|
||||||
this.state = BrotliState::EndOfStream;
|
this.state = BrotliState::EndOfStream;
|
||||||
ResponseStreamResult::EndOfStream
|
ResponseStreamResult::EndOfStream
|
||||||
} else {
|
} else {
|
||||||
this.state = BrotliState::Flushing;
|
this.state = BrotliState::Flushing;
|
||||||
output_buffer.truncate(output_written - this.output_written_so_far);
|
output_buffer.truncate(output_offset);
|
||||||
ResponseStreamResult::NonEmptyBuf(BufView::from(output_buffer))
|
ResponseStreamResult::NonEmptyBuf(BufView::from(output_buffer))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
use brotli::enc::backward_references::BrotliEncoderMode;
|
||||||
|
use brotli::enc::encode::BrotliEncoderCompress;
|
||||||
|
use brotli::enc::encode::BrotliEncoderOperation;
|
||||||
use brotli::enc::encode::BrotliEncoderParameter;
|
use brotli::enc::encode::BrotliEncoderParameter;
|
||||||
use brotli::ffi::compressor::*;
|
use brotli::enc::encode::BrotliEncoderStateStruct;
|
||||||
use brotli::ffi::decompressor::ffi::interface::BrotliDecoderResult;
|
use brotli::writer::StandardAlloc;
|
||||||
use brotli::ffi::decompressor::ffi::BrotliDecoderState;
|
use brotli::BrotliDecompressStream;
|
||||||
use brotli::ffi::decompressor::*;
|
use brotli::BrotliResult;
|
||||||
|
use brotli::BrotliState;
|
||||||
use brotli::Decompressor;
|
use brotli::Decompressor;
|
||||||
use deno_core::error::type_error;
|
use deno_core::error::type_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -12,14 +16,20 @@ use deno_core::JsBuffer;
|
||||||
use deno_core::OpState;
|
use deno_core::OpState;
|
||||||
use deno_core::Resource;
|
use deno_core::Resource;
|
||||||
use deno_core::ToJsBuffer;
|
use deno_core::ToJsBuffer;
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
|
fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
|
||||||
if mode > 6 {
|
Ok(match mode {
|
||||||
return Err(type_error("Invalid encoder mode"));
|
0 => BrotliEncoderMode::BROTLI_MODE_GENERIC,
|
||||||
}
|
1 => BrotliEncoderMode::BROTLI_MODE_TEXT,
|
||||||
// SAFETY: mode is a valid discriminant for BrotliEncoderMode
|
2 => BrotliEncoderMode::BROTLI_MODE_FONT,
|
||||||
unsafe { Ok(std::mem::transmute::<u32, BrotliEncoderMode>(mode)) }
|
3 => BrotliEncoderMode::BROTLI_FORCE_LSB_PRIOR,
|
||||||
|
4 => BrotliEncoderMode::BROTLI_FORCE_MSB_PRIOR,
|
||||||
|
5 => BrotliEncoderMode::BROTLI_FORCE_UTF8_PRIOR,
|
||||||
|
6 => BrotliEncoderMode::BROTLI_FORCE_SIGNED_PRIOR,
|
||||||
|
_ => return Err(type_error("Invalid encoder mode")),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
@ -31,24 +41,22 @@ pub fn op_brotli_compress(
|
||||||
#[smi] lgwin: i32,
|
#[smi] lgwin: i32,
|
||||||
#[smi] mode: u32,
|
#[smi] mode: u32,
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError> {
|
||||||
let in_buffer = buffer.as_ptr();
|
let mode = encoder_mode(mode)?;
|
||||||
let in_size = buffer.len();
|
|
||||||
let out_buffer = out.as_mut_ptr();
|
|
||||||
let mut out_size = out.len();
|
let mut out_size = out.len();
|
||||||
|
|
||||||
// SAFETY: in_size and in_buffer, out_size and out_buffer are valid for this call.
|
let result = BrotliEncoderCompress(
|
||||||
if unsafe {
|
StandardAlloc::default(),
|
||||||
BrotliEncoderCompress(
|
&mut StandardAlloc::default(),
|
||||||
quality,
|
quality,
|
||||||
lgwin,
|
lgwin,
|
||||||
encoder_mode(mode)?,
|
mode,
|
||||||
in_size,
|
buffer.len(),
|
||||||
in_buffer,
|
buffer,
|
||||||
&mut out_size as *mut usize,
|
&mut out_size,
|
||||||
out_buffer,
|
out,
|
||||||
)
|
&mut |_, _, _, _| (),
|
||||||
} != 1
|
);
|
||||||
{
|
if result != 1 {
|
||||||
return Err(type_error("Failed to compress"));
|
return Err(type_error("Failed to compress"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,28 +88,25 @@ pub async fn op_brotli_compress_async(
|
||||||
#[smi] lgwin: i32,
|
#[smi] lgwin: i32,
|
||||||
#[smi] mode: u32,
|
#[smi] mode: u32,
|
||||||
) -> Result<ToJsBuffer, AnyError> {
|
) -> Result<ToJsBuffer, AnyError> {
|
||||||
|
let mode = encoder_mode(mode)?;
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let in_buffer = input.as_ptr();
|
let input = &*input;
|
||||||
let in_size = input.len();
|
let mut out = vec![0u8; max_compressed_size(input.len())];
|
||||||
|
|
||||||
let mut out = vec![0u8; max_compressed_size(in_size)];
|
|
||||||
let out_buffer = out.as_mut_ptr();
|
|
||||||
let mut out_size = out.len();
|
let mut out_size = out.len();
|
||||||
|
|
||||||
// SAFETY: in_size and in_buffer, out_size and out_buffer
|
let result = BrotliEncoderCompress(
|
||||||
// are valid for this call.
|
StandardAlloc::default(),
|
||||||
if unsafe {
|
&mut StandardAlloc::default(),
|
||||||
BrotliEncoderCompress(
|
quality,
|
||||||
quality,
|
lgwin,
|
||||||
lgwin,
|
mode,
|
||||||
encoder_mode(mode)?,
|
input.len(),
|
||||||
in_size,
|
input,
|
||||||
in_buffer,
|
&mut out_size,
|
||||||
&mut out_size as *mut usize,
|
&mut out,
|
||||||
out_buffer,
|
&mut |_, _, _, _| (),
|
||||||
)
|
);
|
||||||
} != 1
|
if result != 1 {
|
||||||
{
|
|
||||||
return Err(type_error("Failed to compress"));
|
return Err(type_error("Failed to compress"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,38 +117,26 @@ pub async fn op_brotli_compress_async(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BrotliCompressCtx {
|
struct BrotliCompressCtx {
|
||||||
inst: *mut BrotliEncoderState,
|
inst: RefCell<BrotliEncoderStateStruct<StandardAlloc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for BrotliCompressCtx {}
|
impl Resource for BrotliCompressCtx {}
|
||||||
|
|
||||||
impl Drop for BrotliCompressCtx {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// SAFETY: `self.inst` is the current brotli encoder instance.
|
|
||||||
// It is not used after the following call.
|
|
||||||
unsafe { BrotliEncoderDestroyInstance(self.inst) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op2]
|
#[op2]
|
||||||
#[smi]
|
#[smi]
|
||||||
pub fn op_create_brotli_compress(
|
pub fn op_create_brotli_compress(
|
||||||
state: &mut OpState,
|
state: &mut OpState,
|
||||||
#[serde] params: Vec<(u8, i32)>,
|
#[serde] params: Vec<(u8, i32)>,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let inst =
|
let mut inst = BrotliEncoderStateStruct::new(StandardAlloc::default());
|
||||||
// SAFETY: Creates a brotli encoder instance for default allocators.
|
|
||||||
unsafe { BrotliEncoderCreateInstance(None, None, std::ptr::null_mut()) };
|
|
||||||
|
|
||||||
for (key, value) in params {
|
for (key, value) in params {
|
||||||
// SAFETY: `key` can range from 0-255.
|
inst.set_parameter(encoder_param(key), value as u32);
|
||||||
// Any valid u32 can be used for the `value`.
|
|
||||||
unsafe {
|
|
||||||
BrotliEncoderSetParameter(inst, encoder_param(key), value as u32);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.resource_table.add(BrotliCompressCtx { inst })
|
state.resource_table.add(BrotliCompressCtx {
|
||||||
|
inst: RefCell::new(inst),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encoder_param(param: u8) -> BrotliEncoderParameter {
|
fn encoder_param(param: u8) -> BrotliEncoderParameter {
|
||||||
|
@ -160,30 +153,25 @@ pub fn op_brotli_compress_stream(
|
||||||
#[buffer] output: &mut [u8],
|
#[buffer] output: &mut [u8],
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError> {
|
||||||
let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
|
let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
|
||||||
|
let mut inst = ctx.inst.borrow_mut();
|
||||||
|
let mut output_offset = 0;
|
||||||
|
|
||||||
// SAFETY: TODO(littledivy)
|
let result = inst.compress_stream(
|
||||||
unsafe {
|
BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
|
||||||
let mut available_in = input.len();
|
&mut input.len(),
|
||||||
let mut next_in = input.as_ptr();
|
input,
|
||||||
let mut available_out = output.len();
|
&mut 0,
|
||||||
let mut next_out = output.as_mut_ptr();
|
&mut output.len(),
|
||||||
|
output,
|
||||||
if BrotliEncoderCompressStream(
|
&mut output_offset,
|
||||||
ctx.inst,
|
&mut None,
|
||||||
BrotliEncoderOperation::BROTLI_OPERATION_PROCESS,
|
&mut |_, _, _, _| (),
|
||||||
&mut available_in,
|
);
|
||||||
&mut next_in,
|
if !result {
|
||||||
&mut available_out,
|
return Err(type_error("Failed to compress"));
|
||||||
&mut next_out,
|
|
||||||
std::ptr::null_mut(),
|
|
||||||
) != 1
|
|
||||||
{
|
|
||||||
return Err(type_error("Failed to compress"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// On progress, next_out is advanced and available_out is reduced.
|
|
||||||
Ok(output.len() - available_out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(output_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
@ -194,29 +182,25 @@ pub fn op_brotli_compress_stream_end(
|
||||||
#[buffer] output: &mut [u8],
|
#[buffer] output: &mut [u8],
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError> {
|
||||||
let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
|
let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
|
||||||
|
let mut inst = ctx.inst.borrow_mut();
|
||||||
|
let mut output_offset = 0;
|
||||||
|
|
||||||
// SAFETY: TODO(littledivy)
|
let result = inst.compress_stream(
|
||||||
unsafe {
|
BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
|
||||||
let mut available_out = output.len();
|
&mut 0,
|
||||||
let mut next_out = output.as_mut_ptr();
|
&[],
|
||||||
let mut total_out = 0;
|
&mut 0,
|
||||||
|
&mut output.len(),
|
||||||
if BrotliEncoderCompressStream(
|
output,
|
||||||
ctx.inst,
|
&mut output_offset,
|
||||||
BrotliEncoderOperation::BROTLI_OPERATION_FINISH,
|
&mut None,
|
||||||
&mut 0,
|
&mut |_, _, _, _| (),
|
||||||
std::ptr::null_mut(),
|
);
|
||||||
&mut available_out,
|
if !result {
|
||||||
&mut next_out,
|
return Err(type_error("Failed to compress"));
|
||||||
&mut total_out,
|
|
||||||
) != 1
|
|
||||||
{
|
|
||||||
return Err(type_error("Failed to compress"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// On finish, next_out is advanced and available_out is reduced.
|
|
||||||
Ok(output.len() - available_out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(output_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
|
fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
|
||||||
|
@ -243,25 +227,22 @@ pub async fn op_brotli_decompress_async(
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BrotliDecompressCtx {
|
struct BrotliDecompressCtx {
|
||||||
inst: *mut BrotliDecoderState,
|
inst: RefCell<BrotliState<StandardAlloc, StandardAlloc, StandardAlloc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for BrotliDecompressCtx {}
|
impl Resource for BrotliDecompressCtx {}
|
||||||
|
|
||||||
impl Drop for BrotliDecompressCtx {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
// SAFETY: TODO(littledivy)
|
|
||||||
unsafe { CBrotliDecoderDestroyInstance(self.inst) };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
#[smi]
|
#[smi]
|
||||||
pub fn op_create_brotli_decompress(state: &mut OpState) -> u32 {
|
pub fn op_create_brotli_decompress(state: &mut OpState) -> u32 {
|
||||||
let inst =
|
let inst = BrotliState::new(
|
||||||
// SAFETY: TODO(littledivy)
|
StandardAlloc::default(),
|
||||||
unsafe { CBrotliDecoderCreateInstance(None, None, std::ptr::null_mut()) };
|
StandardAlloc::default(),
|
||||||
state.resource_table.add(BrotliDecompressCtx { inst })
|
StandardAlloc::default(),
|
||||||
|
);
|
||||||
|
state.resource_table.add(BrotliDecompressCtx {
|
||||||
|
inst: RefCell::new(inst),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
@ -273,32 +254,24 @@ pub fn op_brotli_decompress_stream(
|
||||||
#[buffer] output: &mut [u8],
|
#[buffer] output: &mut [u8],
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError> {
|
||||||
let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
|
let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
|
||||||
|
let mut inst = ctx.inst.borrow_mut();
|
||||||
|
let mut output_offset = 0;
|
||||||
|
|
||||||
// SAFETY: TODO(littledivy)
|
let result = BrotliDecompressStream(
|
||||||
unsafe {
|
&mut input.len(),
|
||||||
let mut available_in = input.len();
|
&mut 0,
|
||||||
let mut next_in = input.as_ptr();
|
input,
|
||||||
let mut available_out = output.len();
|
&mut output.len(),
|
||||||
let mut next_out = output.as_mut_ptr();
|
&mut output_offset,
|
||||||
|
output,
|
||||||
if matches!(
|
&mut 0,
|
||||||
CBrotliDecoderDecompressStream(
|
&mut inst,
|
||||||
ctx.inst,
|
);
|
||||||
&mut available_in,
|
if matches!(result, BrotliResult::ResultFailure) {
|
||||||
&mut next_in,
|
return Err(type_error("Failed to decompress"));
|
||||||
&mut available_out,
|
|
||||||
&mut next_out,
|
|
||||||
std::ptr::null_mut(),
|
|
||||||
),
|
|
||||||
BrotliDecoderResult::BROTLI_DECODER_RESULT_ERROR
|
|
||||||
) {
|
|
||||||
let ec = CBrotliDecoderGetErrorCode(ctx.inst) as i32;
|
|
||||||
return Err(type_error(format!("Failed to decompress, error {ec}")));
|
|
||||||
}
|
|
||||||
|
|
||||||
// On progress, next_out is advanced and available_out is reduced.
|
|
||||||
Ok(output.len() - available_out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(output_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op2(fast)]
|
#[op2(fast)]
|
||||||
|
@ -309,30 +282,22 @@ pub fn op_brotli_decompress_stream_end(
|
||||||
#[buffer] output: &mut [u8],
|
#[buffer] output: &mut [u8],
|
||||||
) -> Result<usize, AnyError> {
|
) -> Result<usize, AnyError> {
|
||||||
let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
|
let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
|
||||||
|
let mut inst = ctx.inst.borrow_mut();
|
||||||
|
let mut output_offset = 0;
|
||||||
|
|
||||||
// SAFETY: TODO(littledivy)
|
let result = BrotliDecompressStream(
|
||||||
unsafe {
|
&mut 0,
|
||||||
let mut available_out = output.len();
|
&mut 0,
|
||||||
let mut next_out = output.as_mut_ptr();
|
&[],
|
||||||
let mut available_in = 0;
|
&mut output.len(),
|
||||||
let mut next_in = [];
|
&mut output_offset,
|
||||||
let mut total_out = 0;
|
output,
|
||||||
|
&mut 0,
|
||||||
if matches!(
|
&mut inst,
|
||||||
CBrotliDecoderDecompressStream(
|
);
|
||||||
ctx.inst,
|
if matches!(result, BrotliResult::ResultFailure) {
|
||||||
&mut available_in,
|
return Err(type_error("Failed to decompress"));
|
||||||
next_in.as_mut_ptr(),
|
|
||||||
&mut available_out,
|
|
||||||
&mut next_out,
|
|
||||||
&mut total_out,
|
|
||||||
),
|
|
||||||
BrotliDecoderResult::BROTLI_DECODER_RESULT_ERROR
|
|
||||||
) {
|
|
||||||
return Err(type_error("Failed to decompress"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// On finish, next_out is advanced and available_out is reduced.
|
|
||||||
Ok(output.len() - available_out)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(output_offset)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue