Skip to content

feat(encoding/unstable): add format option to encodeBase64 and decodeBase64 #6457

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Mar 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d4ba5bf
perf(encoding): base64
BlackAsLight Feb 22, 2025
c1eccd4
perf(encoding): base64url
BlackAsLight Feb 22, 2025
df36993
perf(encoding): base32
BlackAsLight Feb 23, 2025
ea879eb
perf(encoding): base32hex
BlackAsLight Feb 23, 2025
2103c65
chore(encoding): add missing copyright comment
BlackAsLight Feb 23, 2025
ba88700
adjust(encoding): base64 to use `switch` instead of `if`
BlackAsLight Feb 23, 2025
8f671ae
chore(encoding): update exports
BlackAsLight Feb 23, 2025
56b6f99
chore(encoding): fmt
BlackAsLight Feb 23, 2025
71e0246
perf(encoding): hex
BlackAsLight Feb 23, 2025
a0ac03e
chore(encoding): remove file committed on accident
BlackAsLight Feb 23, 2025
927c2e7
perf(encoding): update streams to be more memory efficient
BlackAsLight Feb 23, 2025
39a3026
perf(encoding): base32crockford
BlackAsLight Feb 23, 2025
6bb70e5
Merge branch 'denoland:main' into encoding_refactor
BlackAsLight Feb 23, 2025
994124b
chore(encoding): fix docs
BlackAsLight Feb 23, 2025
01477c2
revert(encoding): perf brought to stable exports
BlackAsLight Feb 23, 2025
5acf1fc
docs(encoding): fix mismatch type
BlackAsLight Feb 23, 2025
6112d8a
chore(encoding): add missing export
BlackAsLight Feb 23, 2025
4bb9d91
chore(encoding): remove file committed on accident
BlackAsLight Feb 23, 2025
3b91390
perf(encoding): base32crockford stream
BlackAsLight Feb 23, 2025
75778c2
fix(encoding): types for deno v1.x
BlackAsLight Feb 23, 2025
d4fcd64
fix(encoding): types for deno v1.x
BlackAsLight Feb 23, 2025
ec1d78e
refactor(encoding): to bring perf to stable packages
BlackAsLight Feb 26, 2025
78e3c9d
refactor(encoding): merging same base functions & adding tests & docs
BlackAsLight Feb 26, 2025
0bec310
chore(tools): update check_docs.ts entrypoint
BlackAsLight Feb 26, 2025
8edd5e2
chore(encoding): fix types of deno v1.x
BlackAsLight Feb 26, 2025
8cffee7
Merge branch 'main' into encoding_refactor
BlackAsLight Feb 26, 2025
a26462a
revert(encoding): all changes except unstable base64
BlackAsLight Feb 27, 2025
628adf8
revert(tools): changes to check_docs.ts
BlackAsLight Feb 27, 2025
6bc7c32
revert(tool): missing change to check_docs.ts
BlackAsLight Feb 27, 2025
791712d
redo(tools): change that wasn't meant to be reverted
BlackAsLight Feb 27, 2025
01cb239
revert(encoding): changes for base64 stream
BlackAsLight Mar 3, 2025
9da395d
revert(tools): changes to check_docs.ts for base64 stream
BlackAsLight Mar 3, 2025
d2cd054
perf(encoding): improved for base64
BlackAsLight Mar 3, 2025
85a318a
Merge branch 'main' into encoding_base64_sync
BlackAsLight Mar 3, 2025
fbc4e61
add(encoding): default option to format arugment
BlackAsLight Mar 4, 2025
093cd8b
Merge branch 'main' into encoding_base64_sync
BlackAsLight Mar 4, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _tools/check_docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ const ENTRY_POINTS = [
"../datetime/mod.ts",
"../dotenv/mod.ts",
"../encoding/mod.ts",
"../encoding/unstable_base64.ts",
"../encoding/unstable_base64_stream.ts",
"../encoding/unstable_base32hex_stream.ts",
"../encoding/unstable_base32_stream.ts",
Expand Down
122 changes: 122 additions & 0 deletions encoding/_common64.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// Copyright 2018-2025 the Deno authors. MIT license.

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

/**
* Calculate the output size needed to encode a given input size for
* {@linkcode encodeRawBase64}.
*
* @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 { calcMax } from "@std/encoding/unstable-base64";
*
* assertEquals(calcMax(1), 4);
* ```
*/
export function calcMax(originalSize: number): number {
return ((originalSize + 2) / 3 | 0) * 4;
}

export function encode(
buffer: Uint8Array_,
i: number,
o: number,
alphabet: Uint8Array,
padding: number,
): number {
i += 2;
for (; i < buffer.length; i += 3) {
const x = (buffer[i - 2]! << 16) | (buffer[i - 1]! << 8) | buffer[i]!;
buffer[o++] = alphabet[x >> 18]!;
buffer[o++] = alphabet[x >> 12 & 0x3F]!;
buffer[o++] = alphabet[x >> 6 & 0x3F]!;
buffer[o++] = alphabet[x & 0x3F]!;
}
switch (i) {
case buffer.length + 1: {
const x = buffer[i - 2]! << 16;
buffer[o++] = alphabet[x >> 18]!;
buffer[o++] = alphabet[x >> 12 & 0x3F]!;
buffer[o++] = padding;
buffer[o++] = padding;
break;
}
case buffer.length: {
const x = (buffer[i - 2]! << 16) | (buffer[i - 1]! << 8);
buffer[o++] = alphabet[x >> 18]!;
buffer[o++] = alphabet[x >> 12 & 0x3F]!;
buffer[o++] = alphabet[x >> 6 & 0x3F]!;
buffer[o++] = padding;
break;
}
}
return o;
}

export function decode(
buffer: Uint8Array_,
i: number,
o: number,
alphabet: Uint8Array,
padding: number,
): number {
for (let x = buffer.length - 2; x < buffer.length; ++x) {
if (buffer[x] === padding) {
for (let y = x + 1; y < buffer.length; ++y) {
if (buffer[y] !== padding) {
throw new TypeError(
`Invalid Character (${String.fromCharCode(buffer[y]!)})`,
);
}
}
buffer = buffer.subarray(0, x);
break;
}
}
if ((buffer.length - o) % 4 === 1) {
throw new TypeError(
`Invalid Character (${String.fromCharCode(buffer[buffer.length - 1]!)})`,
);
}

i += 3;
for (; i < buffer.length; i += 4) {
const x = (getByte(buffer[i - 3]!, alphabet) << 18) |
(getByte(buffer[i - 2]!, alphabet) << 12) |
(getByte(buffer[i - 1]!, alphabet) << 6) |
getByte(buffer[i]!, alphabet);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
buffer[o++] = x & 0xFF;
}
switch (i) {
case buffer.length + 1: {
const x = (getByte(buffer[i - 3]!, alphabet) << 18) |
(getByte(buffer[i - 2]!, alphabet) << 12);
buffer[o++] = x >> 16;
break;
}
case buffer.length: {
const x = (getByte(buffer[i - 3]!, alphabet) << 18) |
(getByte(buffer[i - 2]!, alphabet) << 12) |
(getByte(buffer[i - 1]!, alphabet) << 6);
buffer[o++] = x >> 16;
buffer[o++] = x >> 8 & 0xFF;
break;
}
}
return o;
}

function getByte(char: number, alphabet: Uint8Array): number {
const byte = alphabet[char]!;
if (byte === 64) { // alphabet.Base64.length
throw new TypeError(`Invalid Character (${String.fromCharCode(char)})`);
}
return byte;
}
20 changes: 20 additions & 0 deletions encoding/_common_detach.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2018-2025 the Deno authors. MIT license.

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

export function detach(
buffer: Uint8Array_,
maxSize: number,
): [Uint8Array_, number] {
const originalSize = buffer.length;
if (buffer.byteOffset) {
const b = new Uint8Array(buffer.buffer);
b.set(buffer);
buffer = b.subarray(0, originalSize);
}
// deno-lint-ignore no-explicit-any
buffer = new Uint8Array((buffer.buffer as any).transfer(maxSize));
buffer.set(buffer.subarray(0, originalSize), maxSize - originalSize);
return [buffer, maxSize - originalSize];
}
1 change: 1 addition & 0 deletions encoding/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"./unstable-base32hex-stream": "./unstable_base32hex_stream.ts",
"./base58": "./base58.ts",
"./base64": "./base64.ts",
"./unstable-base64": "./unstable_base64.ts",
"./unstable-base64-stream": "./unstable_base64_stream.ts",
"./base64url": "./base64url.ts",
"./unstable-base64url-stream": "./unstable_base64url_stream.ts",
Expand Down
Loading
Loading