diff options
author | 2023-08-08 03:30:05 -0300 | |
---|---|---|
committer | 2023-08-07 23:30:05 -0700 | |
commit | 182e600eb79655e85b3f0371bc46fc4de8e70094 (patch) | |
tree | b91231bc9155cc769cc81a7b2f0892c47bd26d2c | |
parent | cb873cc0818d02216ac7285c58fe59883220d1a9 (diff) | |
download | bun-182e600eb79655e85b3f0371bc46fc4de8e70094.tar.gz bun-182e600eb79655e85b3f0371bc46fc4de8e70094.tar.zst bun-182e600eb79655e85b3f0371bc46fc4de8e70094.zip |
Fix `Bun.hash` functions (#4054)
* fix `Bun.hash` functions to behave as expected
* update Bun.hash tests
* properly test the returned hash
* include murmur32v2
* update Bun.hash docs
* run fmt
-rw-r--r-- | docs/api/hashing.md | 9 | ||||
-rw-r--r-- | examples/hashing.js | 19 | ||||
-rw-r--r-- | src/bun.js/api/bun.zig | 12 | ||||
-rw-r--r-- | test/js/bun/util/hash.test.js | 39 |
4 files changed, 42 insertions, 37 deletions
diff --git a/docs/api/hashing.md b/docs/api/hashing.md index 3c15e1346..13a285693 100644 --- a/docs/api/hashing.md +++ b/docs/api/hashing.md @@ -77,7 +77,7 @@ The standard `Bun.hash` functions uses [Wyhash](https://github.com/wangyi-fudan/ ```ts Bun.hash("some data here"); -// 976213160445840 +// 11562320457524636935n ``` The input can be a string, `TypedArray`, `DataView`, `ArrayBuffer`, or `SharedArrayBuffer`. @@ -91,14 +91,14 @@ Bun.hash(arr.buffer); Bun.hash(new DataView(arr.buffer)); ``` -Optionally, an integer seed can be specified as the second parameter. +Optionally, an integer seed can be specified as the second parameter. For 64-bit hashes seeds above `Number.MAX_SAFE_INTEGER` should be given as BigInt to avoid loss of precision. ```ts Bun.hash("some data here", 1234); -// 1173484059023252 +// 15724820720172937558n ``` -Additional hashing algorithms are available as properties on `Bun.hash`. The API is the same for each. +Additional hashing algorithms are available as properties on `Bun.hash`. The API is the same for each, only changing the return type from number for 32-bit hashes to bigint for 64-bit hashes. ```ts Bun.hash.wyhash("data", 1234); // equivalent to Bun.hash() @@ -107,6 +107,7 @@ Bun.hash.adler32("data", 1234); Bun.hash.cityHash32("data", 1234); Bun.hash.cityHash64("data", 1234); Bun.hash.murmur32v3("data", 1234); +Bun.hash.murmur32v2("data", 1234); Bun.hash.murmur64v2("data", 1234); ``` diff --git a/examples/hashing.js b/examples/hashing.js index cf4772ffe..3f23d1312 100644 --- a/examples/hashing.js +++ b/examples/hashing.js @@ -1,18 +1,19 @@ -// Accepts a string, TypedArray, or Blob (file blob supported is not implemented but planned) +// Accepts a string, TypedArray, or Blob (file blob support is not implemented but planned) const input = "hello world".repeat(400); // Bun.hash() defaults to Wyhash because it's fast console.log(Bun.hash(input)); console.log(Bun.hash.wyhash(input)); -// and returns a number -// all of these hashing functions return numbers, not typed arrays. -console.log(Bun.hash.adler32(input)); -console.log(Bun.hash.crc32(input)); -console.log(Bun.hash.cityHash32(input)); -console.log(Bun.hash.cityHash64(input)); -console.log(Bun.hash.murmur32v3(input)); -console.log(Bun.hash.murmur64v2(input)); +// and returns a bigint +// all of these hashing functions return number if 32-bit or bigint if 64-bit, not typed arrays. +console.log(Bun.hash.adler32(input)); // number +console.log(Bun.hash.crc32(input)); // number +console.log(Bun.hash.cityHash32(input)); // number +console.log(Bun.hash.cityHash64(input)); // bigint +console.log(Bun.hash.murmur32v3(input)); // number +console.log(Bun.hash.murmur32v2(input)); // number +console.log(Bun.hash.murmur64v2(input)); // bigint // Second argument accepts a seed where relevant console.log(Bun.hash(input, 12345)); diff --git a/src/bun.js/api/bun.zig b/src/bun.js/api/bun.zig index 5210063ea..fe0aafc25 100644 --- a/src/bun.js/api/bun.zig +++ b/src/bun.js/api/bun.zig @@ -3192,24 +3192,24 @@ pub const Hash = struct { } else { var seed: u64 = 0; if (args.nextEat()) |arg| { - if (arg.isNumber()) { - seed = arg.toU32(); + if (arg.isNumber() or arg.isBigInt()) { + seed = arg.toUInt64NoTruncate(); } } if (comptime std.meta.trait.isNumber(@TypeOf(function_args[0]))) { - function_args[0] = @as(@TypeOf(function_args[0]), @intCast(seed)); + function_args[0] = @as(@TypeOf(function_args[0]), @truncate(seed)); function_args[1] = input; } else { - function_args[1] = @as(@TypeOf(function_args[1]), @intCast(seed)); function_args[0] = input; + function_args[1] = @as(@TypeOf(function_args[1]), @truncate(seed)); } const value = @call(.auto, Function, function_args); if (@TypeOf(value) == u32) { - return JSC.JSValue.jsNumber(@as(i32, @bitCast(value))).asObjectRef(); + return JSC.JSValue.jsNumber(@as(u32, @bitCast(value))).asObjectRef(); } - return JSC.JSValue.jsNumber(value).asObjectRef(); + return JSC.JSValue.fromUInt64NoTruncate(ctx.ptr(), value).asObjectRef(); } } }; diff --git a/test/js/bun/util/hash.test.js b/test/js/bun/util/hash.test.js index 87a5a9ce3..29c683801 100644 --- a/test/js/bun/util/hash.test.js +++ b/test/js/bun/util/hash.test.js @@ -1,47 +1,50 @@ -import fs from "fs"; import { it, expect } from "bun:test"; -import path from "path"; import { gcTick } from "harness"; it(`Bun.hash()`, () => { gcTick(); - Bun.hash("hello world"); - Bun.hash(new TextEncoder().encode("hello world")); + expect(Bun.hash("hello world")).toBe(0x668d5e431c3b2573n); + expect(Bun.hash(new TextEncoder().encode("hello world"))).toBe(0x668d5e431c3b2573n); }); it(`Bun.hash.wyhash()`, () => { - Bun.hash.wyhash("hello world"); + expect(Bun.hash.wyhash("hello world")).toBe(0x668d5e431c3b2573n); gcTick(); - Bun.hash.wyhash(new TextEncoder().encode("hello world")); + expect(Bun.hash.wyhash(new TextEncoder().encode("hello world"))).toBe(0x668d5e431c3b2573n); }); it(`Bun.hash.adler32()`, () => { - Bun.hash.adler32("hello world"); + expect(Bun.hash.adler32("hello world")).toBe(0x1a0b045d); gcTick(); - Bun.hash.adler32(new TextEncoder().encode("hello world")); + expect(Bun.hash.adler32(new TextEncoder().encode("hello world"))).toBe(0x1a0b045d); }); it(`Bun.hash.crc32()`, () => { - Bun.hash.crc32("hello world"); + expect(Bun.hash.crc32("hello world")).toBe(0x0d4a1185); gcTick(); - Bun.hash.crc32(new TextEncoder().encode("hello world")); + expect(Bun.hash.crc32(new TextEncoder().encode("hello world"))).toBe(0x0d4a1185); }); it(`Bun.hash.cityHash32()`, () => { - Bun.hash.cityHash32("hello world"); + expect(Bun.hash.cityHash32("hello world")).toBe(0x19a7581a); gcTick(); - Bun.hash.cityHash32(new TextEncoder().encode("hello world")); + expect(Bun.hash.cityHash32(new TextEncoder().encode("hello world"))).toBe(0x19a7581a); gcTick(); }); it(`Bun.hash.cityHash64()`, () => { - Bun.hash.cityHash64("hello world"); + expect(Bun.hash.cityHash64("hello world")).toBe(0xc7920bbdbecee42fn); gcTick(); - Bun.hash.cityHash64(new TextEncoder().encode("hello world")); + expect(Bun.hash.cityHash64(new TextEncoder().encode("hello world"))).toBe(0xc7920bbdbecee42fn); gcTick(); }); it(`Bun.hash.murmur32v3()`, () => { - Bun.hash.murmur32v3("hello world"); + expect(Bun.hash.murmur32v3("hello world")).toBe(0x5e928f0f); gcTick(); - Bun.hash.murmur32v3(new TextEncoder().encode("hello world")); + expect(Bun.hash.murmur32v3(new TextEncoder().encode("hello world"))).toBe(0x5e928f0f); +}); +it(`Bun.hash.murmur32v2()`, () => { + expect(Bun.hash.murmur32v2("hello world")).toBe(0x44a81419); + gcTick(); + expect(Bun.hash.murmur32v2(new TextEncoder().encode("hello world"))).toBe(0x44a81419); }); it(`Bun.hash.murmur64v2()`, () => { - Bun.hash.murmur64v2("hello world"); + expect(Bun.hash.murmur64v2("hello world")).toBe(0xd3ba2368a832afcen); gcTick(); - Bun.hash.murmur64v2(new TextEncoder().encode("hello world")); + expect(Bun.hash.murmur64v2(new TextEncoder().encode("hello world"))).toBe(0xd3ba2368a832afcen); }); |