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:
parent
40866d7cd5
commit
86448fd9aa
2 changed files with 203 additions and 5 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in a new issue