summaryrefslogtreecommitdiff
path: root/ext/node/zlib
diff options
context:
space:
mode:
authorBartek IwaƄczuk <biwanczuk@gmail.com>2023-04-24 12:22:21 +0200
committerGitHub <noreply@github.com>2023-04-24 12:22:21 +0200
commit1f0360c07382dbd86066d1aa8aa4bae34aff18c5 (patch)
treecc82d00aea829f0b3d3949f40df9696b099ee662 /ext/node/zlib
parent28e2c7204fe02304a8fc3339d7758eec0f64f723 (diff)
refactor(ext/node): reorganize ops (#18799)
Move all op related code of "ext/node" to "ext/node/ops" module. These files were unnecessarily scattered around the extension.
Diffstat (limited to 'ext/node/zlib')
-rw-r--r--ext/node/zlib/alloc.rs64
-rw-r--r--ext/node/zlib/mod.rs450
-rw-r--r--ext/node/zlib/mode.rs71
-rw-r--r--ext/node/zlib/stream.rs136
4 files changed, 0 insertions, 721 deletions
diff --git a/ext/node/zlib/alloc.rs b/ext/node/zlib/alloc.rs
deleted file mode 100644
index c7fecadd8..000000000
--- a/ext/node/zlib/alloc.rs
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-// Workaround for https://github.com/rust-lang/libz-sys/issues/55
-// See https://github.com/rust-lang/flate2-rs/blob/31fb07820345691352aaa64f367c1e482ad9cfdc/src/ffi/c.rs#L60
-use std::alloc::Layout;
-use std::alloc::{self};
-use std::os::raw::c_void;
-use std::ptr;
-
-const ALIGN: usize = std::mem::align_of::<usize>();
-
-fn align_up(size: usize, align: usize) -> usize {
- (size + align - 1) & !(align - 1)
-}
-
-pub extern "C" fn zalloc(
- _ptr: *mut c_void,
- items: u32,
- item_size: u32,
-) -> *mut c_void {
- // We need to multiply `items` and `item_size` to get the actual desired
- // allocation size. Since `zfree` doesn't receive a size argument we
- // also need to allocate space for a `usize` as a header so we can store
- // how large the allocation is to deallocate later.
- let size = match (items as usize)
- .checked_mul(item_size as usize)
- .map(|size| align_up(size, ALIGN))
- .and_then(|i| i.checked_add(std::mem::size_of::<usize>()))
- {
- Some(i) => i,
- None => return ptr::null_mut(),
- };
-
- // Make sure the `size` isn't too big to fail `Layout`'s restrictions
- let layout = match Layout::from_size_align(size, ALIGN) {
- Ok(layout) => layout,
- Err(_) => return ptr::null_mut(),
- };
-
- // SAFETY: `layout` has non-zero size, guaranteed to be a sentinel address
- // or a null pointer.
- unsafe {
- // Allocate the data, and if successful store the size we allocated
- // at the beginning and then return an offset pointer.
- let ptr = alloc::alloc(layout) as *mut usize;
- if ptr.is_null() {
- return ptr as *mut c_void;
- }
- *ptr = size;
- ptr.add(1) as *mut c_void
- }
-}
-
-pub extern "C" fn zfree(_ptr: *mut c_void, address: *mut c_void) {
- // SAFETY: Move our address being free'd back one pointer, read the size we
- // stored in `zalloc`, and then free it using the standard Rust
- // allocator.
- unsafe {
- let ptr = (address as *mut usize).offset(-1);
- let size = *ptr;
- let layout = Layout::from_size_align_unchecked(size, ALIGN);
- alloc::dealloc(ptr as *mut u8, layout)
- }
-}
diff --git a/ext/node/zlib/mod.rs b/ext/node/zlib/mod.rs
deleted file mode 100644
index c103b3009..000000000
--- a/ext/node/zlib/mod.rs
+++ /dev/null
@@ -1,450 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use deno_core::error::bad_resource_id;
-use deno_core::error::type_error;
-use deno_core::error::AnyError;
-use deno_core::op;
-use deno_core::OpState;
-use libz_sys::*;
-use std::borrow::Cow;
-use std::cell::RefCell;
-use std::future::Future;
-use std::rc::Rc;
-
-mod alloc;
-mod mode;
-mod stream;
-
-use mode::Flush;
-use mode::Mode;
-
-use self::stream::StreamWrapper;
-
-#[inline]
-fn check(condition: bool, msg: &str) -> Result<(), AnyError> {
- if condition {
- Ok(())
- } else {
- Err(type_error(msg.to_string()))
- }
-}
-
-#[inline]
-fn zlib(state: &mut OpState, handle: u32) -> Result<Rc<Zlib>, AnyError> {
- state
- .resource_table
- .get::<Zlib>(handle)
- .map_err(|_| bad_resource_id())
-}
-
-#[derive(Default)]
-struct ZlibInner {
- dictionary: Option<Vec<u8>>,
- err: i32,
- flush: Flush,
- init_done: bool,
- level: i32,
- mem_level: i32,
- mode: Mode,
- strategy: i32,
- window_bits: i32,
- write_in_progress: bool,
- pending_close: bool,
- gzib_id_bytes_read: u32,
- strm: StreamWrapper,
-}
-
-const GZIP_HEADER_ID1: u8 = 0x1f;
-const GZIP_HEADER_ID2: u8 = 0x8b;
-
-impl ZlibInner {
- #[allow(clippy::too_many_arguments)]
- fn start_write(
- &mut self,
- input: &[u8],
- in_off: u32,
- in_len: u32,
- out: &mut [u8],
- out_off: u32,
- out_len: u32,
- flush: Flush,
- ) -> Result<(), 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")?;
-
- self.write_in_progress = true;
-
- 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"))?
- .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"))?
- .as_mut_ptr();
-
- self.strm.avail_in = in_len;
- self.strm.next_in = next_in;
- self.strm.avail_out = out_len;
- self.strm.next_out = next_out;
-
- self.flush = flush;
- Ok(())
- }
-
- fn do_write(&mut self, flush: Flush) -> Result<(), AnyError> {
- self.flush = flush;
- match self.mode {
- Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => {
- self.err = self.strm.deflate(flush);
- }
- // Auto-detect mode.
- Mode::Unzip if self.strm.avail_in > 0 => 'blck: {
- let mut next_expected_header_byte = Some(0);
- // SAFETY: `self.strm.next_in` is valid pointer to the input buffer.
- // `self.strm.avail_in` is the length of the input buffer that is only set by
- // `start_write`.
- let strm = unsafe {
- std::slice::from_raw_parts(
- self.strm.next_in,
- self.strm.avail_in as usize,
- )
- };
-
- if self.gzib_id_bytes_read == 0 {
- if strm[0] == GZIP_HEADER_ID1 {
- self.gzib_id_bytes_read = 1;
- next_expected_header_byte = Some(1);
-
- // Not enough.
- if self.strm.avail_in == 1 {
- break 'blck;
- }
- } else {
- self.mode = Mode::Inflate;
- next_expected_header_byte = None;
- }
- }
-
- if self.gzib_id_bytes_read == 1 {
- let byte = match next_expected_header_byte {
- Some(i) => strm[i],
- None => break 'blck,
- };
- if byte == GZIP_HEADER_ID2 {
- self.gzib_id_bytes_read = 2;
- self.mode = Mode::Gunzip;
- } else {
- self.mode = Mode::Inflate;
- }
- } else if next_expected_header_byte.is_some() {
- return Err(type_error(
- "invalid number of gzip magic number bytes read",
- ));
- }
- }
- _ => {}
- }
-
- match self.mode {
- Mode::Inflate
- | Mode::Gunzip
- | Mode::InflateRaw
- // We're still reading the header.
- | Mode::Unzip => {
- self.err = self.strm.inflate(self.flush);
- // TODO(@littledivy): Use if let chain when it is stable.
- // https://github.com/rust-lang/rust/issues/53667
- //
- // Data was encoded with dictionary
- if let (Z_NEED_DICT, Some(dictionary)) = (self.err, &self.dictionary) {
- self.err = self.strm.inflate_set_dictionary(dictionary);
-
- if self.err == Z_OK {
- self.err = self.strm.inflate(flush);
- } else if self.err == Z_DATA_ERROR {
- self.err = Z_NEED_DICT;
- }
- }
-
- while self.strm.avail_in > 0
- && self.mode == Mode::Gunzip
- && self.err == Z_STREAM_END
- // SAFETY: `strm` is a valid pointer to zlib strm.
- // `strm.next_in` is initialized to the input buffer.
- && unsafe { *self.strm.next_in } != 0x00
- {
- self.err = self.strm.reset(self.mode);
- self.err = self.strm.inflate(flush);
- }
- }
- _ => {}
- }
-
- let done = self.strm.avail_out != 0 && self.flush == Flush::Finish;
- // We're are not done yet, but output buffer is full
- if self.err == Z_BUF_ERROR && !done {
- // Set to Z_OK to avoid reporting the error in JS.
- self.err = Z_OK;
- }
-
- self.write_in_progress = false;
- Ok(())
- }
-
- fn init_stream(&mut self) -> Result<(), AnyError> {
- match self.mode {
- Mode::Gzip | Mode::Gunzip => self.window_bits += 16,
- Mode::Unzip => self.window_bits += 32,
- Mode::DeflateRaw | Mode::InflateRaw => self.window_bits *= -1,
- _ => {}
- }
-
- self.err = match self.mode {
- Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => self.strm.deflate_init(
- self.level,
- self.window_bits,
- self.mem_level,
- self.strategy,
- ),
- Mode::Inflate | Mode::Gunzip | Mode::InflateRaw | Mode::Unzip => {
- self.strm.inflate_init(self.window_bits)
- }
- Mode::None => return Err(type_error("Unknown mode")),
- };
-
- self.write_in_progress = false;
- self.init_done = true;
-
- Ok(())
- }
-
- fn close(&mut self) -> Result<bool, AnyError> {
- if self.write_in_progress {
- self.pending_close = true;
- return Ok(false);
- }
-
- self.pending_close = false;
- check(self.init_done, "close before init")?;
-
- self.strm.end(self.mode);
- self.mode = Mode::None;
- Ok(true)
- }
-
- fn reset_stream(&mut self) -> Result<(), AnyError> {
- self.err = self.strm.reset(self.mode);
-
- Ok(())
- }
-}
-
-struct Zlib {
- inner: RefCell<ZlibInner>,
-}
-
-impl deno_core::Resource for Zlib {
- fn name(&self) -> Cow<str> {
- "zlib".into()
- }
-}
-
-#[op]
-pub fn op_zlib_new(state: &mut OpState, mode: i32) -> Result<u32, AnyError> {
- let mode = Mode::try_from(mode)?;
-
- let inner = ZlibInner {
- mode,
- ..Default::default()
- };
-
- Ok(state.resource_table.add(Zlib {
- inner: RefCell::new(inner),
- }))
-}
-
-#[op]
-pub fn op_zlib_close(state: &mut OpState, handle: u32) -> Result<(), AnyError> {
- let resource = zlib(state, handle)?;
- let mut zlib = resource.inner.borrow_mut();
-
- // If there is a pending write, defer the close until the write is done.
- zlib.close()?;
-
- Ok(())
-}
-
-#[op]
-pub fn op_zlib_write_async(
- state: Rc<RefCell<OpState>>,
- handle: u32,
- flush: i32,
- input: &[u8],
- in_off: u32,
- in_len: u32,
- out: &mut [u8],
- out_off: u32,
- out_len: u32,
-) -> Result<
- impl Future<Output = Result<(i32, u32, u32), AnyError>> + 'static,
- AnyError,
-> {
- let mut state_mut = state.borrow_mut();
- let resource = zlib(&mut state_mut, handle)?;
-
- let mut strm = resource.inner.borrow_mut();
- let flush = Flush::try_from(flush)?;
- strm.start_write(input, in_off, in_len, out, out_off, out_len, flush)?;
-
- let state = state.clone();
- Ok(async move {
- let mut state_mut = state.borrow_mut();
- let resource = zlib(&mut state_mut, handle)?;
- let mut zlib = resource.inner.borrow_mut();
-
- zlib.do_write(flush)?;
- Ok((zlib.err, zlib.strm.avail_out, zlib.strm.avail_in))
- })
-}
-
-#[op]
-pub fn op_zlib_write(
- state: &mut OpState,
- handle: u32,
- flush: i32,
- input: &[u8],
- in_off: u32,
- in_len: u32,
- out: &mut [u8],
- out_off: u32,
- out_len: u32,
- result: &mut [u32],
-) -> Result<i32, AnyError> {
- let resource = zlib(state, handle)?;
-
- let mut zlib = resource.inner.borrow_mut();
- let flush = Flush::try_from(flush)?;
- zlib.start_write(input, in_off, in_len, out, out_off, out_len, flush)?;
- zlib.do_write(flush)?;
-
- result[0] = zlib.strm.avail_out;
- result[1] = zlib.strm.avail_in;
-
- Ok(zlib.err)
-}
-
-#[op]
-pub fn op_zlib_init(
- state: &mut OpState,
- handle: u32,
- level: i32,
- window_bits: i32,
- mem_level: i32,
- strategy: i32,
- dictionary: Option<&[u8]>,
-) -> Result<i32, AnyError> {
- let resource = zlib(state, handle)?;
- let mut zlib = resource.inner.borrow_mut();
-
- check((8..=15).contains(&window_bits), "invalid windowBits")?;
- check((-1..=9).contains(&level), "invalid level")?;
-
- check((1..=9).contains(&mem_level), "invalid memLevel")?;
-
- check(
- strategy == Z_DEFAULT_STRATEGY
- || strategy == Z_FILTERED
- || strategy == Z_HUFFMAN_ONLY
- || strategy == Z_RLE
- || strategy == Z_FIXED,
- "invalid strategy",
- )?;
-
- zlib.level = level;
- zlib.window_bits = window_bits;
- zlib.mem_level = mem_level;
- zlib.strategy = strategy;
-
- zlib.flush = Flush::None;
- zlib.err = Z_OK;
-
- zlib.init_stream()?;
-
- zlib.dictionary = dictionary.map(|buf| buf.to_vec());
-
- Ok(zlib.err)
-}
-
-#[op]
-pub fn op_zlib_reset(
- state: &mut OpState,
- handle: u32,
-) -> Result<i32, AnyError> {
- let resource = zlib(state, handle)?;
-
- let mut zlib = resource.inner.borrow_mut();
- zlib.reset_stream()?;
-
- Ok(zlib.err)
-}
-
-#[op]
-pub fn op_zlib_close_if_pending(
- state: &mut OpState,
- handle: u32,
-) -> Result<(), AnyError> {
- let resource = zlib(state, handle)?;
- let pending_close = {
- let mut zlib = resource.inner.borrow_mut();
- zlib.write_in_progress = false;
- zlib.pending_close
- };
- if pending_close {
- drop(resource);
- state.resource_table.close(handle)?;
- }
-
- Ok(())
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn zlib_start_write() {
- // buffer, length, should pass
- type WriteVector = (&'static [u8], u32, u32, bool);
- const WRITE_VECTORS: [WriteVector; 8] = [
- (b"Hello", 5, 0, true),
- (b"H", 1, 0, true),
- (b"", 0, 0, true),
- // Overrun the buffer
- (b"H", 5, 0, false),
- (b"ello", 5, 0, false),
- (b"Hello", 5, 1, false),
- (b"H", 1, 1, false),
- (b"", 0, 1, false),
- ];
-
- for (input, len, offset, expected) in WRITE_VECTORS.iter() {
- let mut stream = ZlibInner {
- mode: Mode::Inflate,
- ..Default::default()
- };
-
- stream.init_stream().unwrap();
- assert_eq!(stream.err, Z_OK);
- assert_eq!(
- stream
- .start_write(input, *offset, *len, &mut [], 0, 0, Flush::None)
- .is_ok(),
- *expected
- );
- assert_eq!(stream.err, Z_OK);
- stream.close().unwrap();
- }
- }
-}
diff --git a/ext/node/zlib/mode.rs b/ext/node/zlib/mode.rs
deleted file mode 100644
index ef89805ba..000000000
--- a/ext/node/zlib/mode.rs
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use libz_sys as sys;
-
-#[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 {}
-
-macro_rules! repr_i32 {
- ($(#[$meta:meta])* $vis:vis enum $name:ident {
- $($(#[$vmeta:meta])* $vname:ident $(= $val:expr)?,)*
- }) => {
- $(#[$meta])*
- $vis enum $name {
- $($(#[$vmeta])* $vname $(= $val)?,)*
- }
-
- impl core::convert::TryFrom<i32> for $name {
- type Error = Error;
-
- fn try_from(v: i32) -> Result<Self, Self::Error> {
- match v {
- $(x if x == $name::$vname as i32 => Ok($name::$vname),)*
- _ => Err(Error::BadArgument),
- }
- }
- }
- }
- }
-
-repr_i32! {
- #[repr(i32)]
- #[derive(Clone, Copy, Debug, PartialEq, Default)]
- pub enum Mode {
- #[default]
- None,
- Deflate,
- Inflate,
- Gzip,
- Gunzip,
- DeflateRaw,
- InflateRaw,
- Unzip,
- }
-}
-
-repr_i32! {
- #[repr(i32)]
- #[derive(Clone, Copy, Debug, PartialEq, Default)]
- pub enum Flush {
- #[default]
- None = sys::Z_NO_FLUSH,
- Partial = sys::Z_PARTIAL_FLUSH,
- Sync = sys::Z_SYNC_FLUSH,
- Full = sys::Z_FULL_FLUSH,
- Finish = sys::Z_FINISH,
- Block = sys::Z_BLOCK,
- Trees = sys::Z_TREES,
- }
-}
diff --git a/ext/node/zlib/stream.rs b/ext/node/zlib/stream.rs
deleted file mode 100644
index 90cd58ed3..000000000
--- a/ext/node/zlib/stream.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-
-use super::mode::Flush;
-use super::mode::Mode;
-use libz_sys as sys;
-use std::ffi::c_int;
-use std::ops::Deref;
-use std::ops::DerefMut;
-
-pub struct StreamWrapper {
- pub strm: sys::z_stream,
-}
-
-impl Default for StreamWrapper {
- fn default() -> Self {
- Self {
- strm: sys::z_stream {
- next_in: std::ptr::null_mut(),
- avail_in: 0,
- total_in: 0,
- next_out: std::ptr::null_mut(),
- avail_out: 0,
- total_out: 0,
- msg: std::ptr::null_mut(),
- state: std::ptr::null_mut(),
- zalloc: super::alloc::zalloc,
- zfree: super::alloc::zfree,
- opaque: 0 as sys::voidpf,
- data_type: 0,
- adler: 0,
- reserved: 0,
- },
- }
- }
-}
-
-impl Deref for StreamWrapper {
- type Target = sys::z_stream;
-
- fn deref(&self) -> &Self::Target {
- &self.strm
- }
-}
-
-impl DerefMut for StreamWrapper {
- fn deref_mut(&mut self) -> &mut Self::Target {
- &mut self.strm
- }
-}
-
-impl StreamWrapper {
- pub fn reset(&mut self, mode: Mode) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe {
- match mode {
- Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => {
- sys::deflateReset(&mut self.strm)
- }
- Mode::Inflate | Mode::Gunzip | Mode::InflateRaw | Mode::Unzip => {
- sys::inflateReset(&mut self.strm)
- }
- Mode::None => unreachable!(),
- }
- }
- }
-
- pub fn end(&mut self, mode: Mode) {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe {
- match mode {
- Mode::Deflate | Mode::Gzip | Mode::DeflateRaw => {
- sys::deflateEnd(&mut self.strm);
- }
- Mode::Inflate | Mode::Gunzip | Mode::InflateRaw | Mode::Unzip => {
- sys::inflateEnd(&mut self.strm);
- }
- Mode::None => {}
- }
- }
- }
-
- pub fn deflate_init(
- &mut self,
- level: c_int,
- window_bits: c_int,
- mem_level: c_int,
- strategy: c_int,
- ) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe {
- sys::deflateInit2_(
- &mut self.strm,
- level,
- sys::Z_DEFLATED,
- window_bits,
- mem_level,
- strategy,
- sys::zlibVersion(),
- std::mem::size_of::<sys::z_stream>() as i32,
- )
- }
- }
-
- pub fn inflate_init(&mut self, window_bits: c_int) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe {
- sys::inflateInit2_(
- &mut self.strm,
- window_bits,
- sys::zlibVersion(),
- std::mem::size_of::<sys::z_stream>() as i32,
- )
- }
- }
-
- pub fn deflate(&mut self, flush: Flush) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe { sys::deflate(&mut self.strm, flush as _) }
- }
-
- pub fn inflate(&mut self, flush: Flush) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe { sys::inflate(&mut self.strm, flush as _) }
- }
-
- pub fn inflate_set_dictionary(&mut self, dictionary: &[u8]) -> c_int {
- // SAFETY: `self.strm` is an initialized `z_stream`.
- unsafe {
- sys::inflateSetDictionary(
- &mut self.strm,
- dictionary.as_ptr() as *const _,
- dictionary.len() as _,
- )
- }
- }
-}