Refactor base64
This commit is contained in:
parent
22b2f162bc
commit
185c233b2f
|
@ -0,0 +1,46 @@
|
||||||
|
const BASE64_DEC: {[key: string]: number} = {};
|
||||||
|
[... 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'].forEach(
|
||||||
|
(c, i) => BASE64_DEC[c] = i);
|
||||||
|
BASE64_DEC['+'] = BASE64_DEC['-'] = 62;
|
||||||
|
BASE64_DEC['/'] = BASE64_DEC['_'] = 63;
|
||||||
|
|
||||||
|
export function decodeBase64(s: string): Uint8Array {
|
||||||
|
const bs = new Uint8Array(Math.floor(s.length * 3/4));
|
||||||
|
let i = 0;
|
||||||
|
let j = 0;
|
||||||
|
while (i < s.length) {
|
||||||
|
const v1 = BASE64_DEC[s[i++]];
|
||||||
|
const v2 = BASE64_DEC[s[i++]];
|
||||||
|
const v3 = BASE64_DEC[s[i++]];
|
||||||
|
const v4 = BASE64_DEC[s[i++]];
|
||||||
|
const v = (v1 << 18) | (v2 << 12) | (v3 << 6) | v4;
|
||||||
|
bs[j++] = (v >> 16) & 255;
|
||||||
|
if (v3 === void 0) break;
|
||||||
|
bs[j++] = (v >> 8) & 255;
|
||||||
|
if (v4 === void 0) break;
|
||||||
|
bs[j++] = v & 255;
|
||||||
|
}
|
||||||
|
return bs.subarray(0, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BASE64_ENC = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
||||||
|
|
||||||
|
export function encodeBase64(bs: Uint8Array): string {
|
||||||
|
let s = '';
|
||||||
|
let buffer = 0;
|
||||||
|
let bitcount = 0;
|
||||||
|
for (let b of bs) {
|
||||||
|
buffer = ((buffer & 0x3f) << 8) | b;
|
||||||
|
bitcount += 8;
|
||||||
|
while (bitcount >= 6) {
|
||||||
|
bitcount -= 6;
|
||||||
|
const v = (buffer >> bitcount) & 0x3f;
|
||||||
|
s = s + BASE64_ENC[v];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (bitcount > 0) {
|
||||||
|
const v = (buffer << (6 - bitcount)) & 0x3f;
|
||||||
|
s = s + BASE64_ENC[v];
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
|
@ -2,7 +2,8 @@ import { Tag } from './constants';
|
||||||
import { GenericEmbedded } from './embedded';
|
import { GenericEmbedded } from './embedded';
|
||||||
import { Encoder, Preservable } from './encoder';
|
import { Encoder, Preservable } from './encoder';
|
||||||
import { Value } from './values';
|
import { Value } from './values';
|
||||||
import { Writer, PreserveWritable } from './writer';
|
import type { Writer, PreserveWritable } from './writer';
|
||||||
|
import { decodeBase64, encodeBase64 } from './base64';
|
||||||
|
|
||||||
const textEncoder = new TextEncoder();
|
const textEncoder = new TextEncoder();
|
||||||
const textDecoder = new TextDecoder();
|
const textDecoder = new TextDecoder();
|
||||||
|
@ -51,6 +52,10 @@ export class Bytes implements Preservable<any>, PreserveWritable<any> {
|
||||||
return new Bytes(Uint8Array.of(...bytes));
|
return new Bytes(Uint8Array.of(...bytes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static fromBase64(s: string): Bytes {
|
||||||
|
return new Bytes(decodeBase64(s));
|
||||||
|
}
|
||||||
|
|
||||||
static fromHex(s: string): Bytes {
|
static fromHex(s: string): Bytes {
|
||||||
if (s.length & 1) throw new Error("Cannot decode odd-length hexadecimal string");
|
if (s.length & 1) throw new Error("Cannot decode odd-length hexadecimal string");
|
||||||
const result = new Bytes(s.length >> 1);
|
const result = new Bytes(s.length >> 1);
|
||||||
|
@ -139,6 +144,10 @@ export class Bytes implements Preservable<any>, PreserveWritable<any> {
|
||||||
return Bytes.isBytes(v) ? v : void 0;
|
return Bytes.isBytes(v) ? v : void 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toBase64(): string {
|
||||||
|
return encodeBase64(this._view);
|
||||||
|
}
|
||||||
|
|
||||||
toHex(digit = hexDigit): string {
|
toHex(digit = hexDigit): string {
|
||||||
var nibbles = [];
|
var nibbles = [];
|
||||||
for (let i = 0; i < this.length; i++) {
|
for (let i = 0; i < this.length; i++) {
|
||||||
|
|
|
@ -155,7 +155,7 @@ export class ReaderState {
|
||||||
if (c === ']') break;
|
if (c === ']') break;
|
||||||
acc = acc + c;
|
acc = acc + c;
|
||||||
}
|
}
|
||||||
return decodeBase64(acc);
|
return Bytes.fromBase64(acc);
|
||||||
}
|
}
|
||||||
|
|
||||||
requireDelimiter(prefix: string): void {
|
requireDelimiter(prefix: string): void {
|
||||||
|
@ -436,31 +436,6 @@ export class Reader<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BASE64: {[key: string]: number} = {};
|
|
||||||
[... 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'].forEach(
|
|
||||||
(c, i) => BASE64[c] = i);
|
|
||||||
BASE64['+'] = BASE64['-'] = 62;
|
|
||||||
BASE64['/'] = BASE64['_'] = 63;
|
|
||||||
|
|
||||||
export function decodeBase64(s: string): Bytes {
|
|
||||||
const bs = new Uint8Array(Math.floor(s.length * 3/4));
|
|
||||||
let i = 0;
|
|
||||||
let j = 0;
|
|
||||||
while (i < s.length) {
|
|
||||||
const v1 = BASE64[s[i++]];
|
|
||||||
const v2 = BASE64[s[i++]];
|
|
||||||
const v3 = BASE64[s[i++]];
|
|
||||||
const v4 = BASE64[s[i++]];
|
|
||||||
const v = (v1 << 18) | (v2 << 12) | (v3 << 6) | v4;
|
|
||||||
bs[j++] = (v >> 16) & 255;
|
|
||||||
if (v3 === void 0) break;
|
|
||||||
bs[j++] = (v >> 8) & 255;
|
|
||||||
if (v4 === void 0) break;
|
|
||||||
bs[j++] = v & 255;
|
|
||||||
}
|
|
||||||
return Bytes.from(bs.subarray(0, j));
|
|
||||||
}
|
|
||||||
|
|
||||||
function isSpace(s: string): boolean {
|
function isSpace(s: string): boolean {
|
||||||
return ' \t\n\r'.indexOf(s) !== -1;
|
return ' \t\n\r'.indexOf(s) !== -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
export * from './annotated';
|
export * from './annotated';
|
||||||
|
export * from './base64';
|
||||||
export * from './bytes';
|
export * from './bytes';
|
||||||
export * from './codec';
|
export * from './codec';
|
||||||
export * from './compound';
|
export * from './compound';
|
||||||
|
|
|
@ -4,6 +4,7 @@ import type { GenericEmbedded, Embedded, EmbeddedTypeEncode } from "./embedded";
|
||||||
import { Encoder, EncoderState } from "./encoder";
|
import { Encoder, EncoderState } from "./encoder";
|
||||||
import type { Value } from "./values";
|
import type { Value } from "./values";
|
||||||
import { NUMBER_RE } from './reader';
|
import { NUMBER_RE } from './reader';
|
||||||
|
import { encodeBase64 } from './base64';
|
||||||
|
|
||||||
export type Writable<T> =
|
export type Writable<T> =
|
||||||
Value<T> | PreserveWritable<T> | Iterable<Value<T>> | ArrayBufferView;
|
Value<T> | PreserveWritable<T> | Iterable<Value<T>> | ArrayBufferView;
|
||||||
|
@ -205,28 +206,6 @@ export class WriterState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const BASE64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
|
|
||||||
|
|
||||||
export function encodeBase64(bs: Uint8Array): string {
|
|
||||||
let s = '';
|
|
||||||
let buffer = 0;
|
|
||||||
let bitcount = 0;
|
|
||||||
for (let b of bs) {
|
|
||||||
buffer = ((buffer & 0x3f) << 8) | b;
|
|
||||||
bitcount += 8;
|
|
||||||
while (bitcount >= 6) {
|
|
||||||
bitcount -= 6;
|
|
||||||
const v = (buffer >> bitcount) & 0x3f;
|
|
||||||
s = s + BASE64[v];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bitcount > 0) {
|
|
||||||
const v = (buffer << (6 - bitcount)) & 0x3f;
|
|
||||||
s = s + BASE64[v];
|
|
||||||
}
|
|
||||||
return s;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Writer<T> {
|
export class Writer<T> {
|
||||||
state: WriterState;
|
state: WriterState;
|
||||||
embeddedWrite: EmbeddedWriter<T>;
|
embeddedWrite: EmbeddedWriter<T>;
|
||||||
|
|
Loading…
Reference in New Issue