All files / bytes / equals.ts

100.00% Branches 31/31
100.00% Functions 3/3
100.00% Lines 39/39
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
90
 
 
 
 
 
 
 
 
 
 
 
 
x51
x15550
x1888545
x1888545
x7775
x15550
 
 
 
 
 
 
 
 
 
x51
x5212
x5212
x5212
x5212
x5212
x5212
x5212
 
x5212
x5212
x5212
x5212
 
x5212
x7736
x7736
x5212
x156223
x156223
x5212
x3961
x3961
x2606
x5212
 
 
 
 
 
 
 
x51
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x51
x20764
x2
x2
x20764
x20764
x20764
x20764
x20764
























































































// Copyright 2018-2026 the Deno authors. 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/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 "@std/bytes/equals";
 * import { assertEquals } from "@std/assert";
 *
 * const a = new Uint8Array([1, 2, 3]);
 * const b = new Uint8Array([1, 2, 3]);
 * const c = new Uint8Array([4, 5, 6]);
 *
 * assertEquals(equals(a, b), true);
 * assertEquals(equals(a, 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);
}