zlib: expose zlib.crc32() · nodejs/node@6b4dac3 · GitHub
Skip to content

Commit 6b4dac3

Browse files
joyeecheungtargos
authored andcommitted
zlib: expose zlib.crc32()
This patch exposes the crc32() function from zlib to user-land. It computes a 32-bit Cyclic Redundancy Check checksum of `data`. If `value` is specified, it is used as the starting value of the checksum, otherwise, 0 is used as the starting value. ```js const zlib = require('node:zlib'); const { Buffer } = require('node:buffer'); let crc = zlib.crc32('hello'); // 907060870 crc = zlib.crc32('world', crc); // 4192936109 crc = zlib.crc32(Buffer.from('hello')); // 907060870 crc = zlib.crc32(Buffer.from('world'), crc); // 4192936109 ``` PR-URL: #52692 Reviewed-By: Yagiz Nizipli <yagiz.nizipli@sentry.io> Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Mohammed Keyvanzadeh <mohammadkeyvanzade94@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent a0147ff commit 6b4dac3

4 files changed

Lines changed: 313 additions & 0 deletions

File tree

doc/api/zlib.md

Lines changed: 62 additions & 0 deletions

lib/zlib.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ const {
6363
isUint8Array,
6464
} = require('internal/util/types');
6565
const binding = internalBinding('zlib');
66+
const { crc32: crc32Native } = binding;
6667
const assert = require('internal/assert');
6768
const {
6869
Buffer,
@@ -72,6 +73,7 @@ const { owner_symbol } = require('internal/async_hooks').symbols;
7273
const {
7374
validateFunction,
7475
validateNumber,
76+
validateUint32,
7577
} = require('internal/validators');
7678

7779
const kFlushFlag = Symbol('kFlushFlag');
@@ -899,6 +901,14 @@ function createProperty(ctor) {
899901
};
900902
}
901903

904+
function crc32(data, value = 0) {
905+
if (typeof data !== 'string' && !isArrayBufferView(data)) {
906+
throw new ERR_INVALID_ARG_TYPE('data', ['Buffer', 'TypedArray', 'DataView', 'string'], data);
907+
}
908+
validateUint32(value, 'value');
909+
return crc32Native(data, value);
910+
}
911+
902912
// Legacy alias on the C++ wrapper object. This is not public API, so we may
903913
// want to runtime-deprecate it at some point. There's no hurry, though.
904914
ObjectDefineProperty(binding.Zlib.prototype, 'jsref', {
@@ -908,6 +918,7 @@ ObjectDefineProperty(binding.Zlib.prototype, 'jsref', {
908918
});
909919

910920
module.exports = {
921+
crc32,
911922
Deflate,
912923
Inflate,
913924
Gzip,

src/node_zlib.cc

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1286,6 +1286,33 @@ struct MakeClass {
12861286
}
12871287
};
12881288

1289+
template <typename T, typename F>
1290+
T CallOnSequence(v8::Isolate* isolate, Local<Value> value, F callback) {
1291+
if (value->IsString()) {
1292+
Utf8Value data(isolate, value);
1293+
return callback(data.out(), data.length());
1294+
} else {
1295+
ArrayBufferViewContents<char> data(value);
1296+
return callback(data.data(), data.length());
1297+
}
1298+
}
1299+
1300+
// TODO(joyeecheung): use fast API
1301+
static void CRC32(const FunctionCallbackInfo<Value>& args) {
1302+
CHECK(args[0]->IsArrayBufferView() || args[0]->IsString());
1303+
CHECK(args[1]->IsUint32());
1304+
uint32_t value = args[1].As<v8::Uint32>()->Value();
1305+
1306+
uint32_t result = CallOnSequence<uint32_t>(
1307+
args.GetIsolate(),
1308+
args[0],
1309+
[&](const char* data, size_t size) -> uint32_t {
1310+
return crc32(value, reinterpret_cast<const Bytef*>(data), size);
1311+
});
1312+
1313+
args.GetReturnValue().Set(result);
1314+
}
1315+
12891316
void Initialize(Local<Object> target,
12901317
Local<Value> unused,
12911318
Local<Context> context,
@@ -1296,6 +1323,7 @@ void Initialize(Local<Object> target,
12961323
MakeClass<BrotliEncoderStream>::Make(env, target, "BrotliEncoder");
12971324
MakeClass<BrotliDecoderStream>::Make(env, target, "BrotliDecoder");
12981325

1326+
SetMethod(context, target, "crc32", CRC32);
12991327
target->Set(env->context(),
13001328
FIXED_ONE_BYTE_STRING(env->isolate(), "ZLIB_VERSION"),
13011329
FIXED_ONE_BYTE_STRING(env->isolate(), ZLIB_VERSION)).Check();
@@ -1305,6 +1333,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
13051333
MakeClass<ZlibStream>::Make(registry);
13061334
MakeClass<BrotliEncoderStream>::Make(registry);
13071335
MakeClass<BrotliDecoderStream>::Make(registry);
1336+
registry->Register(CRC32);
13081337
}
13091338

13101339
} // anonymous namespace

test/parallel/test-zlib-crc32.js

Lines changed: 211 additions & 0 deletions

0 commit comments

Comments
 (0)