@yume-chan/adb 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.json +23 -0
- package/CHANGELOG.md +16 -0
- package/LICENSE +21 -21
- package/README.md +227 -257
- package/dts/adb.d.ts.map +1 -1
- package/dts/auth.d.ts +11 -1
- package/dts/auth.d.ts.map +1 -1
- package/dts/backend.d.ts +3 -5
- package/dts/backend.d.ts.map +1 -1
- package/dts/commands/demo-mode.d.ts +3 -3
- package/dts/commands/demo-mode.d.ts.map +1 -1
- package/dts/commands/reverse.d.ts +2 -2
- package/dts/commands/reverse.d.ts.map +1 -1
- package/dts/commands/shell/index.d.ts +31 -5
- package/dts/commands/shell/index.d.ts.map +1 -1
- package/dts/commands/shell/legacy.d.ts +13 -2
- package/dts/commands/shell/legacy.d.ts.map +1 -1
- package/dts/commands/shell/protocol.d.ts +11 -3
- package/dts/commands/shell/protocol.d.ts.map +1 -1
- package/dts/commands/shell/types.d.ts +35 -3
- package/dts/commands/shell/types.d.ts.map +1 -1
- package/dts/commands/sync/request.d.ts +1 -1
- package/dts/commands/sync/request.d.ts.map +1 -1
- package/dts/commands/sync/response.d.ts +2 -2
- package/dts/commands/sync/response.d.ts.map +1 -1
- package/dts/commands/sync/sync.d.ts.map +1 -1
- package/dts/crypto.d.ts +7 -0
- package/dts/crypto.d.ts.map +1 -1
- package/dts/packet.d.ts.map +1 -1
- package/dts/socket/close-event-emitter.d.ts.map +1 -1
- package/dts/socket/controller.d.ts.map +1 -1
- package/dts/socket/data-event-emitter.d.ts.map +1 -1
- package/dts/socket/dispatcher.d.ts.map +1 -1
- package/dts/stream/buffered-stream.d.ts +2 -4
- package/dts/stream/buffered-stream.d.ts.map +1 -1
- package/dts/utils/encoding.d.ts +3 -0
- package/dts/utils/encoding.d.ts.map +1 -0
- package/dts/utils/index.d.ts +1 -0
- package/dts/utils/index.d.ts.map +1 -1
- package/esm/adb.js +3 -2
- package/esm/adb.js.map +1 -1
- package/esm/auth.js +2 -2
- package/esm/auth.js.map +1 -1
- package/esm/commands/demo-mode.js +9 -9
- package/esm/commands/demo-mode.js.map +1 -1
- package/esm/commands/reverse.js +3 -2
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/shell/index.js +28 -18
- package/esm/commands/shell/index.js.map +1 -1
- package/esm/commands/shell/legacy.js +16 -0
- package/esm/commands/shell/legacy.js.map +1 -1
- package/esm/commands/shell/protocol.js +36 -9
- package/esm/commands/shell/protocol.js.map +1 -1
- package/esm/commands/sync/request.js +5 -4
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.js +4 -3
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/crypto.js +7 -2
- package/esm/crypto.js.map +1 -1
- package/esm/packet.js +12 -14
- package/esm/packet.js.map +1 -1
- package/esm/socket/close-event-emitter.js.map +1 -1
- package/esm/socket/controller.js.map +1 -1
- package/esm/socket/data-event-emitter.js.map +1 -1
- package/esm/socket/dispatcher.js +7 -7
- package/esm/socket/dispatcher.js.map +1 -1
- package/esm/stream/buffered-stream.js +0 -6
- package/esm/stream/buffered-stream.js.map +1 -1
- package/esm/utils/encoding.js +11 -0
- package/esm/utils/encoding.js.map +1 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/index.js.map +1 -1
- package/package.json +44 -51
- package/src/adb.ts +243 -242
- package/src/auth.ts +166 -156
- package/src/backend.ts +20 -24
- package/src/commands/base.ts +11 -11
- package/src/commands/demo-mode.ts +160 -160
- package/src/commands/framebuffer.ts +73 -73
- package/src/commands/index.ts +8 -8
- package/src/commands/install.ts +21 -21
- package/src/commands/reverse.ts +134 -133
- package/src/commands/shell/index.ts +87 -68
- package/src/commands/shell/legacy.ts +59 -42
- package/src/commands/shell/protocol.ts +121 -94
- package/src/commands/shell/types.ts +55 -21
- package/src/commands/shell/utils.ts +20 -20
- package/src/commands/sync/index.ts +7 -7
- package/src/commands/sync/list.ts +39 -39
- package/src/commands/sync/pull.ts +34 -34
- package/src/commands/sync/push.ts +46 -46
- package/src/commands/sync/request.ts +49 -48
- package/src/commands/sync/response.ts +58 -57
- package/src/commands/sync/stat.ts +121 -121
- package/src/commands/sync/sync.ts +113 -113
- package/src/commands/tcpip.ts +21 -21
- package/src/crypto.ts +285 -280
- package/src/features.ts +5 -5
- package/src/index.ts +10 -10
- package/src/packet.ts +84 -89
- package/src/socket/close-event-emitter.ts +28 -28
- package/src/socket/controller.ts +105 -105
- package/src/socket/data-event-emitter.ts +27 -27
- package/src/socket/dispatcher.ts +269 -269
- package/src/socket/index.ts +6 -6
- package/src/socket/logger.ts +12 -12
- package/src/socket/socket.ts +28 -28
- package/src/stream/buffered-stream.ts +92 -100
- package/src/stream/index.ts +2 -2
- package/src/stream/stream.ts +50 -50
- package/src/utils/auto-reset-event.ts +41 -41
- package/src/utils/base64.ts +274 -274
- package/src/utils/chunk.ts +70 -70
- package/src/utils/encoding.ts +13 -0
- package/src/utils/event-queue.ts +145 -145
- package/src/utils/index.ts +5 -4
- package/cjs/adb.js +0 -205
- package/cjs/adb.js.map +0 -1
- package/cjs/auth.js +0 -141
- package/cjs/auth.js.map +0 -1
- package/cjs/backend.js +0 -3
- package/cjs/backend.js.map +0 -1
- package/cjs/commands/base.js +0 -12
- package/cjs/commands/base.js.map +0 -1
- package/cjs/commands/demo-mode.js +0 -174
- package/cjs/commands/demo-mode.js.map +0 -1
- package/cjs/commands/framebuffer.js +0 -66
- package/cjs/commands/framebuffer.js.map +0 -1
- package/cjs/commands/index.js +0 -12
- package/cjs/commands/index.js.map +0 -1
- package/cjs/commands/install.js +0 -20
- package/cjs/commands/install.js.map +0 -1
- package/cjs/commands/reverse.js +0 -105
- package/cjs/commands/reverse.js.map +0 -1
- package/cjs/commands/shell/index.js +0 -56
- package/cjs/commands/shell/index.js.map +0 -1
- package/cjs/commands/shell/legacy.js +0 -37
- package/cjs/commands/shell/legacy.js.map +0 -1
- package/cjs/commands/shell/protocol.js +0 -83
- package/cjs/commands/shell/protocol.js.map +0 -1
- package/cjs/commands/shell/types.js +0 -3
- package/cjs/commands/shell/types.js.map +0 -1
- package/cjs/commands/shell/utils.js +0 -23
- package/cjs/commands/shell/utils.js.map +0 -1
- package/cjs/commands/sync/index.js +0 -11
- package/cjs/commands/sync/index.js.map +0 -1
- package/cjs/commands/sync/list.js +0 -36
- package/cjs/commands/sync/list.js.map +0 -1
- package/cjs/commands/sync/pull.js +0 -34
- package/cjs/commands/sync/pull.js.map +0 -1
- package/cjs/commands/sync/push.js +0 -49
- package/cjs/commands/sync/push.js.map +0 -1
- package/cjs/commands/sync/request.js +0 -48
- package/cjs/commands/sync/request.js.map +0 -1
- package/cjs/commands/sync/response.js +0 -53
- package/cjs/commands/sync/response.js.map +0 -1
- package/cjs/commands/sync/stat.js +0 -109
- package/cjs/commands/sync/stat.js.map +0 -1
- package/cjs/commands/sync/sync.js +0 -118
- package/cjs/commands/sync/sync.js.map +0 -1
- package/cjs/commands/tcpip.js +0 -28
- package/cjs/commands/tcpip.js.map +0 -1
- package/cjs/crypto.js +0 -231
- package/cjs/crypto.js.map +0 -1
- package/cjs/features.js +0 -10
- package/cjs/features.js.map +0 -1
- package/cjs/index.js +0 -14
- package/cjs/index.js.map +0 -1
- package/cjs/packet.js +0 -77
- package/cjs/packet.js.map +0 -1
- package/cjs/socket/close-event-emitter.js +0 -32
- package/cjs/socket/close-event-emitter.js.map +0 -1
- package/cjs/socket/controller.js +0 -84
- package/cjs/socket/controller.js.map +0 -1
- package/cjs/socket/data-event-emitter.js +0 -29
- package/cjs/socket/data-event-emitter.js.map +0 -1
- package/cjs/socket/dispatcher.js +0 -219
- package/cjs/socket/dispatcher.js.map +0 -1
- package/cjs/socket/index.js +0 -10
- package/cjs/socket/index.js.map +0 -1
- package/cjs/socket/logger.js +0 -3
- package/cjs/socket/logger.js.map +0 -1
- package/cjs/socket/socket.js +0 -24
- package/cjs/socket/socket.js.map +0 -1
- package/cjs/stream/buffered-stream.js +0 -78
- package/cjs/stream/buffered-stream.js.map +0 -1
- package/cjs/stream/index.js +0 -6
- package/cjs/stream/index.js.map +0 -1
- package/cjs/stream/stream.js +0 -45
- package/cjs/stream/stream.js.map +0 -1
- package/cjs/utils/auto-reset-event.js +0 -37
- package/cjs/utils/auto-reset-event.js.map +0 -1
- package/cjs/utils/base64.js +0 -210
- package/cjs/utils/base64.js.map +0 -1
- package/cjs/utils/chunk.js +0 -75
- package/cjs/utils/chunk.js.map +0 -1
- package/cjs/utils/event-queue.js +0 -108
- package/cjs/utils/event-queue.js.map +0 -1
- package/cjs/utils/index.js +0 -8
- package/cjs/utils/index.js.map +0 -1
- package/tsconfig.cjs.json +0 -11
- package/tsconfig.esm.json +0 -28
- package/tsconfig.esm.tsbuildinfo +0 -1305
- package/tsconfig.json +0 -18
package/src/utils/base64.ts
CHANGED
|
@@ -1,274 +1,274 @@
|
|
|
1
|
-
// Prepare maps for O(1) searching
|
|
2
|
-
const charToIndex: Record<string, number> = {};
|
|
3
|
-
const indexToChar: number[] = [];
|
|
4
|
-
const paddingChar = '='.charCodeAt(0);
|
|
5
|
-
|
|
6
|
-
function addRange(start: string, end: string) {
|
|
7
|
-
const charCodeStart = start.charCodeAt(0);
|
|
8
|
-
const charCodeEnd = end.charCodeAt(0);
|
|
9
|
-
const length = charCodeEnd - charCodeStart + 1;
|
|
10
|
-
|
|
11
|
-
for (let charCode = charCodeStart; charCode <= charCodeEnd; charCode += 1) {
|
|
12
|
-
charToIndex[String.fromCharCode(charCode)] = indexToChar.length;
|
|
13
|
-
indexToChar.push(charCode);
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
addRange('A', 'Z');
|
|
18
|
-
addRange('a', 'z');
|
|
19
|
-
addRange('0', '9');
|
|
20
|
-
addRange('+', '+');
|
|
21
|
-
addRange('/', '/');
|
|
22
|
-
|
|
23
|
-
export function calculateBase64EncodedLength(inputLength: number): [outputLength: number, paddingLength: number] {
|
|
24
|
-
const remainder = inputLength % 3;
|
|
25
|
-
const paddingLength = remainder !== 0 ? 3 - remainder : 0;
|
|
26
|
-
return [(inputLength + paddingLength) / 3 * 4, paddingLength];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function encodeBase64(
|
|
30
|
-
input: ArrayBuffer | Uint8Array,
|
|
31
|
-
inputOffset?: number,
|
|
32
|
-
inputLength?: number,
|
|
33
|
-
): ArrayBuffer; // overload 1
|
|
34
|
-
export function encodeBase64(
|
|
35
|
-
input: ArrayBuffer | Uint8Array,
|
|
36
|
-
output: ArrayBuffer | Uint8Array,
|
|
37
|
-
outputOffset?: number
|
|
38
|
-
): number; // overload 2
|
|
39
|
-
export function encodeBase64(
|
|
40
|
-
input: ArrayBuffer | Uint8Array,
|
|
41
|
-
inputOffset: number,
|
|
42
|
-
output: ArrayBuffer | Uint8Array,
|
|
43
|
-
outputOffset?: number
|
|
44
|
-
): number; // overload 3
|
|
45
|
-
export function encodeBase64(
|
|
46
|
-
input: ArrayBuffer | Uint8Array,
|
|
47
|
-
inputOffset: number,
|
|
48
|
-
inputLength: number,
|
|
49
|
-
output: ArrayBuffer | Uint8Array,
|
|
50
|
-
outputOffset?: number
|
|
51
|
-
): number; // overload 4
|
|
52
|
-
export function encodeBase64(
|
|
53
|
-
input: ArrayBuffer | Uint8Array,
|
|
54
|
-
arg1?: number | ArrayBuffer | Uint8Array,
|
|
55
|
-
arg2?: number | ArrayBuffer | Uint8Array,
|
|
56
|
-
_arg3?: number | ArrayBuffer | Uint8Array,
|
|
57
|
-
_arg4?: number,
|
|
58
|
-
): ArrayBuffer | number {
|
|
59
|
-
if (input instanceof ArrayBuffer) {
|
|
60
|
-
input = new Uint8Array(input);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Because `Uint8Array` is type compatible with `ArrayBuffer`,
|
|
64
|
-
// TypeScript doesn't correctly narrow `input` to `Uint8Array` when assigning.
|
|
65
|
-
// Manually eliminate `ArrayBuffer` from `input` with a type guard.
|
|
66
|
-
if (input instanceof ArrayBuffer) {
|
|
67
|
-
return input;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
let inputOffset: number;
|
|
71
|
-
let inputLength: number;
|
|
72
|
-
let output: Uint8Array;
|
|
73
|
-
let outputOffset: number;
|
|
74
|
-
|
|
75
|
-
let outputArgumentIndex: number;
|
|
76
|
-
if (typeof arg1 === 'number') {
|
|
77
|
-
// overload 1, 3, 4
|
|
78
|
-
inputOffset = arg1;
|
|
79
|
-
|
|
80
|
-
if (typeof arg2 === 'number') {
|
|
81
|
-
// overload 1, 4
|
|
82
|
-
inputLength = arg2;
|
|
83
|
-
outputArgumentIndex = 3;
|
|
84
|
-
} else {
|
|
85
|
-
// overload 3
|
|
86
|
-
inputLength = input.byteLength - inputOffset;
|
|
87
|
-
outputArgumentIndex = 2;
|
|
88
|
-
}
|
|
89
|
-
} else {
|
|
90
|
-
// overload 2
|
|
91
|
-
inputOffset = 0;
|
|
92
|
-
inputLength = input.byteLength;
|
|
93
|
-
outputArgumentIndex = 1;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const [outputLength, paddingLength] = calculateBase64EncodedLength(inputLength);
|
|
97
|
-
|
|
98
|
-
let maybeOutput: ArrayBuffer | Uint8Array | undefined = arguments[outputArgumentIndex];
|
|
99
|
-
let outputType: 'ArrayBuffer' | 'number';
|
|
100
|
-
if (maybeOutput) {
|
|
101
|
-
outputOffset = arguments[outputArgumentIndex + 1] ?? 0;
|
|
102
|
-
|
|
103
|
-
if (maybeOutput.byteLength - outputOffset < outputLength) {
|
|
104
|
-
throw new Error('output buffer is too small');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (maybeOutput instanceof ArrayBuffer) {
|
|
108
|
-
output = new Uint8Array(maybeOutput);
|
|
109
|
-
} else {
|
|
110
|
-
output = maybeOutput;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
outputType = 'number';
|
|
114
|
-
} else {
|
|
115
|
-
const buffer = new ArrayBuffer(outputLength);
|
|
116
|
-
output = new Uint8Array(buffer);
|
|
117
|
-
outputOffset = 0;
|
|
118
|
-
outputType = 'ArrayBuffer';
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Because `Uint8Array` is type compatible with `ArrayBuffer`,
|
|
122
|
-
// TypeScript doesn't correctly narrow `output` to `Uint8Array` when assigning.
|
|
123
|
-
// Manually eliminate `ArrayBuffer` from `output` with a type guard.
|
|
124
|
-
if (output instanceof ArrayBuffer) {
|
|
125
|
-
return output;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
if (input.buffer === output.buffer) {
|
|
129
|
-
const bufferInputStart = input.byteOffset + inputOffset;
|
|
130
|
-
const bufferOutputStart = output.byteOffset + outputOffset;
|
|
131
|
-
if (bufferOutputStart < bufferInputStart - 1) {
|
|
132
|
-
const bufferOutputEnd = bufferOutputStart + outputLength;
|
|
133
|
-
if (bufferOutputEnd >= bufferInputStart) {
|
|
134
|
-
throw new Error('input and output buffer can not be overlapping');
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Run backward to do in-place overwrite
|
|
140
|
-
let inputIndex = inputOffset + inputLength - 1;
|
|
141
|
-
let outputIndex = outputOffset + outputLength - 1;
|
|
142
|
-
|
|
143
|
-
if (paddingLength === 2) {
|
|
144
|
-
// aaaaaabb
|
|
145
|
-
const x = input[inputIndex];
|
|
146
|
-
inputIndex -= 1;
|
|
147
|
-
|
|
148
|
-
output[outputIndex] = paddingChar;
|
|
149
|
-
outputIndex -= 1;
|
|
150
|
-
|
|
151
|
-
output[outputIndex] = paddingChar;
|
|
152
|
-
outputIndex -= 1;
|
|
153
|
-
|
|
154
|
-
output[outputIndex] = indexToChar[((x & 0b11) << 4)];
|
|
155
|
-
outputIndex -= 1;
|
|
156
|
-
|
|
157
|
-
output[outputIndex] = indexToChar[x >> 2];
|
|
158
|
-
outputIndex -= 1;
|
|
159
|
-
} else if (paddingLength === 1) {
|
|
160
|
-
// bbbbcccc
|
|
161
|
-
const y = input[inputIndex];
|
|
162
|
-
inputIndex -= 1;
|
|
163
|
-
|
|
164
|
-
// aaaaaabb
|
|
165
|
-
const x = input[inputIndex];
|
|
166
|
-
inputIndex -= 1;
|
|
167
|
-
|
|
168
|
-
output[outputIndex] = paddingChar;
|
|
169
|
-
outputIndex -= 1;
|
|
170
|
-
|
|
171
|
-
output[outputIndex] = indexToChar[((y & 0b1111) << 2)];
|
|
172
|
-
outputIndex -= 1;
|
|
173
|
-
|
|
174
|
-
output[outputIndex] = indexToChar[((x & 0b11) << 4) | (y >> 4)];
|
|
175
|
-
outputIndex -= 1;
|
|
176
|
-
|
|
177
|
-
output[outputIndex] = indexToChar[x >> 2];
|
|
178
|
-
outputIndex -= 1;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
while (inputIndex >= inputOffset) {
|
|
182
|
-
// ccdddddd
|
|
183
|
-
const z = input[inputIndex];
|
|
184
|
-
inputIndex -= 1;
|
|
185
|
-
|
|
186
|
-
// bbbbcccc
|
|
187
|
-
const y = input[inputIndex];
|
|
188
|
-
inputIndex -= 1;
|
|
189
|
-
|
|
190
|
-
// aaaaaabb
|
|
191
|
-
const x = input[inputIndex];
|
|
192
|
-
inputIndex -= 1;
|
|
193
|
-
|
|
194
|
-
output[outputIndex] = indexToChar[z & 0b111111];
|
|
195
|
-
outputIndex -= 1;
|
|
196
|
-
|
|
197
|
-
output[outputIndex] = indexToChar[((y & 0b1111) << 2) | (z >> 6)];
|
|
198
|
-
outputIndex -= 1;
|
|
199
|
-
|
|
200
|
-
output[outputIndex] = indexToChar[((x & 0b11) << 4) | (y >> 4)];
|
|
201
|
-
outputIndex -= 1;
|
|
202
|
-
|
|
203
|
-
output[outputIndex] = indexToChar[x >> 2];
|
|
204
|
-
outputIndex -= 1;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
if (outputType === 'ArrayBuffer') {
|
|
208
|
-
return output.buffer;
|
|
209
|
-
} else {
|
|
210
|
-
return outputLength;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
export function decodeBase64(input: string): ArrayBuffer {
|
|
215
|
-
let padding: number;
|
|
216
|
-
if (input[input.length - 2] === '=') {
|
|
217
|
-
padding = 2;
|
|
218
|
-
} else if (input[input.length - 1] === '=') {
|
|
219
|
-
padding = 1;
|
|
220
|
-
} else {
|
|
221
|
-
padding = 0;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
const result = new Uint8Array(input.length / 4 * 3 - padding);
|
|
225
|
-
let sIndex = 0;
|
|
226
|
-
let dIndex = 0;
|
|
227
|
-
|
|
228
|
-
while (sIndex < input.length - (padding !== 0 ? 4 : 0)) {
|
|
229
|
-
const a = charToIndex[input[sIndex]];
|
|
230
|
-
sIndex += 1;
|
|
231
|
-
|
|
232
|
-
const b = charToIndex[input[sIndex]];
|
|
233
|
-
sIndex += 1;
|
|
234
|
-
|
|
235
|
-
const c = charToIndex[input[sIndex]];
|
|
236
|
-
sIndex += 1;
|
|
237
|
-
|
|
238
|
-
const d = charToIndex[input[sIndex]];
|
|
239
|
-
sIndex += 1;
|
|
240
|
-
|
|
241
|
-
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
242
|
-
dIndex += 1;
|
|
243
|
-
|
|
244
|
-
result[dIndex] = ((b & 0b1111) << 4) | ((c & 0b11_1100) >> 2);
|
|
245
|
-
dIndex += 1;
|
|
246
|
-
|
|
247
|
-
result[dIndex] = ((c & 0b11) << 6) | d;
|
|
248
|
-
dIndex += 1;
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
if (padding === 1) {
|
|
252
|
-
const a = charToIndex[input[sIndex]];
|
|
253
|
-
sIndex += 1;
|
|
254
|
-
|
|
255
|
-
const b = charToIndex[input[sIndex]];
|
|
256
|
-
sIndex += 1;
|
|
257
|
-
|
|
258
|
-
const c = charToIndex[input[sIndex]];
|
|
259
|
-
|
|
260
|
-
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
261
|
-
dIndex += 1;
|
|
262
|
-
|
|
263
|
-
result[dIndex] = ((b & 0b1111) << 4) | ((c & 0b11_1100) >> 2);
|
|
264
|
-
} else if (padding === 2) {
|
|
265
|
-
const a = charToIndex[input[sIndex]];
|
|
266
|
-
sIndex += 1;
|
|
267
|
-
|
|
268
|
-
const b = charToIndex[input[sIndex]];
|
|
269
|
-
|
|
270
|
-
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
return result.buffer;
|
|
274
|
-
}
|
|
1
|
+
// Prepare maps for O(1) searching
|
|
2
|
+
const charToIndex: Record<string, number> = {};
|
|
3
|
+
const indexToChar: number[] = [];
|
|
4
|
+
const paddingChar = '='.charCodeAt(0);
|
|
5
|
+
|
|
6
|
+
function addRange(start: string, end: string) {
|
|
7
|
+
const charCodeStart = start.charCodeAt(0);
|
|
8
|
+
const charCodeEnd = end.charCodeAt(0);
|
|
9
|
+
const length = charCodeEnd - charCodeStart + 1;
|
|
10
|
+
|
|
11
|
+
for (let charCode = charCodeStart; charCode <= charCodeEnd; charCode += 1) {
|
|
12
|
+
charToIndex[String.fromCharCode(charCode)] = indexToChar.length;
|
|
13
|
+
indexToChar.push(charCode);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
addRange('A', 'Z');
|
|
18
|
+
addRange('a', 'z');
|
|
19
|
+
addRange('0', '9');
|
|
20
|
+
addRange('+', '+');
|
|
21
|
+
addRange('/', '/');
|
|
22
|
+
|
|
23
|
+
export function calculateBase64EncodedLength(inputLength: number): [outputLength: number, paddingLength: number] {
|
|
24
|
+
const remainder = inputLength % 3;
|
|
25
|
+
const paddingLength = remainder !== 0 ? 3 - remainder : 0;
|
|
26
|
+
return [(inputLength + paddingLength) / 3 * 4, paddingLength];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function encodeBase64(
|
|
30
|
+
input: ArrayBuffer | Uint8Array,
|
|
31
|
+
inputOffset?: number,
|
|
32
|
+
inputLength?: number,
|
|
33
|
+
): ArrayBuffer; // overload 1
|
|
34
|
+
export function encodeBase64(
|
|
35
|
+
input: ArrayBuffer | Uint8Array,
|
|
36
|
+
output: ArrayBuffer | Uint8Array,
|
|
37
|
+
outputOffset?: number
|
|
38
|
+
): number; // overload 2
|
|
39
|
+
export function encodeBase64(
|
|
40
|
+
input: ArrayBuffer | Uint8Array,
|
|
41
|
+
inputOffset: number,
|
|
42
|
+
output: ArrayBuffer | Uint8Array,
|
|
43
|
+
outputOffset?: number
|
|
44
|
+
): number; // overload 3
|
|
45
|
+
export function encodeBase64(
|
|
46
|
+
input: ArrayBuffer | Uint8Array,
|
|
47
|
+
inputOffset: number,
|
|
48
|
+
inputLength: number,
|
|
49
|
+
output: ArrayBuffer | Uint8Array,
|
|
50
|
+
outputOffset?: number
|
|
51
|
+
): number; // overload 4
|
|
52
|
+
export function encodeBase64(
|
|
53
|
+
input: ArrayBuffer | Uint8Array,
|
|
54
|
+
arg1?: number | ArrayBuffer | Uint8Array,
|
|
55
|
+
arg2?: number | ArrayBuffer | Uint8Array,
|
|
56
|
+
_arg3?: number | ArrayBuffer | Uint8Array,
|
|
57
|
+
_arg4?: number,
|
|
58
|
+
): ArrayBuffer | number {
|
|
59
|
+
if (input instanceof ArrayBuffer) {
|
|
60
|
+
input = new Uint8Array(input);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Because `Uint8Array` is type compatible with `ArrayBuffer`,
|
|
64
|
+
// TypeScript doesn't correctly narrow `input` to `Uint8Array` when assigning.
|
|
65
|
+
// Manually eliminate `ArrayBuffer` from `input` with a type guard.
|
|
66
|
+
if (input instanceof ArrayBuffer) {
|
|
67
|
+
return input;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let inputOffset: number;
|
|
71
|
+
let inputLength: number;
|
|
72
|
+
let output: Uint8Array;
|
|
73
|
+
let outputOffset: number;
|
|
74
|
+
|
|
75
|
+
let outputArgumentIndex: number;
|
|
76
|
+
if (typeof arg1 === 'number') {
|
|
77
|
+
// overload 1, 3, 4
|
|
78
|
+
inputOffset = arg1;
|
|
79
|
+
|
|
80
|
+
if (typeof arg2 === 'number') {
|
|
81
|
+
// overload 1, 4
|
|
82
|
+
inputLength = arg2;
|
|
83
|
+
outputArgumentIndex = 3;
|
|
84
|
+
} else {
|
|
85
|
+
// overload 3
|
|
86
|
+
inputLength = input.byteLength - inputOffset;
|
|
87
|
+
outputArgumentIndex = 2;
|
|
88
|
+
}
|
|
89
|
+
} else {
|
|
90
|
+
// overload 2
|
|
91
|
+
inputOffset = 0;
|
|
92
|
+
inputLength = input.byteLength;
|
|
93
|
+
outputArgumentIndex = 1;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const [outputLength, paddingLength] = calculateBase64EncodedLength(inputLength);
|
|
97
|
+
|
|
98
|
+
let maybeOutput: ArrayBuffer | Uint8Array | undefined = arguments[outputArgumentIndex];
|
|
99
|
+
let outputType: 'ArrayBuffer' | 'number';
|
|
100
|
+
if (maybeOutput) {
|
|
101
|
+
outputOffset = arguments[outputArgumentIndex + 1] ?? 0;
|
|
102
|
+
|
|
103
|
+
if (maybeOutput.byteLength - outputOffset < outputLength) {
|
|
104
|
+
throw new Error('output buffer is too small');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (maybeOutput instanceof ArrayBuffer) {
|
|
108
|
+
output = new Uint8Array(maybeOutput);
|
|
109
|
+
} else {
|
|
110
|
+
output = maybeOutput;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
outputType = 'number';
|
|
114
|
+
} else {
|
|
115
|
+
const buffer = new ArrayBuffer(outputLength);
|
|
116
|
+
output = new Uint8Array(buffer);
|
|
117
|
+
outputOffset = 0;
|
|
118
|
+
outputType = 'ArrayBuffer';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Because `Uint8Array` is type compatible with `ArrayBuffer`,
|
|
122
|
+
// TypeScript doesn't correctly narrow `output` to `Uint8Array` when assigning.
|
|
123
|
+
// Manually eliminate `ArrayBuffer` from `output` with a type guard.
|
|
124
|
+
if (output instanceof ArrayBuffer) {
|
|
125
|
+
return output;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (input.buffer === output.buffer) {
|
|
129
|
+
const bufferInputStart = input.byteOffset + inputOffset;
|
|
130
|
+
const bufferOutputStart = output.byteOffset + outputOffset;
|
|
131
|
+
if (bufferOutputStart < bufferInputStart - 1) {
|
|
132
|
+
const bufferOutputEnd = bufferOutputStart + outputLength;
|
|
133
|
+
if (bufferOutputEnd >= bufferInputStart) {
|
|
134
|
+
throw new Error('input and output buffer can not be overlapping');
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Run backward to do in-place overwrite
|
|
140
|
+
let inputIndex = inputOffset + inputLength - 1;
|
|
141
|
+
let outputIndex = outputOffset + outputLength - 1;
|
|
142
|
+
|
|
143
|
+
if (paddingLength === 2) {
|
|
144
|
+
// aaaaaabb
|
|
145
|
+
const x = input[inputIndex];
|
|
146
|
+
inputIndex -= 1;
|
|
147
|
+
|
|
148
|
+
output[outputIndex] = paddingChar;
|
|
149
|
+
outputIndex -= 1;
|
|
150
|
+
|
|
151
|
+
output[outputIndex] = paddingChar;
|
|
152
|
+
outputIndex -= 1;
|
|
153
|
+
|
|
154
|
+
output[outputIndex] = indexToChar[((x & 0b11) << 4)];
|
|
155
|
+
outputIndex -= 1;
|
|
156
|
+
|
|
157
|
+
output[outputIndex] = indexToChar[x >> 2];
|
|
158
|
+
outputIndex -= 1;
|
|
159
|
+
} else if (paddingLength === 1) {
|
|
160
|
+
// bbbbcccc
|
|
161
|
+
const y = input[inputIndex];
|
|
162
|
+
inputIndex -= 1;
|
|
163
|
+
|
|
164
|
+
// aaaaaabb
|
|
165
|
+
const x = input[inputIndex];
|
|
166
|
+
inputIndex -= 1;
|
|
167
|
+
|
|
168
|
+
output[outputIndex] = paddingChar;
|
|
169
|
+
outputIndex -= 1;
|
|
170
|
+
|
|
171
|
+
output[outputIndex] = indexToChar[((y & 0b1111) << 2)];
|
|
172
|
+
outputIndex -= 1;
|
|
173
|
+
|
|
174
|
+
output[outputIndex] = indexToChar[((x & 0b11) << 4) | (y >> 4)];
|
|
175
|
+
outputIndex -= 1;
|
|
176
|
+
|
|
177
|
+
output[outputIndex] = indexToChar[x >> 2];
|
|
178
|
+
outputIndex -= 1;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
while (inputIndex >= inputOffset) {
|
|
182
|
+
// ccdddddd
|
|
183
|
+
const z = input[inputIndex];
|
|
184
|
+
inputIndex -= 1;
|
|
185
|
+
|
|
186
|
+
// bbbbcccc
|
|
187
|
+
const y = input[inputIndex];
|
|
188
|
+
inputIndex -= 1;
|
|
189
|
+
|
|
190
|
+
// aaaaaabb
|
|
191
|
+
const x = input[inputIndex];
|
|
192
|
+
inputIndex -= 1;
|
|
193
|
+
|
|
194
|
+
output[outputIndex] = indexToChar[z & 0b111111];
|
|
195
|
+
outputIndex -= 1;
|
|
196
|
+
|
|
197
|
+
output[outputIndex] = indexToChar[((y & 0b1111) << 2) | (z >> 6)];
|
|
198
|
+
outputIndex -= 1;
|
|
199
|
+
|
|
200
|
+
output[outputIndex] = indexToChar[((x & 0b11) << 4) | (y >> 4)];
|
|
201
|
+
outputIndex -= 1;
|
|
202
|
+
|
|
203
|
+
output[outputIndex] = indexToChar[x >> 2];
|
|
204
|
+
outputIndex -= 1;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (outputType === 'ArrayBuffer') {
|
|
208
|
+
return output.buffer;
|
|
209
|
+
} else {
|
|
210
|
+
return outputLength;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
export function decodeBase64(input: string): ArrayBuffer {
|
|
215
|
+
let padding: number;
|
|
216
|
+
if (input[input.length - 2] === '=') {
|
|
217
|
+
padding = 2;
|
|
218
|
+
} else if (input[input.length - 1] === '=') {
|
|
219
|
+
padding = 1;
|
|
220
|
+
} else {
|
|
221
|
+
padding = 0;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const result = new Uint8Array(input.length / 4 * 3 - padding);
|
|
225
|
+
let sIndex = 0;
|
|
226
|
+
let dIndex = 0;
|
|
227
|
+
|
|
228
|
+
while (sIndex < input.length - (padding !== 0 ? 4 : 0)) {
|
|
229
|
+
const a = charToIndex[input[sIndex]];
|
|
230
|
+
sIndex += 1;
|
|
231
|
+
|
|
232
|
+
const b = charToIndex[input[sIndex]];
|
|
233
|
+
sIndex += 1;
|
|
234
|
+
|
|
235
|
+
const c = charToIndex[input[sIndex]];
|
|
236
|
+
sIndex += 1;
|
|
237
|
+
|
|
238
|
+
const d = charToIndex[input[sIndex]];
|
|
239
|
+
sIndex += 1;
|
|
240
|
+
|
|
241
|
+
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
242
|
+
dIndex += 1;
|
|
243
|
+
|
|
244
|
+
result[dIndex] = ((b & 0b1111) << 4) | ((c & 0b11_1100) >> 2);
|
|
245
|
+
dIndex += 1;
|
|
246
|
+
|
|
247
|
+
result[dIndex] = ((c & 0b11) << 6) | d;
|
|
248
|
+
dIndex += 1;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
if (padding === 1) {
|
|
252
|
+
const a = charToIndex[input[sIndex]];
|
|
253
|
+
sIndex += 1;
|
|
254
|
+
|
|
255
|
+
const b = charToIndex[input[sIndex]];
|
|
256
|
+
sIndex += 1;
|
|
257
|
+
|
|
258
|
+
const c = charToIndex[input[sIndex]];
|
|
259
|
+
|
|
260
|
+
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
261
|
+
dIndex += 1;
|
|
262
|
+
|
|
263
|
+
result[dIndex] = ((b & 0b1111) << 4) | ((c & 0b11_1100) >> 2);
|
|
264
|
+
} else if (padding === 2) {
|
|
265
|
+
const a = charToIndex[input[sIndex]];
|
|
266
|
+
sIndex += 1;
|
|
267
|
+
|
|
268
|
+
const b = charToIndex[input[sIndex]];
|
|
269
|
+
|
|
270
|
+
result[dIndex] = (a << 2) | ((b & 0b11_0000) >> 4);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
return result.buffer;
|
|
274
|
+
}
|