summaryrefslogtreecommitdiff
path: root/ext/node/ops/zlib
diff options
context:
space:
mode:
authorhaturau <135221985+haturatu@users.noreply.github.com>2024-11-20 01:20:47 +0900
committerGitHub <noreply@github.com>2024-11-20 01:20:47 +0900
commit85719a67e59c7aa45bead26e4942d7df8b1b42d4 (patch)
treeface0aecaac53e93ce2f23b53c48859bcf1a36ec /ext/node/ops/zlib
parent67697bc2e4a62a9670699fd18ad0dd8efc5bd955 (diff)
parent186b52731c6bb326c4d32905c5e732d082e83465 (diff)
Merge branch 'denoland:main' into main
Diffstat (limited to 'ext/node/ops/zlib')
-rw-r--r--ext/node/ops/zlib/brotli.rs77
-rw-r--r--ext/node/ops/zlib/mod.rs86
-rw-r--r--ext/node/ops/zlib/mode.rs21
3 files changed, 106 insertions, 78 deletions
diff --git a/ext/node/ops/zlib/brotli.rs b/ext/node/ops/zlib/brotli.rs
index 3e3905fc3..1a681ff7f 100644
--- a/ext/node/ops/zlib/brotli.rs
+++ b/ext/node/ops/zlib/brotli.rs
@@ -9,8 +9,6 @@ use brotli::BrotliDecompressStream;
use brotli::BrotliResult;
use brotli::BrotliState;
use brotli::Decompressor;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
use deno_core::op2;
use deno_core::JsBuffer;
use deno_core::OpState;
@@ -19,7 +17,23 @@ use deno_core::ToJsBuffer;
use std::cell::RefCell;
use std::io::Read;
-fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
+#[derive(Debug, thiserror::Error)]
+pub enum BrotliError {
+ #[error("Invalid encoder mode")]
+ InvalidEncoderMode,
+ #[error("Failed to compress")]
+ CompressFailed,
+ #[error("Failed to decompress")]
+ DecompressFailed,
+ #[error(transparent)]
+ Join(#[from] tokio::task::JoinError),
+ #[error(transparent)]
+ Resource(deno_core::error::AnyError),
+ #[error("{0}")]
+ Io(std::io::Error),
+}
+
+fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, BrotliError> {
Ok(match mode {
0 => BrotliEncoderMode::BROTLI_MODE_GENERIC,
1 => BrotliEncoderMode::BROTLI_MODE_TEXT,
@@ -28,7 +42,7 @@ fn encoder_mode(mode: u32) -> Result<BrotliEncoderMode, AnyError> {
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")),
+ _ => return Err(BrotliError::InvalidEncoderMode),
})
}
@@ -40,7 +54,7 @@ pub fn op_brotli_compress(
#[smi] quality: i32,
#[smi] lgwin: i32,
#[smi] mode: u32,
-) -> Result<usize, AnyError> {
+) -> Result<usize, BrotliError> {
let mode = encoder_mode(mode)?;
let mut out_size = out.len();
@@ -57,7 +71,7 @@ pub fn op_brotli_compress(
&mut |_, _, _, _| (),
);
if result != 1 {
- return Err(type_error("Failed to compress"));
+ return Err(BrotliError::CompressFailed);
}
Ok(out_size)
@@ -87,7 +101,7 @@ pub async fn op_brotli_compress_async(
#[smi] quality: i32,
#[smi] lgwin: i32,
#[smi] mode: u32,
-) -> Result<ToJsBuffer, AnyError> {
+) -> Result<ToJsBuffer, BrotliError> {
let mode = encoder_mode(mode)?;
tokio::task::spawn_blocking(move || {
let input = &*input;
@@ -107,7 +121,7 @@ pub async fn op_brotli_compress_async(
&mut |_, _, _, _| (),
);
if result != 1 {
- return Err(type_error("Failed to compress"));
+ return Err(BrotliError::CompressFailed);
}
out.truncate(out_size);
@@ -151,8 +165,11 @@ pub fn op_brotli_compress_stream(
#[smi] rid: u32,
#[buffer] input: &[u8],
#[buffer] output: &mut [u8],
-) -> Result<usize, AnyError> {
- let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
+) -> Result<usize, BrotliError> {
+ let ctx = state
+ .resource_table
+ .get::<BrotliCompressCtx>(rid)
+ .map_err(BrotliError::Resource)?;
let mut inst = ctx.inst.borrow_mut();
let mut output_offset = 0;
@@ -168,7 +185,7 @@ pub fn op_brotli_compress_stream(
&mut |_, _, _, _| (),
);
if !result {
- return Err(type_error("Failed to compress"));
+ return Err(BrotliError::CompressFailed);
}
Ok(output_offset)
@@ -180,8 +197,11 @@ pub fn op_brotli_compress_stream_end(
state: &mut OpState,
#[smi] rid: u32,
#[buffer] output: &mut [u8],
-) -> Result<usize, AnyError> {
- let ctx = state.resource_table.get::<BrotliCompressCtx>(rid)?;
+) -> Result<usize, BrotliError> {
+ let ctx = state
+ .resource_table
+ .get::<BrotliCompressCtx>(rid)
+ .map_err(BrotliError::Resource)?;
let mut inst = ctx.inst.borrow_mut();
let mut output_offset = 0;
@@ -197,13 +217,13 @@ pub fn op_brotli_compress_stream_end(
&mut |_, _, _, _| (),
);
if !result {
- return Err(type_error("Failed to compress"));
+ return Err(BrotliError::CompressFailed);
}
Ok(output_offset)
}
-fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
+fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, std::io::Error> {
let mut output = Vec::with_capacity(4096);
let mut decompressor = Decompressor::new(buffer, buffer.len());
decompressor.read_to_end(&mut output)?;
@@ -214,7 +234,7 @@ fn brotli_decompress(buffer: &[u8]) -> Result<ToJsBuffer, AnyError> {
#[serde]
pub fn op_brotli_decompress(
#[buffer] buffer: &[u8],
-) -> Result<ToJsBuffer, AnyError> {
+) -> Result<ToJsBuffer, std::io::Error> {
brotli_decompress(buffer)
}
@@ -222,8 +242,11 @@ pub fn op_brotli_decompress(
#[serde]
pub async fn op_brotli_decompress_async(
#[buffer] buffer: JsBuffer,
-) -> Result<ToJsBuffer, AnyError> {
- tokio::task::spawn_blocking(move || brotli_decompress(&buffer)).await?
+) -> Result<ToJsBuffer, BrotliError> {
+ tokio::task::spawn_blocking(move || {
+ brotli_decompress(&buffer).map_err(BrotliError::Io)
+ })
+ .await?
}
struct BrotliDecompressCtx {
@@ -252,8 +275,11 @@ pub fn op_brotli_decompress_stream(
#[smi] rid: u32,
#[buffer] input: &[u8],
#[buffer] output: &mut [u8],
-) -> Result<usize, AnyError> {
- let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
+) -> Result<usize, BrotliError> {
+ let ctx = state
+ .resource_table
+ .get::<BrotliDecompressCtx>(rid)
+ .map_err(BrotliError::Resource)?;
let mut inst = ctx.inst.borrow_mut();
let mut output_offset = 0;
@@ -268,7 +294,7 @@ pub fn op_brotli_decompress_stream(
&mut inst,
);
if matches!(result, BrotliResult::ResultFailure) {
- return Err(type_error("Failed to decompress"));
+ return Err(BrotliError::DecompressFailed);
}
Ok(output_offset)
@@ -280,8 +306,11 @@ pub fn op_brotli_decompress_stream_end(
state: &mut OpState,
#[smi] rid: u32,
#[buffer] output: &mut [u8],
-) -> Result<usize, AnyError> {
- let ctx = state.resource_table.get::<BrotliDecompressCtx>(rid)?;
+) -> Result<usize, BrotliError> {
+ let ctx = state
+ .resource_table
+ .get::<BrotliDecompressCtx>(rid)
+ .map_err(BrotliError::Resource)?;
let mut inst = ctx.inst.borrow_mut();
let mut output_offset = 0;
@@ -296,7 +325,7 @@ pub fn op_brotli_decompress_stream_end(
&mut inst,
);
if matches!(result, BrotliResult::ResultFailure) {
- return Err(type_error("Failed to decompress"));
+ return Err(BrotliError::DecompressFailed);
}
Ok(output_offset)
diff --git a/ext/node/ops/zlib/mod.rs b/ext/node/ops/zlib/mod.rs
index b1d6d21d2..991c0925d 100644
--- a/ext/node/ops/zlib/mod.rs
+++ b/ext/node/ops/zlib/mod.rs
@@ -1,14 +1,14 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
+
use deno_core::op2;
+use libc::c_ulong;
use std::borrow::Cow;
use std::cell::RefCell;
use zlib::*;
mod alloc;
pub mod brotli;
-mod mode;
+pub mod mode;
mod stream;
use mode::Flush;
@@ -17,11 +17,11 @@ use mode::Mode;
use self::stream::StreamWrapper;
#[inline]
-fn check(condition: bool, msg: &str) -> Result<(), AnyError> {
+fn check(condition: bool, msg: &str) -> Result<(), deno_core::error::AnyError> {
if condition {
Ok(())
} else {
- Err(type_error(msg.to_string()))
+ Err(deno_core::error::type_error(msg.to_string()))
}
}
@@ -56,7 +56,7 @@ impl ZlibInner {
out_off: u32,
out_len: u32,
flush: Flush,
- ) -> Result<(), AnyError> {
+ ) -> Result<(), deno_core::error::AnyError> {
check(self.init_done, "write before init")?;
check(!self.write_in_progress, "write already in progress")?;
check(!self.pending_close, "close already in progress")?;
@@ -65,11 +65,11 @@ impl ZlibInner {
let next_in = input
.get(in_off as usize..in_off as usize + in_len as usize)
- .ok_or_else(|| type_error("invalid input range"))?
+ .ok_or_else(|| deno_core::error::type_error("invalid input range"))?
.as_ptr() as *mut _;
let next_out = out
.get_mut(out_off as usize..out_off as usize + out_len as usize)
- .ok_or_else(|| type_error("invalid output range"))?
+ .ok_or_else(|| deno_core::error::type_error("invalid output range"))?
.as_mut_ptr();
self.strm.avail_in = in_len;
@@ -81,7 +81,10 @@ impl ZlibInner {
Ok(())
}
- fn do_write(&mut self, flush: Flush) -> Result<(), AnyError> {
+ fn do_write(
+ &mut self,
+ flush: Flush,
+ ) -> Result<(), deno_core::error::AnyError> {
self.flush = flush;
match self.mode {
Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => {
@@ -127,7 +130,7 @@ impl ZlibInner {
self.mode = Mode::Inflate;
}
} else if next_expected_header_byte.is_some() {
- return Err(type_error(
+ return Err(deno_core::error::type_error(
"invalid number of gzip magic number bytes read",
));
}
@@ -181,7 +184,7 @@ impl ZlibInner {
Ok(())
}
- fn init_stream(&mut self) -> Result<(), AnyError> {
+ fn init_stream(&mut self) -> Result<(), deno_core::error::AnyError> {
match self.mode {
Mode::Gzip | Mode::Gunzip => self.window_bits += 16,
Mode::Unzip => self.window_bits += 32,
@@ -199,7 +202,7 @@ impl ZlibInner {
Mode::Inflate | Mode::Gunzip | Mode::InflateRaw | Mode::Unzip => {
self.strm.inflate_init(self.window_bits)
}
- Mode::None => return Err(type_error("Unknown mode")),
+ Mode::None => return Err(deno_core::error::type_error("Unknown mode")),
};
self.write_in_progress = false;
@@ -208,7 +211,7 @@ impl ZlibInner {
Ok(())
}
- fn close(&mut self) -> Result<bool, AnyError> {
+ fn close(&mut self) -> Result<bool, deno_core::error::AnyError> {
if self.write_in_progress {
self.pending_close = true;
return Ok(false);
@@ -222,10 +225,8 @@ impl ZlibInner {
Ok(true)
}
- fn reset_stream(&mut self) -> Result<(), AnyError> {
+ fn reset_stream(&mut self) {
self.err = self.strm.reset(self.mode);
-
- Ok(())
}
}
@@ -243,7 +244,7 @@ impl deno_core::Resource for Zlib {
#[op2]
#[cppgc]
-pub fn op_zlib_new(#[smi] mode: i32) -> Result<Zlib, AnyError> {
+pub fn op_zlib_new(#[smi] mode: i32) -> Result<Zlib, mode::ModeError> {
let mode = Mode::try_from(mode)?;
let inner = ZlibInner {
@@ -256,12 +257,20 @@ pub fn op_zlib_new(#[smi] mode: i32) -> Result<Zlib, AnyError> {
})
}
+#[derive(Debug, thiserror::Error)]
+pub enum ZlibError {
+ #[error("zlib not initialized")]
+ NotInitialized,
+ #[error(transparent)]
+ Mode(#[from] mode::ModeError),
+ #[error(transparent)]
+ Other(#[from] deno_core::error::AnyError),
+}
+
#[op2(fast)]
-pub fn op_zlib_close(#[cppgc] resource: &Zlib) -> Result<(), AnyError> {
+pub fn op_zlib_close(#[cppgc] resource: &Zlib) -> Result<(), ZlibError> {
let mut resource = resource.inner.borrow_mut();
- let zlib = resource
- .as_mut()
- .ok_or_else(|| type_error("zlib not initialized"))?;
+ let zlib = resource.as_mut().ok_or(ZlibError::NotInitialized)?;
// If there is a pending write, defer the close until the write is done.
zlib.close()?;
@@ -282,11 +291,9 @@ pub fn op_zlib_write(
#[smi] out_off: u32,
#[smi] out_len: u32,
#[buffer] result: &mut [u32],
-) -> Result<i32, AnyError> {
+) -> Result<i32, ZlibError> {
let mut zlib = resource.inner.borrow_mut();
- let zlib = zlib
- .as_mut()
- .ok_or_else(|| type_error("zlib not initialized"))?;
+ let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?;
let flush = Flush::try_from(flush)?;
zlib.start_write(input, in_off, in_len, out, out_off, out_len, flush)?;
@@ -307,11 +314,9 @@ pub fn op_zlib_init(
#[smi] mem_level: i32,
#[smi] strategy: i32,
#[buffer] dictionary: &[u8],
-) -> Result<i32, AnyError> {
+) -> Result<i32, ZlibError> {
let mut zlib = resource.inner.borrow_mut();
- let zlib = zlib
- .as_mut()
- .ok_or_else(|| type_error("zlib not initialized"))?;
+ let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?;
check((8..=15).contains(&window_bits), "invalid windowBits")?;
check((-1..=9).contains(&level), "invalid level")?;
@@ -348,13 +353,11 @@ pub fn op_zlib_init(
#[op2(fast)]
#[smi]
-pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result<i32, AnyError> {
+pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result<i32, ZlibError> {
let mut zlib = resource.inner.borrow_mut();
- let zlib = zlib
- .as_mut()
- .ok_or_else(|| type_error("zlib not initialized"))?;
+ let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?;
- zlib.reset_stream()?;
+ zlib.reset_stream();
Ok(zlib.err)
}
@@ -362,12 +365,10 @@ pub fn op_zlib_reset(#[cppgc] resource: &Zlib) -> Result<i32, AnyError> {
#[op2(fast)]
pub fn op_zlib_close_if_pending(
#[cppgc] resource: &Zlib,
-) -> Result<(), AnyError> {
+) -> Result<(), ZlibError> {
let pending_close = {
let mut zlib = resource.inner.borrow_mut();
- let zlib = zlib
- .as_mut()
- .ok_or_else(|| type_error("zlib not initialized"))?;
+ let zlib = zlib.as_mut().ok_or(ZlibError::NotInitialized)?;
zlib.write_in_progress = false;
zlib.pending_close
@@ -381,6 +382,15 @@ pub fn op_zlib_close_if_pending(
Ok(())
}
+#[op2(fast)]
+#[smi]
+pub fn op_zlib_crc32(#[buffer] data: &[u8], #[smi] value: u32) -> u32 {
+ // SAFETY: `data` is a valid buffer.
+ unsafe {
+ zlib::crc32(value as c_ulong, data.as_ptr(), data.len() as u32) as u32
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/ext/node/ops/zlib/mode.rs b/ext/node/ops/zlib/mode.rs
index 753300cc4..41565f9b1 100644
--- a/ext/node/ops/zlib/mode.rs
+++ b/ext/node/ops/zlib/mode.rs
@@ -1,19 +1,8 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-#[derive(Debug)]
-pub enum Error {
- BadArgument,
-}
-
-impl std::fmt::Display for Error {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- match self {
- Error::BadArgument => write!(f, "bad argument"),
- }
- }
-}
-
-impl std::error::Error for Error {}
+#[derive(Debug, thiserror::Error)]
+#[error("bad argument")]
+pub struct ModeError;
macro_rules! repr_i32 {
($(#[$meta:meta])* $vis:vis enum $name:ident {
@@ -25,12 +14,12 @@ macro_rules! repr_i32 {
}
impl core::convert::TryFrom<i32> for $name {
- type Error = Error;
+ type Error = ModeError;
fn try_from(v: i32) -> Result<Self, Self::Error> {
match v {
$(x if x == $name::$vname as i32 => Ok($name::$vname),)*
- _ => Err(Error::BadArgument),
+ _ => Err(ModeError),
}
}
}