Skip to content

Commit

Permalink
stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
littledivy committed Mar 23, 2023
1 parent e3436f2 commit 917ab1f
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 35 deletions.
2 changes: 2 additions & 0 deletions ext/node/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,10 @@ deno_core::extension!(deno_node,
idna::op_node_idna_punycode_encode,
zlib::op_zlib_new,
zlib::op_zlib_close,
zlib::op_zlib_close_if_pending,
zlib::op_zlib_write,
zlib::op_zlib_write_async,
zlib::op_zlib_get_message,
zlib::op_zlib_init,
zlib::op_zlib_reset,
op_node_build_os,
Expand Down
53 changes: 46 additions & 7 deletions ext/node/polyfills/_zlib_binding.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class Zlib {
out_off,
out_len,
) {
ops.op_zlib_write(
const err = ops.op_zlib_write(
this.#handle,
flush,
input,
Expand All @@ -80,7 +80,32 @@ class Zlib {
writeResult,
);

return [writeResult[1], writeResult[0]];
if (this.#checkError(err)) {
return [writeResult[1], writeResult[0]];
}
return;
}

#checkError(err) {
// Acceptable error states depend on the type of zlib stream.
switch (err) {
case Z_BUF_ERROR:
this.#error("unexpected end of file");
return false;
case Z_OK:
case Z_STREAM_END:
// normal statuses, not fatal
break;
case Z_NEED_DICT:
this.#error("Bad dictionary");
return false;
default:
// something else.
this.#error("Zlib error");
return false;
}

return true;
}

write(
Expand All @@ -102,8 +127,10 @@ class Zlib {
out,
out_off,
out_len,
).then(([availOut, availIn]) => {
this.callback(availIn, availOut);
).then(([err, availOut, availIn]) => {
if (this.#checkError(err)) {
this.callback(availIn, availOut);
}
});

return this;
Expand All @@ -115,23 +142,35 @@ class Zlib {
memLevel,
strategy,
dictionary,
) {
ops.op_zlib_init(
) {
const err = ops.op_zlib_init(
this.#handle,
level,
windowBits,
memLevel,
strategy,
dictionary,
);

if (err != Z_OK) {
this.#error("Failed to initialize zlib", err);
}
}

params() {
throw new Error("deflateParams Not supported");
}

reset() {
ops.op_zlib_reset(this.#handle);
const err = ops.op_zlib_reset(this.#handle);
if (err != Z_OK) {
this.#error("Failed to reset stream");
}
}

#error(message) {
this.onerror(message, this.err);
ops.op_zlib_close_if_pending(this.#handle);
}
}

Expand Down
105 changes: 77 additions & 28 deletions ext/node/zlib/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,14 +84,13 @@ impl ZlibInner {
fn do_write(&mut self, flush: i32) -> Result<(), AnyError> {
match self.mode {
DEFLATE | GZIP | DEFLATERAW => {
unsafe { libz_sys::deflate(&mut self.strm, flush) };
self.err = unsafe { libz_sys::deflate(&mut self.strm, flush) };
}
UNZIP if self.strm.avail_in > 0 => {
let mut next_expected_header_byte = Some(0);

if self.gzib_id_bytes_read == 0 {
let byte =
unsafe { *self.strm.next_in.offset(0) };
let byte = unsafe { *self.strm.next_in.offset(0) };
if byte == GZIP_HEADER_ID1 {
self.gzib_id_bytes_read = 1;
next_expected_header_byte = Some(1);
Expand All @@ -108,8 +107,9 @@ impl ZlibInner {
}

if self.gzib_id_bytes_read == 1 && next_expected_header_byte.is_some() {
let byte =
unsafe { *self.strm.next_in.offset(next_expected_header_byte.unwrap()) };
let byte = unsafe {
*self.strm.next_in.offset(next_expected_header_byte.unwrap())
};
if byte == GZIP_HEADER_ID2 {
self.gzib_id_bytes_read = 2;
self.mode = GUNZIP;
Expand All @@ -127,8 +127,8 @@ impl ZlibInner {

match self.mode {
INFLATE | GUNZIP | INFLATERAW => {
self.err = unsafe { libz_sys::inflate(&mut self.strm, flush) };
self.err = unsafe { libz_sys::inflate(&mut self.strm, self.flush) };

// TODO(@littledivy): Use if let chain when it is stable.
// https://github.com/rust-lang/rust/issues/53667
if self.err == Z_NEED_DICT && self.dictionary.is_some() {
Expand All @@ -143,7 +143,7 @@ impl ZlibInner {
};

if self.err == Z_OK {
self.err = unsafe { libz_sys::inflate(&mut self.strm, flush) };
self.err = unsafe { libz_sys::inflate(&mut self.strm, self.flush) };
} else if self.err == Z_DATA_ERROR {
self.err = Z_NEED_DICT;
}
Expand All @@ -160,7 +160,11 @@ impl ZlibInner {
}
_ => {}
}

if self.err == Z_BUF_ERROR
&& !(self.strm.avail_out != 0 && self.flush == Z_FINISH)
{
self.err = Z_OK;
};
self.write_in_progress = false;
Ok(())
}
Expand Down Expand Up @@ -271,7 +275,7 @@ pub fn op_zlib_write_async(
out_off: u32,
out_len: u32,
) -> Result<
impl Future<Output = Result<(u32, u32), AnyError>> + 'static,
impl Future<Output = Result<(i32, u32, u32), AnyError>> + 'static,
AnyError,
> {
let resource = state
Expand All @@ -292,8 +296,7 @@ pub fn op_zlib_write_async(
.map_err(|_| bad_resource_id())?;
let mut zlib = resource.inner.borrow_mut();
zlib.do_write(flush)?;

Ok((zlib.strm.avail_out, zlib.strm.avail_in))
Ok((zlib.err, zlib.strm.avail_out, zlib.strm.avail_in))
})
}

Expand All @@ -309,7 +312,7 @@ pub fn op_zlib_write(
out_off: u32,
out_len: u32,
result: &mut [u32],
) -> Result<(), AnyError> {
) -> Result<i32, AnyError> {
let resource = state
.resource_table
.get::<Zlib>(handle)
Expand All @@ -322,7 +325,7 @@ pub fn op_zlib_write(
result[0] = zlib.strm.avail_out as u32;
result[1] = zlib.strm.avail_in as u32;

Ok(())
Ok(zlib.err)
}

#[op]
Expand All @@ -334,7 +337,7 @@ pub fn op_zlib_init(
mem_level: i32,
strategy: i32,
dictionary: Option<ZeroCopyBuf>,
) -> Result<(), AnyError> {
) -> Result<i32, AnyError> {
let resource = state
.resource_table
.get::<Zlib>(handle)
Expand Down Expand Up @@ -370,7 +373,7 @@ pub fn op_zlib_init(
_ => {}
}

match zlib.mode {
zlib.err = match zlib.mode {
DEFLATE | GZIP | DEFLATERAW => unsafe {
deflateInit2_(
&mut zlib.strm,
Expand All @@ -381,28 +384,31 @@ pub fn op_zlib_init(
zlib.strategy,
zlibVersion(),
std::mem::size_of::<z_stream>() as i32,
);
)
},
INFLATE | GUNZIP | INFLATERAW | UNZIP => unsafe {
inflateInit2_(
&mut zlib.strm,
zlib.window_bits,
zlibVersion(),
std::mem::size_of::<z_stream>() as i32,
);
)
},
_ => return Err(type_error("Unknown mode")),
}
};

zlib.dictionary = dictionary.map(|buf| buf.to_vec());
zlib.write_in_progress = false;
zlib.init_done = true;

Ok(())
Ok(zlib.err)
}

#[op]
pub fn op_zlib_reset(state: &mut OpState, handle: u32) -> Result<(), AnyError> {
pub fn op_zlib_reset(
state: &mut OpState,
handle: u32,
) -> Result<i32, AnyError> {
let resource = state
.resource_table
.get::<Zlib>(handle)
Expand All @@ -411,15 +417,58 @@ pub fn op_zlib_reset(state: &mut OpState, handle: u32) -> Result<(), AnyError> {
let mut zlib = resource.inner.borrow_mut();

zlib.err = Z_OK;
match zlib.mode {
DEFLATE | GZIP | DEFLATERAW => {
unsafe { libz_sys::deflateReset(&mut zlib.strm) };
}
INFLATE | GUNZIP | INFLATERAW | UNZIP => {
unsafe { libz_sys::inflateReset(&mut zlib.strm) };
}
zlib.err = match zlib.mode {
DEFLATE | GZIP | DEFLATERAW => unsafe {
libz_sys::deflateReset(&mut zlib.strm)
},
INFLATE | GUNZIP | INFLATERAW | UNZIP => unsafe {
libz_sys::inflateReset(&mut zlib.strm)
},
_ => return Err(type_error("Unknown mode")),
};

Ok(zlib.err)
}

#[op]
pub fn op_zlib_close_if_pending(
state: &mut OpState,
handle: u32,
) -> Result<(), AnyError> {
let resource = state
.resource_table
.get::<Zlib>(handle)
.map_err(|_| bad_resource_id())?;
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(())
}

#[op]
pub fn op_zlib_get_message(
state: &mut OpState,
handle: u32,
) -> Result<Option<String>, AnyError> {
let resource = state
.resource_table
.get::<Zlib>(handle)
.map_err(|_| bad_resource_id())?;

let zlib = resource.inner.borrow();
if zlib.err == Z_OK {
return Ok(None);
}

let msg = unsafe { std::ffi::CStr::from_ptr(zlib.strm.msg) }
.to_string_lossy()
.to_string();
Ok(Some(msg))
}

0 comments on commit 917ab1f

Please sign in to comment.