Skip to content

Commit

Permalink
WIP: zlib one-shot methods (#2533)
Browse files Browse the repository at this point in the history
  • Loading branch information
npaun authored Aug 26, 2024
1 parent accbbec commit 2c6af65
Show file tree
Hide file tree
Showing 6 changed files with 684 additions and 33 deletions.
267 changes: 252 additions & 15 deletions src/node/internal/internal_zlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
// https://opensource.org/licenses/Apache-2.0
// Copyright Joyent and Node contributors. All rights reserved. MIT license.

import { default as zlibUtil, type ZlibOptions } from 'node-internal:zlib';
import {
default as zlibUtil,
type ZlibOptions,
type CompressCallback,
} from 'node-internal:zlib';
import { Buffer } from 'node-internal:internal_buffer';
import { validateUint32 } from 'node-internal:validators';
import { ERR_INVALID_ARG_TYPE } from 'node-internal:internal_errors';
import { isArrayBufferView } from 'node-internal:internal_types';
import { Zlib } from 'node-internal:internal_zlib_base';

const {
Expand All @@ -20,6 +23,253 @@ const {
CONST_UNZIP,
} = zlibUtil;

export function crc32(
data: ArrayBufferView | string,
value: number = 0
): number {
validateUint32(value, 'value');
return zlibUtil.crc32(data, value);
}

export function inflateSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(zlibUtil.zlibSync(data, options, zlibUtil.CONST_INFLATE));
}

export function deflateSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(zlibUtil.zlibSync(data, options, zlibUtil.CONST_DEFLATE));
}

export function gunzipSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(zlibUtil.zlibSync(data, options, zlibUtil.CONST_GUNZIP));
}

export function gzipSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(zlibUtil.zlibSync(data, options, zlibUtil.CONST_GZIP));
}

export function inflateRawSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(
zlibUtil.zlibSync(data, options, zlibUtil.CONST_INFLATERAW)
);
}

export function deflateRawSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(
zlibUtil.zlibSync(data, options, zlibUtil.CONST_DEFLATERAW)
);
}

export function unzipSync(
data: ArrayBufferView | string,
options: ZlibOptions = {}
): Buffer {
return Buffer.from(
zlibUtil.zlibSync(data, options, zlibUtil.CONST_DEFLATERAW)
);
}

function normalizeArgs(
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): [ZlibOptions, CompressCallback<Error, Buffer>] {
if (typeof optionsOrCallback === 'function') {
return [{}, optionsOrCallback];
} else if (typeof callbackOrUndefined === 'function') {
return [optionsOrCallback, callbackOrUndefined];
}

throw new ERR_INVALID_ARG_TYPE('callback', 'Function', callbackOrUndefined);
}

function wrapCallback(
callback: CompressCallback<Error, Buffer>
): CompressCallback<string, ArrayBuffer> {
return (error: string | undefined, result: ArrayBuffer | undefined) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
queueMicrotask(() => {
callback(
error ? new Error(error) : undefined,
result ? Buffer.from(result) : undefined
);
});
};
}

export function inflate(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function inflate(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function inflate(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(data, options, zlibUtil.CONST_INFLATE, wrapCallback(callback));
}

export function unzip(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function unzip(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function unzip(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(data, options, zlibUtil.CONST_UNZIP, wrapCallback(callback));
}

export function inflateRaw(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function inflateRaw(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function inflateRaw(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(
data,
options,
zlibUtil.CONST_INFLATERAW,
wrapCallback(callback)
);
}

export function gunzip(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function gunzip(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function gunzip(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(data, options, zlibUtil.CONST_GUNZIP, wrapCallback(callback));
}

export function deflate(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function deflate(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function deflate(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(data, options, zlibUtil.CONST_DEFLATE, wrapCallback(callback));
}

export function deflateRaw(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function deflateRaw(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function deflateRaw(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(
data,
options,
zlibUtil.CONST_DEFLATERAW,
wrapCallback(callback)
);
}

export function gzip(
data: ArrayBufferView | string,
callback: CompressCallback<Error, Buffer>
): void;
export function gzip(
data: ArrayBufferView | string,
options: ZlibOptions,
callback: CompressCallback<Error, Buffer>
): void;
export function gzip(
data: ArrayBufferView | string,
optionsOrCallback: ZlibOptions | CompressCallback<Error, Buffer>,
callbackOrUndefined?: CompressCallback<Error, Buffer>
): void {
const [options, callback] = normalizeArgs(
optionsOrCallback,
callbackOrUndefined
);
zlibUtil.zlib(data, options, zlibUtil.CONST_GZIP, wrapCallback(callback));
}

const constPrefix = 'CONST_';
export const constants: Record<string, number> = {};

Expand All @@ -41,19 +291,6 @@ Object.defineProperties(
)
);

export function crc32(
data: ArrayBufferView | string,
value: number = 0
): number {
if (typeof data === 'string') {
data = Buffer.from(data);
} else if (!isArrayBufferView(data)) {
throw new ERR_INVALID_ARG_TYPE('data', 'ArrayBufferView', typeof data);
}
validateUint32(value, 'value');
return zlibUtil.crc32(data, value);
}

export class Gzip extends Zlib {
public constructor(options: ZlibOptions) {
super(options, CONST_GZIP);
Expand Down
18 changes: 18 additions & 0 deletions src/node/internal/zlib.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,24 @@ import { owner_symbol, type Zlib } from 'node-internal:internal_zlib_base';

export function crc32(data: ArrayBufferView, value: number): number;

export type CompressCallback<ErrT, BufT> = (
error?: ErrT,
result?: BufT
) => void;

export function crc32(data: ArrayBufferView | string, value: number): number;
export function zlibSync(
data: ArrayBufferView | string,
options: ZlibOptions,
mode: number
): ArrayBuffer;
export function zlib(
data: ArrayBufferView | string,
options: ZlibOptions,
mode: number,
cb: CompressCallback<string, ArrayBuffer>
): ArrayBuffer;

// zlib.constants (part of the API contract for node:zlib)
export const CONST_Z_NO_FLUSH: number;
export const CONST_Z_PARTIAL_FLUSH: number;
Expand Down
50 changes: 50 additions & 0 deletions src/node/zlib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,24 @@ const createInflate = protectMethod(zlib.createInflate);
const createInflateRaw = protectMethod(zlib.createInflateRaw);
const createUnzip = protectMethod(zlib.createUnzip);

const inflate = protectMethod(zlib.inflate);
const inflateSync = protectMethod(zlib.inflateSync);
const deflate = protectMethod(zlib.deflate);
const deflateSync = protectMethod(zlib.deflateSync);

const inflateRaw = protectMethod(zlib.inflateRaw);
const inflateRawSync = protectMethod(zlib.inflateRawSync);
const deflateRaw = protectMethod(zlib.deflateRaw);
const deflateRawSync = protectMethod(zlib.deflateRawSync);

const gzip = protectMethod(zlib.gzip);
const gzipSync = protectMethod(zlib.gzipSync);
const gunzip = protectMethod(zlib.gunzip);
const gunzipSync = protectMethod(zlib.gunzipSync);

const unzip = protectMethod(zlib.unzip);
const unzipSync = protectMethod(zlib.unzipSync);

export {
crc32,
constants,
Expand All @@ -50,6 +68,22 @@ export {
createInflate,
createInflateRaw,
createUnzip,

// One-shot methods
inflate,
inflateSync,
deflate,
deflateSync,
inflateRaw,
inflateRawSync,
deflateRaw,
deflateRawSync,
gzip,
gzipSync,
gunzip,
gunzipSync,
unzip,
unzipSync,
};

export default {
Expand All @@ -73,4 +107,20 @@ export default {
createInflate,
createInflateRaw,
createUnzip,

// One-shot methods
inflate,
inflateSync,
deflate,
deflateSync,
inflateRaw,
inflateRawSync,
deflateRaw,
deflateRawSync,
gzip,
gzipSync,
gunzip,
gunzipSync,
unzip,
unzipSync,
};
Loading

0 comments on commit 2c6af65

Please sign in to comment.