All files / yaml / _type / binary.ts

100.00% Branches 22/22
100.00% Lines 87/87
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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
 
 
 
 
 
 
 
x18
x18
 
x26
x26
 
x33
x33
x33
x33
 
 
x26
x95
 
 
x95
 
 
x95
 
x159
x159
 
 
x32
x26
 
x24
 
x24
x24
x24
 
 
 
x24
x24
x24
x82
x92
x92
x92
x92
 
x82
x82
 
 
 
x24
 
x24
x25
x25
x25
x24
x33
x33
x29
x30
x30
 
x24
x24
 
x25
x25
x25
 
 
 
x25
x25
x25
x86
x103
x103
x103
x103
x103
 
x86
x86
 
 
 
x25
 
x25
x28
x28
x28
x28
x25
x32
x32
x32
x32
x29
x30
x30
x30
x30
x30
 
x25
x25
x319
x319
x319
 
x18
x18
x18
x18
x18
x18
x18
x18





























































































































// Ported from js-yaml v3.13.1:
// Copyright 2011-2015 by Vitaly Puzrin. All rights reserved. MIT license.
// https://github.com/nodeca/js-yaml/commit/665aadda42349dcae869f12040d9b10ef18d12da
// Copyright 2018-2025 the Deno authors. MIT license.
import type { Type } from "../_type.ts";

// [ 64, 65, 66 ] -> [ padding, CR, LF ]
const BASE64_MAP =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";

function resolveYamlBinary(data: string): boolean {
  if (data === null) return false;

  let code: number;
  let bitlen = 0;
  const max = data.length;
  const map = BASE64_MAP;

  // Convert one by one.
  for (let idx = 0; idx < max; idx++) {
    code = map.indexOf(data.charAt(idx));

    // Skip CR/LF
    if (code > 64) continue;

    // Fail on illegal characters
    if (code < 0) return false;

    bitlen += 6;
  }

  // If there are any bits left, source was corrupted
  return bitlen % 8 === 0;
}

function constructYamlBinary(data: string): Uint8Array {
  // remove CR/LF & padding to simplify scan
  const input = data.replace(/[\r\n=]/g, "");
  const max = input.length;
  const map = BASE64_MAP;

  // Collect by 6*4 bits (3 bytes)

  const result = [];
  let bits = 0;
  for (let idx = 0; idx < max; idx++) {
    if (idx % 4 === 0 && idx) {
      result.push((bits >> 16) & 0xff);
      result.push((bits >> 8) & 0xff);
      result.push(bits & 0xff);
    }

    bits = (bits << 6) | map.indexOf(input.charAt(idx));
  }

  // Dump tail

  const tailbits = (max % 4) * 6;

  if (tailbits === 0) {
    result.push((bits >> 16) & 0xff);
    result.push((bits >> 8) & 0xff);
    result.push(bits & 0xff);
  } else if (tailbits === 18) {
    result.push((bits >> 10) & 0xff);
    result.push((bits >> 2) & 0xff);
  } else if (tailbits === 12) {
    result.push((bits >> 4) & 0xff);
  }

  return new Uint8Array(result);
}

function representYamlBinary(object: Uint8Array): string {
  const max = object.length;
  const map = BASE64_MAP;

  // Convert every three bytes to 4 ASCII characters.

  let result = "";
  let bits = 0;
  for (let idx = 0; idx < max; idx++) {
    if (idx % 3 === 0 && idx) {
      result += map[(bits >> 18) & 0x3f];
      result += map[(bits >> 12) & 0x3f];
      result += map[(bits >> 6) & 0x3f];
      result += map[bits & 0x3f];
    }

    bits = (bits << 8) + object[idx]!;
  }

  // Dump tail

  const tail = max % 3;

  if (tail === 0) {
    result += map[(bits >> 18) & 0x3f];
    result += map[(bits >> 12) & 0x3f];
    result += map[(bits >> 6) & 0x3f];
    result += map[bits & 0x3f];
  } else if (tail === 2) {
    result += map[(bits >> 10) & 0x3f];
    result += map[(bits >> 4) & 0x3f];
    result += map[(bits << 2) & 0x3f];
    result += map[64];
  } else if (tail === 1) {
    result += map[(bits >> 2) & 0x3f];
    result += map[(bits << 4) & 0x3f];
    result += map[64];
    result += map[64];
  }

  return result;
}
function isBinary(obj: unknown): obj is Uint8Array {
  return obj instanceof Uint8Array;
}

export const binary: Type<"scalar", Uint8Array> = {
  tag: "tag:yaml.org,2002:binary",
  construct: constructYamlBinary,
  kind: "scalar",
  predicate: isBinary,
  represent: representYamlBinary,
  resolve: resolveYamlBinary,
};