/
equals.ts
89 lines (85 loc) · 2.4 KB
/
equals.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.
/**
* Check whether byte slices are equal to each other using 8-bit comparisons.
*
* @param a First array to check equality
* @param b Second array to check equality
* @returns `true` if the arrays are equal, `false` otherwise
*
* @private
*/
function equalsNaive(a: Uint8Array, b: Uint8Array): boolean {
for (let i = 0; i < b.length; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
/** Check whether byte slices are equal to each other using 32-bit comparisons.
*
* @param a First array to check equality.
* @param b Second array to check equality.
* @returns `true` if the arrays are equal, `false` otherwise.
*
* @private
*/
function equals32Bit(a: Uint8Array, b: Uint8Array): boolean {
const len = a.length;
const compactOffset = 3 - ((a.byteOffset + 3) % 4);
const compactLen = Math.floor((len - compactOffset) / 4);
const compactA = new Uint32Array(
a.buffer,
a.byteOffset + compactOffset,
compactLen,
);
const compactB = new Uint32Array(
b.buffer,
b.byteOffset + compactOffset,
compactLen,
);
for (let i = 0; i < compactOffset; i++) {
if (a[i] !== b[i]) return false;
}
for (let i = 0; i < compactA.length; i++) {
if (compactA[i] !== compactB[i]) return false;
}
for (let i = compactOffset + compactLen * 4; i < len; i++) {
if (a[i] !== b[i]) return false;
}
return true;
}
/**
* Byte length threshold for when to use 32-bit comparisons, based on
* benchmarks.
*
* @see {@link https://github.com/denoland/deno_std/pull/4635}
*/
const THRESHOLD_32_BIT = 160;
/**
* Check whether byte slices are equal to each other.
*
* @param a First array to check equality.
* @param b Second array to check equality.
* @returns `true` if the arrays are equal, `false` otherwise.
*
* @example Basic usage
* ```ts
* import { equals } from "https://deno.land/std@$STD_VERSION/bytes/equals.ts";
*
* const a = new Uint8Array([1, 2, 3]);
* const b = new Uint8Array([1, 2, 3]);
* const c = new Uint8Array([4, 5, 6]);
*
* equals(a, b); // true
* equals(b, c); // false
* ```
*/
export function equals(a: Uint8Array, b: Uint8Array): boolean {
if (a.length !== b.length) {
return false;
}
return a.length >= THRESHOLD_32_BIT &&
(a.byteOffset % 4) === (b.byteOffset % 4)
? equals32Bit(a, b)
: equalsNaive(a, b);
}