1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 07:44:48 -05:00

feat(std/node): support hex / base64 encoding in Buffer (#6414)

This commit is contained in:
Marcos Casagrande 2020-06-21 15:47:03 +02:00 committed by GitHub
parent 40866d7cd5
commit 86448fd9aa
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 203 additions and 5 deletions

View file

@ -1,3 +1,38 @@
import * as hex from "../encoding/hex.ts";
import * as base64 from "../encoding/base64.ts";
import { notImplemented } from "./_utils.ts";
const validEncodings = ["utf8", "hex", "base64"];
const notImplementedEncodings = [
"utf16le",
"latin1",
"ascii",
"binary",
"ucs2",
];
function checkEncoding(encoding = "utf8", strict = true): string {
if (typeof encoding !== "string" || (strict && encoding === "")) {
if (!strict) return "utf8";
throw new TypeError(`Unkown encoding: ${encoding}`);
}
encoding = encoding.toLowerCase();
if (encoding === "utf-8" || encoding === "") {
return "utf8";
}
if (notImplementedEncodings.includes(encoding)) {
notImplemented(`"${encoding}" encoding`);
}
if (!validEncodings.includes(encoding)) {
throw new TypeError(`Unkown encoding: ${encoding}`);
}
return encoding;
}
/** /**
* See also https://nodejs.org/api/buffer.html * See also https://nodejs.org/api/buffer.html
*/ */
@ -66,11 +101,24 @@ export default class Buffer extends Uint8Array {
/** /**
* Creates a new Buffer containing string. * Creates a new Buffer containing string.
*/ */
static from(string: string): Buffer; static from(string: string, encoding?: string): Buffer;
static from(
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
static from(value: any, offset?: number, length?: number): Buffer { value: any,
if (typeof value == "string") offsetOrEncoding?: number | string,
length?: number
): Buffer {
const offset =
typeof offsetOrEncoding === "string" ? undefined : offsetOrEncoding;
let encoding =
typeof offsetOrEncoding === "string" ? offsetOrEncoding : undefined;
if (typeof value == "string") {
encoding = checkEncoding(encoding, false);
if (encoding === "hex") return new Buffer(hex.decodeString(value).buffer);
if (encoding === "base64") return new Buffer(base64.decode(value));
return new Buffer(new TextEncoder().encode(value).buffer); return new Buffer(new TextEncoder().encode(value).buffer);
}
// workaround for https://github.com/microsoft/TypeScript/issues/38446 // workaround for https://github.com/microsoft/TypeScript/issues/38446
return new Buffer(value, offset!, length); return new Buffer(value, offset!, length);
@ -246,7 +294,13 @@ export default class Buffer extends Uint8Array {
* encoding. start and end may be passed to decode only a subset of buf. * encoding. start and end may be passed to decode only a subset of buf.
*/ */
toString(encoding = "utf8", start = 0, end = this.length): string { toString(encoding = "utf8", start = 0, end = this.length): string {
return new TextDecoder(encoding).decode(this.subarray(start, end)); encoding = checkEncoding(encoding);
const b = this.subarray(start, end);
if (encoding === "hex") return hex.encodeToString(b);
if (encoding === "base64") return base64.encode(b.buffer);
return new TextDecoder(encoding).decode(b);
} }
/** /**

View file

@ -116,6 +116,150 @@ Deno.test({
}, },
}); });
Deno.test({
name: "Buffer from string hex",
fn() {
for (const encoding of ["hex", "HEX"]) {
const buffer: Buffer = Buffer.from(
"7468697320697320612074c3a97374",
encoding
);
assertEquals(buffer.length, 15, "Buffer length should be 15");
assertEquals(
buffer.toString(),
"this is a tést",
"Buffer to string should recover the string"
);
}
},
});
Deno.test({
name: "Buffer from string base64",
fn() {
for (const encoding of ["base64", "BASE64"]) {
const buffer: Buffer = Buffer.from("dGhpcyBpcyBhIHTDqXN0", encoding);
assertEquals(buffer.length, 15, "Buffer length should be 15");
assertEquals(
buffer.toString(),
"this is a tést",
"Buffer to string should recover the string"
);
}
},
});
Deno.test({
name: "Buffer to string base64",
fn() {
for (const encoding of ["base64", "BASE64"]) {
const buffer: Buffer = Buffer.from("deno land");
assertEquals(
buffer.toString(encoding),
"ZGVubyBsYW5k",
"Buffer to string should recover the string in base64"
);
}
const b64 = "dGhpcyBpcyBhIHTDqXN0";
assertEquals(Buffer.from(b64, "base64").toString("base64"), b64);
},
});
Deno.test({
name: "Buffer to string hex",
fn() {
for (const encoding of ["hex", "HEX"]) {
const buffer: Buffer = Buffer.from("deno land");
assertEquals(
buffer.toString(encoding),
"64656e6f206c616e64",
"Buffer to string should recover the string"
);
}
const hex = "64656e6f206c616e64";
assertEquals(Buffer.from(hex, "hex").toString("hex"), hex);
},
});
Deno.test({
name: "Buffer to string invalid encoding",
fn() {
const buffer: Buffer = Buffer.from("deno land");
const invalidEncodings = [null, 5, {}, true, false, "foo", ""];
for (const encoding of invalidEncodings) {
assertThrows(
() => {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
buffer.toString(encoding);
},
TypeError,
`Unkown encoding: ${encoding}`,
"Should throw on invalid encoding"
);
}
},
});
Deno.test({
name: "Buffer from string invalid encoding",
fn() {
const defaultToUtf8Encodings = [null, 5, {}, true, false, ""];
const invalidEncodings = ["deno", "base645"];
for (const encoding of defaultToUtf8Encodings) {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
assertEquals(Buffer.from("yes", encoding).toString(), "yes");
}
for (const encoding of invalidEncodings) {
assertThrows(
() => {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
Buffer.from("yes", encoding);
},
TypeError,
`Unkown encoding: ${encoding}`
);
}
},
});
Deno.test({
name: "Buffer to/from string not implemented encodings",
fn() {
const buffer: Buffer = Buffer.from("deno land");
const notImplemented = ["ascii", "binary"];
for (const encoding of notImplemented) {
assertThrows(
() => {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
buffer.toString(encoding);
},
Error,
`"${encoding}" encoding`,
"Should throw on invalid encoding"
);
assertThrows(
() => {
// deno-lint-ignore ban-ts-comment
// @ts-ignore
Buffer.from("", encoding);
},
Error,
`"${encoding}" encoding`,
"Should throw on invalid encoding"
);
}
},
});
Deno.test({ Deno.test({
name: "Buffer from another buffer creates a Buffer", name: "Buffer from another buffer creates a Buffer",
fn() { fn() {