All files / encoding / _common16.ts

100.00% Branches 14/14
100.00% Functions 4/4
100.00% Lines 49/49
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
 
 
 
 
 
x36
x36
x36
x36
x36
x36
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
x36
x1789
x1789
 
x36
x36
x36
x36
x36
 
x1780
x110204
x110204
x110204
x110204
x1780
x1780
 
x36
x36
x36
x36
x36
 
x47
x7
x7
x7
x7
 
x7
 
x40
x44
x8043
x8043
x8043
x32
x47
 
x16081
x16081
x16081
x8
x8
x8
x8
 
x8
x16073
x16081












































































// Copyright 2018-2026 the Deno authors. MIT license.

import type { Uint8Array_ } from "./_types.ts";
export type { Uint8Array_ };

export const alphabet = new TextEncoder().encode("0123456789abcdef");
export const rAlphabet = new Uint8Array(128).fill(16); // alphabet.Hex.length
alphabet.forEach((byte, i) => rAlphabet[byte] = i);
new TextEncoder()
  .encode("ABCDEF")
  .forEach((byte, i) => rAlphabet[byte] = i + 10);

/**
 * Calculate the output size needed to encode a given input size for
 * {@linkcode encodeIntoHex}.
 *
 * @param originalSize The size of the input buffer.
 * @returns The size of the output buffer.
 *
 * @example Basic Usage
 * ```ts
 * import { assertEquals } from "@std/assert";
 * import { calcSizeHex } from "@std/encoding/unstable-hex";
 *
 * assertEquals(calcSizeHex(1), 2);
 * ```
 */
export function calcSizeHex(originalSize: number): number {
  return originalSize * 2;
}

export function encode(
  buffer: Uint8Array_,
  i: number,
  o: number,
  alphabet: Uint8Array,
): number {
  for (; i < buffer.length; ++i) {
    const x = buffer[i]!;
    buffer[o++] = alphabet[x >> 4]!;
    buffer[o++] = alphabet[x & 0xF]!;
  }
  return o;
}

export function decode(
  buffer: Uint8Array_,
  i: number,
  o: number,
  alphabet: Uint8Array,
): number {
  if ((buffer.length - o) % 2 === 1) {
    throw new RangeError(
      `Cannot decode input as hex: Length (${
        buffer.length - o
      }) must be divisible by 2`,
    );
  }

  i += 1;
  for (; i < buffer.length; i += 2) {
    buffer[o++] = (getByte(buffer[i - 1]!, alphabet) << 4) |
      getByte(buffer[i]!, alphabet);
  }
  return o;
}

function getByte(char: number, alphabet: Uint8Array): number {
  const byte = alphabet[char] ?? 16;
  if (byte === 16) { // alphabet.Hex.length
    throw new TypeError(
      `Cannot decode input as hex: Invalid character (${
        String.fromCharCode(char)
      })`,
    );
  }
  return byte;
}