fix(ext/node): zlib.crc32() (#26856)

Fixes https://github.com/denoland/deno/issues/26845
This commit is contained in:
Divy Srivastava 2024-11-13 20:07:45 +05:30 committed by GitHub
parent 7d9ba09f5a
commit 6a4c6d83ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 69 additions and 0 deletions

View File

@ -345,6 +345,7 @@ deno_core::extension!(deno_node,
ops::zlib::op_zlib_write,
ops::zlib::op_zlib_init,
ops::zlib::op_zlib_reset,
ops::zlib::op_zlib_crc32,
ops::zlib::brotli::op_brotli_compress,
ops::zlib::brotli::op_brotli_compress_async,
ops::zlib::brotli::op_create_brotli_compress,

View File

@ -1,6 +1,7 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
use deno_core::op2;
use libc::c_ulong;
use std::borrow::Cow;
use std::cell::RefCell;
use zlib::*;
@ -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::*;

View File

@ -40,6 +40,58 @@ import {
createBrotliCompress,
createBrotliDecompress,
} from "ext:deno_node/_brotli.js";
import { ERR_INVALID_ARG_TYPE } from "ext:deno_node/internal/errors.ts";
import { validateUint32 } from "ext:deno_node/internal/validators.mjs";
import { op_zlib_crc32 } from "ext:core/ops";
import { core, primordials } from "ext:core/mod.js";
import { TextEncoder } from "ext:deno_web/08_text_encoding.js";
const {
Uint8Array,
TypedArrayPrototypeGetBuffer,
TypedArrayPrototypeGetByteLength,
TypedArrayPrototypeGetByteOffset,
DataViewPrototypeGetBuffer,
DataViewPrototypeGetByteLength,
DataViewPrototypeGetByteOffset,
} = primordials;
const { isTypedArray, isDataView } = core;
const enc = new TextEncoder();
const toU8 = (input) => {
if (typeof input === "string") {
return enc.encode(input);
}
if (isTypedArray(input)) {
return new Uint8Array(
TypedArrayPrototypeGetBuffer(input),
TypedArrayPrototypeGetByteOffset(input),
TypedArrayPrototypeGetByteLength(input),
);
} else if (isDataView(input)) {
return new Uint8Array(
DataViewPrototypeGetBuffer(input),
DataViewPrototypeGetByteOffset(input),
DataViewPrototypeGetByteLength(input),
);
}
return input;
};
export function crc32(data, value = 0) {
if (typeof data !== "string" && !isArrayBufferView(data)) {
throw new ERR_INVALID_ARG_TYPE("data", [
"Buffer",
"TypedArray",
"DataView",
"string",
], data);
}
validateUint32(value, "value");
return op_zlib_crc32(toU8(data), value);
}
export class Options {
constructor() {
@ -87,6 +139,7 @@ export default {
BrotliOptions,
codes,
constants,
crc32,
createBrotliCompress,
createBrotliDecompress,
createDeflate,

View File

@ -7,6 +7,7 @@ import {
brotliCompressSync,
brotliDecompressSync,
constants,
crc32,
createBrotliCompress,
createBrotliDecompress,
createDeflate,
@ -225,3 +226,7 @@ Deno.test("gzip() and gzipSync() accept ArrayBuffer", async () => {
const outputSync = gzipSync(buf);
assert(outputSync instanceof Buffer);
});
Deno.test("crc32()", () => {
assertEquals(crc32("hello world"), 222957957);
});