mirror of
https://github.com/denoland/std.git
synced 2024-11-21 20:50:22 +00:00
refactor(bytes): move to single-export files (#2955)
This commit is contained in:
parent
8e46f5953e
commit
e1117a8c0d
26
bytes/concat.ts
Normal file
26
bytes/concat.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Concatenate the given arrays into a new Uint8Array.
|
||||
*
|
||||
* ```ts
|
||||
* import { concat } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const a = new Uint8Array([0, 1, 2]);
|
||||
* const b = new Uint8Array([3, 4, 5]);
|
||||
* console.log(concat(a, b)); // [0, 1, 2, 3, 4, 5]
|
||||
*/
|
||||
export function concat(...buf: Uint8Array[]): Uint8Array {
|
||||
let length = 0;
|
||||
for (const b of buf) {
|
||||
length += b.length;
|
||||
}
|
||||
|
||||
const output = new Uint8Array(length);
|
||||
let index = 0;
|
||||
for (const b of buf) {
|
||||
output.set(b, index);
|
||||
index += b.length;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
36
bytes/concat_test.ts
Normal file
36
bytes/concat_test.ts
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import { concat } from "./concat.ts";
|
||||
|
||||
Deno.test("[bytes] concat", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const u1 = encoder.encode("Hello ");
|
||||
const u2 = encoder.encode("World");
|
||||
const joined = concat(u1, u2);
|
||||
assertEquals(new TextDecoder().decode(joined), "Hello World");
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] concat empty arrays", () => {
|
||||
const u1 = new Uint8Array();
|
||||
const u2 = new Uint8Array();
|
||||
const joined = concat(u1, u2);
|
||||
assertEquals(joined.byteLength, 0);
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] concat multiple arrays", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const u1 = encoder.encode("Hello ");
|
||||
const u2 = encoder.encode("W");
|
||||
const u3 = encoder.encode("o");
|
||||
const u4 = encoder.encode("r");
|
||||
const u5 = encoder.encode("l");
|
||||
const u6 = encoder.encode("d");
|
||||
const joined = concat(u1, u2, u3, u4, u5, u6);
|
||||
assertEquals(new TextDecoder().decode(joined), "Hello World");
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
38
bytes/copy.ts
Normal file
38
bytes/copy.ts
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Copy bytes from the `src` array to the `dst` array. Returns the number of
|
||||
* bytes copied.
|
||||
*
|
||||
* If the `src` array is larger than what the `dst` array can hold, only the
|
||||
* amount of bytes that fit in the `dst` array are copied.
|
||||
*
|
||||
* An offset can be specified as the third argument that begins the copy at
|
||||
* that given index in the `dst` array. The offset defaults to the beginning of
|
||||
* the array.
|
||||
*
|
||||
* ```ts
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const src = new Uint8Array([9, 8, 7]);
|
||||
* const dst = new Uint8Array([0, 1, 2, 3, 4, 5]);
|
||||
* console.log(copy(src, dst)); // 3
|
||||
* console.log(dst); // [9, 8, 7, 3, 4, 5]
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const src = new Uint8Array([1, 1, 1, 1]);
|
||||
* const dst = new Uint8Array([0, 0, 0, 0]);
|
||||
* console.log(copy(src, dst, 1)); // 3
|
||||
* console.log(dst); // [0, 1, 1, 1]
|
||||
* ```
|
||||
*/
|
||||
export function copy(src: Uint8Array, dst: Uint8Array, off = 0): number {
|
||||
off = Math.max(0, Math.min(off, dst.byteLength));
|
||||
const dstBytesAvailable = dst.byteLength - off;
|
||||
if (src.byteLength > dstBytesAvailable) {
|
||||
src = src.subarray(0, dstBytesAvailable);
|
||||
}
|
||||
dst.set(src, off);
|
||||
return src.byteLength;
|
||||
}
|
37
bytes/copy_test.ts
Normal file
37
bytes/copy_test.ts
Normal file
@ -0,0 +1,37 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import { copy } from "./copy.ts";
|
||||
|
||||
Deno.test("[bytes] copy", function () {
|
||||
const dst = new Uint8Array(4);
|
||||
|
||||
dst.fill(0);
|
||||
let src = Uint8Array.of(1, 2);
|
||||
let len = copy(src, dst, 0);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(1, 2, 0, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2);
|
||||
len = copy(src, dst, 1);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(0, 1, 2, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2, 3, 4, 5);
|
||||
len = copy(src, dst);
|
||||
assert(len === 4);
|
||||
assertEquals(dst, Uint8Array.of(1, 2, 3, 4));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2);
|
||||
len = copy(src, dst, 100);
|
||||
assert(len === 0);
|
||||
assertEquals(dst, Uint8Array.of(0, 0, 0, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(3, 4);
|
||||
len = copy(src, dst, -2);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(3, 4, 0, 0));
|
||||
});
|
25
bytes/ends_with.ts
Normal file
25
bytes/ends_with.ts
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Returns true if the suffix array appears at the end of the source array,
|
||||
* false otherwise.
|
||||
*
|
||||
* The complexity of this function is O(suffix.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { endsWith } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const suffix = new Uint8Array([1, 2, 3]);
|
||||
* console.log(endsWith(source, suffix)); // true
|
||||
* ```
|
||||
*/
|
||||
export function endsWith(source: Uint8Array, suffix: Uint8Array): boolean {
|
||||
for (
|
||||
let srci = source.length - 1, sfxi = suffix.length - 1;
|
||||
sfxi >= 0;
|
||||
srci--, sfxi--
|
||||
) {
|
||||
if (source[srci] !== suffix[sfxi]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
13
bytes/ends_with_test.ts
Normal file
13
bytes/ends_with_test.ts
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
import { endsWith } from "./ends_with.ts";
|
||||
|
||||
Deno.test("[bytes] endsWith", () => {
|
||||
const v = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([1, 2]));
|
||||
const v2 = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1]));
|
||||
const v3 = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 2, 3]));
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
@ -6,7 +6,7 @@
|
||||
* @param a first array to check equality
|
||||
* @param b second array to check equality
|
||||
*/
|
||||
export function equalsNaive(a: Uint8Array, b: Uint8Array): boolean {
|
||||
function equalsNaive(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.length !== b.length) return false;
|
||||
for (let i = 0; i < b.length; i++) {
|
||||
if (a[i] !== b[i]) return false;
|
||||
@ -19,7 +19,7 @@ export function equalsNaive(a: Uint8Array, b: Uint8Array): boolean {
|
||||
* @param a first array to check equality
|
||||
* @param b second array to check equality
|
||||
*/
|
||||
export function equals32Bit(a: Uint8Array, b: Uint8Array): boolean {
|
||||
function equals32Bit(a: Uint8Array, b: Uint8Array): boolean {
|
||||
if (a.length !== b.length) return false;
|
||||
const len = a.length;
|
||||
const compressable = Math.floor(len / 4);
|
||||
|
@ -1,35 +0,0 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { equals32Bit, equalsNaive } from "./equals.ts";
|
||||
|
||||
console.log("generating benchmarks...");
|
||||
const testCases: [Uint8Array, Uint8Array][] = [];
|
||||
// CHANGE THESE
|
||||
const len = 10000;
|
||||
const nCases = 10000;
|
||||
for (let i = 0; i < nCases; i++) {
|
||||
const arr1 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr2 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr3 = arr1.slice(0);
|
||||
arr3[arr3.length - 1] = arr1[arr1.length - 1] ^ 1;
|
||||
testCases.push([arr1, arr1.slice(0)]);
|
||||
testCases.push([arr1, arr2]);
|
||||
testCases.push([arr1, arr3]);
|
||||
}
|
||||
|
||||
Deno.bench({
|
||||
name: "bench old equals",
|
||||
fn() {
|
||||
for (const [a, b] of testCases) {
|
||||
equalsNaive(a, b);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Deno.bench({
|
||||
name: "bench simd equals",
|
||||
fn() {
|
||||
for (const [a, b] of testCases) {
|
||||
equals32Bit(a, b);
|
||||
}
|
||||
},
|
||||
});
|
34
bytes/equals_test.ts
Normal file
34
bytes/equals_test.ts
Normal file
@ -0,0 +1,34 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { equals } from "./equals.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
|
||||
Deno.test("[bytes] equals", () => {
|
||||
const v = equals(new Uint8Array([0, 1, 2, 3]), new Uint8Array([0, 1, 2, 3]));
|
||||
const v2 = equals(new Uint8Array([0, 1, 2, 2]), new Uint8Array([0, 1, 2, 3]));
|
||||
const v3 = equals(new Uint8Array([0, 1, 2, 3]), new Uint8Array([0, 1, 2]));
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] equals randomized testing", () => {
|
||||
// run tests before and after cutoff
|
||||
for (let len = 995; len <= 1005; len++) {
|
||||
const arr1 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr2 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr3 = arr1.slice(0);
|
||||
// the chance of arr1 equaling arr2 is basically 0
|
||||
// but introduce an inequality at the end just in case
|
||||
arr2[arr2.length - 1] = arr1[arr1.length - 1] ^ 1;
|
||||
// arr3 is arr1 but with an inequality in the very last element
|
||||
// this is to test the equality check when length isn't a multiple of 4
|
||||
arr3[arr3.length - 1] ^= 1;
|
||||
// arrays with same underlying ArrayBuffer should be equal
|
||||
assert(equals(arr1, arr1));
|
||||
// equal arrays with different underlying ArrayBuffers should be equal
|
||||
assert(equals(arr1, arr1.slice(0)));
|
||||
// inequal arrays should be inequal
|
||||
assert(!equals(arr1, arr2));
|
||||
assert(!equals(arr1, arr3));
|
||||
}
|
||||
});
|
27
bytes/includes_needle.ts
Normal file
27
bytes/includes_needle.ts
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
import { indexOfNeedle } from "./index_of_needle.ts";
|
||||
|
||||
/** Returns true if the source array contains the needle array, false otherwise.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the beginning of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.length * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { includesNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(includesNeedle(source, needle)); // true
|
||||
* console.log(includesNeedle(source, needle, 6)); // false
|
||||
* ```
|
||||
*/
|
||||
export function includesNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = 0,
|
||||
): boolean {
|
||||
return indexOfNeedle(source, needle, start) !== -1;
|
||||
}
|
15
bytes/includes_needle_test.ts
Normal file
15
bytes/includes_needle_test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { includesNeedle } from "./includes_needle.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
|
||||
Deno.test("[bytes] includesNeedle", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const source = encoder.encode("deno.land");
|
||||
const pattern = encoder.encode("deno");
|
||||
|
||||
assert(includesNeedle(source, pattern));
|
||||
assert(includesNeedle(new Uint8Array([0, 1, 2, 3]), new Uint8Array([2, 3])));
|
||||
|
||||
assert(includesNeedle(source, pattern, -10));
|
||||
assert(!includesNeedle(source, pattern, -1));
|
||||
});
|
49
bytes/index_of_needle.ts
Normal file
49
bytes/index_of_needle.ts
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Returns the index of the first occurrence of the needle array in the source
|
||||
* array, or -1 if it is not present.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the start of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.lenth * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { indexOfNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(indexOfNeedle(source, needle)); // 1
|
||||
* console.log(indexOfNeedle(source, needle, 2)); // 3
|
||||
* ```
|
||||
*/
|
||||
export function indexOfNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = 0,
|
||||
): number {
|
||||
if (start >= source.length) {
|
||||
return -1;
|
||||
}
|
||||
if (start < 0) {
|
||||
start = Math.max(0, source.length + start);
|
||||
}
|
||||
const s = needle[0];
|
||||
for (let i = start; i < source.length; i++) {
|
||||
if (source[i] !== s) continue;
|
||||
const pin = i;
|
||||
let matched = 1;
|
||||
let j = i;
|
||||
while (matched < needle.length) {
|
||||
j++;
|
||||
if (source[j] !== needle[j - pin]) {
|
||||
break;
|
||||
}
|
||||
matched++;
|
||||
}
|
||||
if (matched === needle.length) {
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
64
bytes/index_of_needle_test.ts
Normal file
64
bytes/index_of_needle_test.ts
Normal file
@ -0,0 +1,64 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { indexOfNeedle } from "./index_of_needle.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle1", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 3]),
|
||||
new Uint8Array([0, 1, 2]),
|
||||
);
|
||||
assertEquals(i, 2);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle2", () => {
|
||||
const i = indexOfNeedle(new Uint8Array([0, 0, 1]), new Uint8Array([0, 1]));
|
||||
assertEquals(i, 1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle3", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const i = indexOfNeedle(encoder.encode("Deno"), encoder.encode("D"));
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle4", () => {
|
||||
const i = indexOfNeedle(new Uint8Array(), new Uint8Array([0, 1]));
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
1,
|
||||
);
|
||||
assertEquals(i, 3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index 2", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
7,
|
||||
);
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index < 0", () => {
|
||||
assertEquals(
|
||||
indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
3,
|
||||
),
|
||||
3,
|
||||
);
|
||||
assertEquals(
|
||||
indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 1, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
3,
|
||||
),
|
||||
-1,
|
||||
);
|
||||
});
|
49
bytes/last_index_of_needle.ts
Normal file
49
bytes/last_index_of_needle.ts
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Returns the index of the last occurrence of the needle array in the source
|
||||
* array, or -1 if it is not present.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the end of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.lenth * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { lastIndexOfNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(lastIndexOfNeedle(source, needle)); // 5
|
||||
* console.log(lastIndexOfNeedle(source, needle, 4)); // 3
|
||||
* ```
|
||||
*/
|
||||
export function lastIndexOfNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = source.length - 1,
|
||||
): number {
|
||||
if (start < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (start >= source.length) {
|
||||
start = source.length - 1;
|
||||
}
|
||||
const e = needle[needle.length - 1];
|
||||
for (let i = start; i >= 0; i--) {
|
||||
if (source[i] !== e) continue;
|
||||
const pin = i;
|
||||
let matched = 1;
|
||||
let j = i;
|
||||
while (matched < needle.length) {
|
||||
j--;
|
||||
if (source[j] !== needle[needle.length - 1 - (pin - j)]) {
|
||||
break;
|
||||
}
|
||||
matched++;
|
||||
}
|
||||
if (matched === needle.length) {
|
||||
return pin - needle.length + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
42
bytes/last_index_of_needle_test.ts
Normal file
42
bytes/last_index_of_needle_test.ts
Normal file
@ -0,0 +1,42 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
import { lastIndexOfNeedle } from "./last_index_of_needle.ts";
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle1", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2, 0, 1, 3]),
|
||||
new Uint8Array([0, 1, 2]),
|
||||
);
|
||||
assertEquals(i, 3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle2", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 1]),
|
||||
new Uint8Array([0, 1]),
|
||||
);
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle3", () => {
|
||||
const i = lastIndexOfNeedle(new Uint8Array(), new Uint8Array([0, 1]));
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle with start index", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
2,
|
||||
);
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle with start index 2", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
-1,
|
||||
);
|
||||
assertEquals(i, -1);
|
||||
});
|
271
bytes/mod.ts
271
bytes/mod.ts
@ -8,264 +8,13 @@
|
||||
* @module
|
||||
*/
|
||||
|
||||
/** Returns the index of the first occurrence of the needle array in the source
|
||||
* array, or -1 if it is not present.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the start of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.lenth * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { indexOfNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(indexOfNeedle(source, needle)); // 1
|
||||
* console.log(indexOfNeedle(source, needle, 2)); // 3
|
||||
* ```
|
||||
*/
|
||||
export function indexOfNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = 0,
|
||||
): number {
|
||||
if (start >= source.length) {
|
||||
return -1;
|
||||
}
|
||||
if (start < 0) {
|
||||
start = Math.max(0, source.length + start);
|
||||
}
|
||||
const s = needle[0];
|
||||
for (let i = start; i < source.length; i++) {
|
||||
if (source[i] !== s) continue;
|
||||
const pin = i;
|
||||
let matched = 1;
|
||||
let j = i;
|
||||
while (matched < needle.length) {
|
||||
j++;
|
||||
if (source[j] !== needle[j - pin]) {
|
||||
break;
|
||||
}
|
||||
matched++;
|
||||
}
|
||||
if (matched === needle.length) {
|
||||
return pin;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Returns the index of the last occurrence of the needle array in the source
|
||||
* array, or -1 if it is not present.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the end of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.lenth * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { lastIndexOfNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(lastIndexOfNeedle(source, needle)); // 5
|
||||
* console.log(lastIndexOfNeedle(source, needle, 4)); // 3
|
||||
* ```
|
||||
*/
|
||||
export function lastIndexOfNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = source.length - 1,
|
||||
): number {
|
||||
if (start < 0) {
|
||||
return -1;
|
||||
}
|
||||
if (start >= source.length) {
|
||||
start = source.length - 1;
|
||||
}
|
||||
const e = needle[needle.length - 1];
|
||||
for (let i = start; i >= 0; i--) {
|
||||
if (source[i] !== e) continue;
|
||||
const pin = i;
|
||||
let matched = 1;
|
||||
let j = i;
|
||||
while (matched < needle.length) {
|
||||
j--;
|
||||
if (source[j] !== needle[needle.length - 1 - (pin - j)]) {
|
||||
break;
|
||||
}
|
||||
matched++;
|
||||
}
|
||||
if (matched === needle.length) {
|
||||
return pin - needle.length + 1;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Returns true if the prefix array appears at the start of the source array,
|
||||
* false otherwise.
|
||||
*
|
||||
* The complexity of this function is O(prefix.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { startsWith } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const prefix = new Uint8Array([0, 1, 2]);
|
||||
* console.log(startsWith(source, prefix)); // true
|
||||
* ```
|
||||
*/
|
||||
export function startsWith(source: Uint8Array, prefix: Uint8Array): boolean {
|
||||
for (let i = 0, max = prefix.length; i < max; i++) {
|
||||
if (source[i] !== prefix[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns true if the suffix array appears at the end of the source array,
|
||||
* false otherwise.
|
||||
*
|
||||
* The complexity of this function is O(suffix.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { endsWith } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const suffix = new Uint8Array([1, 2, 3]);
|
||||
* console.log(endsWith(source, suffix)); // true
|
||||
* ```
|
||||
*/
|
||||
export function endsWith(source: Uint8Array, suffix: Uint8Array): boolean {
|
||||
for (
|
||||
let srci = source.length - 1, sfxi = suffix.length - 1;
|
||||
sfxi >= 0;
|
||||
srci--, sfxi--
|
||||
) {
|
||||
if (source[srci] !== suffix[sfxi]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns a new Uint8Array composed of `count` repetitions of the `source`
|
||||
* array.
|
||||
*
|
||||
* If `count` is negative, a `RangeError` is thrown.
|
||||
*
|
||||
* ```ts
|
||||
* import { repeat } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2]);
|
||||
* console.log(repeat(source, 3)); // [0, 1, 2, 0, 1, 2, 0, 1, 2]
|
||||
* console.log(repeat(source, 0)); // []
|
||||
* console.log(repeat(source, -1)); // RangeError
|
||||
* ```
|
||||
*/
|
||||
export function repeat(source: Uint8Array, count: number): Uint8Array {
|
||||
if (count === 0) {
|
||||
return new Uint8Array();
|
||||
}
|
||||
|
||||
if (count < 0) {
|
||||
throw new RangeError("bytes: negative repeat count");
|
||||
} else if ((source.length * count) / count !== source.length) {
|
||||
throw new Error("bytes: repeat count causes overflow");
|
||||
}
|
||||
|
||||
const int = Math.floor(count);
|
||||
|
||||
if (int !== count) {
|
||||
throw new Error("bytes: repeat count must be an integer");
|
||||
}
|
||||
|
||||
const nb = new Uint8Array(source.length * count);
|
||||
|
||||
let bp = copy(source, nb);
|
||||
|
||||
for (; bp < nb.length; bp *= 2) {
|
||||
copy(nb.slice(0, bp), nb, bp);
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
/** Concatenate the given arrays into a new Uint8Array.
|
||||
*
|
||||
* ```ts
|
||||
* import { concat } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const a = new Uint8Array([0, 1, 2]);
|
||||
* const b = new Uint8Array([3, 4, 5]);
|
||||
* console.log(concat(a, b)); // [0, 1, 2, 3, 4, 5]
|
||||
*/
|
||||
export function concat(...buf: Uint8Array[]): Uint8Array {
|
||||
let length = 0;
|
||||
for (const b of buf) {
|
||||
length += b.length;
|
||||
}
|
||||
|
||||
const output = new Uint8Array(length);
|
||||
let index = 0;
|
||||
for (const b of buf) {
|
||||
output.set(b, index);
|
||||
index += b.length;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/** Returns true if the source array contains the needle array, false otherwise.
|
||||
*
|
||||
* A start index can be specified as the third argument that begins the search
|
||||
* at that given index. The start index defaults to the beginning of the array.
|
||||
*
|
||||
* The complexity of this function is O(source.length * needle.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { includesNeedle } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const needle = new Uint8Array([1, 2]);
|
||||
* console.log(includesNeedle(source, needle)); // true
|
||||
* console.log(includesNeedle(source, needle, 6)); // false
|
||||
* ```
|
||||
*/
|
||||
export function includesNeedle(
|
||||
source: Uint8Array,
|
||||
needle: Uint8Array,
|
||||
start = 0,
|
||||
): boolean {
|
||||
return indexOfNeedle(source, needle, start) !== -1;
|
||||
}
|
||||
|
||||
/** Copy bytes from the `src` array to the `dst` array. Returns the number of
|
||||
* bytes copied.
|
||||
*
|
||||
* If the `src` array is larger than what the `dst` array can hold, only the
|
||||
* amount of bytes that fit in the `dst` array are copied.
|
||||
*
|
||||
* An offset can be specified as the third argument that begins the copy at
|
||||
* that given index in the `dst` array. The offset defaults to the beginning of
|
||||
* the array.
|
||||
*
|
||||
* ```ts
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const src = new Uint8Array([9, 8, 7]);
|
||||
* const dst = new Uint8Array([0, 1, 2, 3, 4, 5]);
|
||||
* console.log(copy(src, dst)); // 3
|
||||
* console.log(dst); // [9, 8, 7, 3, 4, 5]
|
||||
* ```
|
||||
*
|
||||
* ```ts
|
||||
* import { copy } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const src = new Uint8Array([1, 1, 1, 1]);
|
||||
* const dst = new Uint8Array([0, 0, 0, 0]);
|
||||
* console.log(copy(src, dst, 1)); // 3
|
||||
* console.log(dst); // [0, 1, 1, 1]
|
||||
* ```
|
||||
*/
|
||||
export function copy(src: Uint8Array, dst: Uint8Array, off = 0): number {
|
||||
off = Math.max(0, Math.min(off, dst.byteLength));
|
||||
const dstBytesAvailable = dst.byteLength - off;
|
||||
if (src.byteLength > dstBytesAvailable) {
|
||||
src = src.subarray(0, dstBytesAvailable);
|
||||
}
|
||||
dst.set(src, off);
|
||||
return src.byteLength;
|
||||
}
|
||||
|
||||
export { equals } from "./equals.ts";
|
||||
export * from "./bytes_list.ts";
|
||||
export * from "./concat.ts";
|
||||
export * from "./copy.ts";
|
||||
export * from "./ends_with.ts";
|
||||
export * from "./equals.ts";
|
||||
export * from "./includes_needle.ts";
|
||||
export * from "./index_of_needle.ts";
|
||||
export * from "./last_index_of_needle.ts";
|
||||
export * from "./repeat.ts";
|
||||
export * from "./starts_with.ts";
|
||||
|
44
bytes/repeat.ts
Normal file
44
bytes/repeat.ts
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
import { copy } from "./copy.ts";
|
||||
|
||||
/** Returns a new Uint8Array composed of `count` repetitions of the `source`
|
||||
* array.
|
||||
*
|
||||
* If `count` is negative, a `RangeError` is thrown.
|
||||
*
|
||||
* ```ts
|
||||
* import { repeat } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2]);
|
||||
* console.log(repeat(source, 3)); // [0, 1, 2, 0, 1, 2, 0, 1, 2]
|
||||
* console.log(repeat(source, 0)); // []
|
||||
* console.log(repeat(source, -1)); // RangeError
|
||||
* ```
|
||||
*/
|
||||
export function repeat(source: Uint8Array, count: number): Uint8Array {
|
||||
if (count === 0) {
|
||||
return new Uint8Array();
|
||||
}
|
||||
|
||||
if (count < 0) {
|
||||
throw new RangeError("bytes: negative repeat count");
|
||||
} else if ((source.length * count) / count !== source.length) {
|
||||
throw new Error("bytes: repeat count causes overflow");
|
||||
}
|
||||
|
||||
const int = Math.floor(count);
|
||||
|
||||
if (int !== count) {
|
||||
throw new Error("bytes: repeat count must be an integer");
|
||||
}
|
||||
|
||||
const nb = new Uint8Array(source.length * count);
|
||||
|
||||
let bp = copy(source, nb);
|
||||
|
||||
for (; bp < nb.length; bp *= 2) {
|
||||
copy(nb.slice(0, bp), nb, bp);
|
||||
}
|
||||
|
||||
return nb;
|
||||
}
|
36
bytes/repeat_test.ts
Normal file
36
bytes/repeat_test.ts
Normal file
@ -0,0 +1,36 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assertEquals, assertThrows } from "../testing/asserts.ts";
|
||||
import { repeat } from "./repeat.ts";
|
||||
|
||||
Deno.test("[bytes] repeat", () => {
|
||||
// input / output / count / error message
|
||||
const repeatTestCase = [
|
||||
["", "", 0],
|
||||
["", "", 1],
|
||||
["", "", 1.1, "bytes: repeat count must be an integer"],
|
||||
["", "", 2],
|
||||
["", "", 0],
|
||||
["-", "", 0],
|
||||
["-", "-", -1, "bytes: negative repeat count"],
|
||||
["-", "----------", 10],
|
||||
["abc ", "abc abc abc ", 3],
|
||||
];
|
||||
for (const [input, output, count, errMsg] of repeatTestCase) {
|
||||
if (errMsg) {
|
||||
assertThrows(
|
||||
() => {
|
||||
repeat(new TextEncoder().encode(input as string), count as number);
|
||||
},
|
||||
Error,
|
||||
errMsg as string,
|
||||
);
|
||||
} else {
|
||||
const newBytes = repeat(
|
||||
new TextEncoder().encode(input as string),
|
||||
count as number,
|
||||
);
|
||||
|
||||
assertEquals(new TextDecoder().decode(newBytes), output);
|
||||
}
|
||||
}
|
||||
});
|
21
bytes/starts_with.ts
Normal file
21
bytes/starts_with.ts
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
// This module is browser compatible.
|
||||
|
||||
/** Returns true if the prefix array appears at the start of the source array,
|
||||
* false otherwise.
|
||||
*
|
||||
* The complexity of this function is O(prefix.length).
|
||||
*
|
||||
* ```ts
|
||||
* import { startsWith } from "https://deno.land/std@$STD_VERSION/bytes/mod.ts";
|
||||
* const source = new Uint8Array([0, 1, 2, 1, 2, 1, 2, 3]);
|
||||
* const prefix = new Uint8Array([0, 1, 2]);
|
||||
* console.log(startsWith(source, prefix)); // true
|
||||
* ```
|
||||
*/
|
||||
export function startsWith(source: Uint8Array, prefix: Uint8Array): boolean {
|
||||
for (let i = 0, max = prefix.length; i < max; i++) {
|
||||
if (source[i] !== prefix[i]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
15
bytes/starts_with_test.ts
Normal file
15
bytes/starts_with_test.ts
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
import { startsWith } from "./starts_with.ts";
|
||||
|
||||
Deno.test("[bytes] startsWith", () => {
|
||||
const v = startsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1]));
|
||||
const v2 = startsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 2]));
|
||||
const v3 = startsWith(
|
||||
new Uint8Array([0, 1, 2]),
|
||||
new Uint8Array([0, 2, 3, 4]),
|
||||
);
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
278
bytes/test.ts
278
bytes/test.ts
@ -1,278 +0,0 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import {
|
||||
concat,
|
||||
copy,
|
||||
endsWith,
|
||||
equals,
|
||||
includesNeedle,
|
||||
indexOfNeedle,
|
||||
lastIndexOfNeedle,
|
||||
repeat,
|
||||
startsWith,
|
||||
} from "./mod.ts";
|
||||
import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle1", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 3]),
|
||||
new Uint8Array([0, 1, 2]),
|
||||
);
|
||||
assertEquals(i, 2);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle2", () => {
|
||||
const i = indexOfNeedle(new Uint8Array([0, 0, 1]), new Uint8Array([0, 1]));
|
||||
assertEquals(i, 1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle3", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const i = indexOfNeedle(encoder.encode("Deno"), encoder.encode("D"));
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle4", () => {
|
||||
const i = indexOfNeedle(new Uint8Array(), new Uint8Array([0, 1]));
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
1,
|
||||
);
|
||||
assertEquals(i, 3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index 2", () => {
|
||||
const i = indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
7,
|
||||
);
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] indexOfNeedle with start index < 0", () => {
|
||||
assertEquals(
|
||||
indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
3,
|
||||
),
|
||||
3,
|
||||
);
|
||||
assertEquals(
|
||||
indexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 1, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
3,
|
||||
),
|
||||
-1,
|
||||
);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle1", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2, 0, 1, 3]),
|
||||
new Uint8Array([0, 1, 2]),
|
||||
);
|
||||
assertEquals(i, 3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle2", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 1]),
|
||||
new Uint8Array([0, 1]),
|
||||
);
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle3", () => {
|
||||
const i = lastIndexOfNeedle(new Uint8Array(), new Uint8Array([0, 1]));
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle with start index", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
2,
|
||||
);
|
||||
assertEquals(i, 0);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] lastIndexOfNeedle with start index 2", () => {
|
||||
const i = lastIndexOfNeedle(
|
||||
new Uint8Array([0, 1, 2, 0, 1, 2]),
|
||||
new Uint8Array([0, 1]),
|
||||
-1,
|
||||
);
|
||||
assertEquals(i, -1);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] equals", () => {
|
||||
const v = equals(new Uint8Array([0, 1, 2, 3]), new Uint8Array([0, 1, 2, 3]));
|
||||
const v2 = equals(new Uint8Array([0, 1, 2, 2]), new Uint8Array([0, 1, 2, 3]));
|
||||
const v3 = equals(new Uint8Array([0, 1, 2, 3]), new Uint8Array([0, 1, 2]));
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] equals randomized testing", () => {
|
||||
// run tests before and after cutoff
|
||||
for (let len = 995; len <= 1005; len++) {
|
||||
const arr1 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr2 = crypto.getRandomValues(new Uint8Array(len));
|
||||
const arr3 = arr1.slice(0);
|
||||
// the chance of arr1 equaling arr2 is basically 0
|
||||
// but introduce an inequality at the end just in case
|
||||
arr2[arr2.length - 1] = arr1[arr1.length - 1] ^ 1;
|
||||
// arr3 is arr1 but with an inequality in the very last element
|
||||
// this is to test the equality check when length isn't a multiple of 4
|
||||
arr3[arr3.length - 1] ^= 1;
|
||||
// arrays with same underlying ArrayBuffer should be equal
|
||||
assert(equals(arr1, arr1));
|
||||
// equal arrays with different underlying ArrayBuffers should be equal
|
||||
assert(equals(arr1, arr1.slice(0)));
|
||||
// inequal arrays should be inequal
|
||||
assert(!equals(arr1, arr2));
|
||||
assert(!equals(arr1, arr3));
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("[bytes] startsWith", () => {
|
||||
const v = startsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1]));
|
||||
const v2 = startsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 2]));
|
||||
const v3 = startsWith(
|
||||
new Uint8Array([0, 1, 2]),
|
||||
new Uint8Array([0, 2, 3, 4]),
|
||||
);
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] endsWith", () => {
|
||||
const v = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([1, 2]));
|
||||
const v2 = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1]));
|
||||
const v3 = endsWith(new Uint8Array([0, 1, 2]), new Uint8Array([0, 1, 2, 3]));
|
||||
assert(v);
|
||||
assert(!v2);
|
||||
assert(!v3);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] repeat", () => {
|
||||
// input / output / count / error message
|
||||
const repeatTestCase = [
|
||||
["", "", 0],
|
||||
["", "", 1],
|
||||
["", "", 1.1, "bytes: repeat count must be an integer"],
|
||||
["", "", 2],
|
||||
["", "", 0],
|
||||
["-", "", 0],
|
||||
["-", "-", -1, "bytes: negative repeat count"],
|
||||
["-", "----------", 10],
|
||||
["abc ", "abc abc abc ", 3],
|
||||
];
|
||||
for (const [input, output, count, errMsg] of repeatTestCase) {
|
||||
if (errMsg) {
|
||||
assertThrows(
|
||||
() => {
|
||||
repeat(new TextEncoder().encode(input as string), count as number);
|
||||
},
|
||||
Error,
|
||||
errMsg as string,
|
||||
);
|
||||
} else {
|
||||
const newBytes = repeat(
|
||||
new TextEncoder().encode(input as string),
|
||||
count as number,
|
||||
);
|
||||
|
||||
assertEquals(new TextDecoder().decode(newBytes), output);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Deno.test("[bytes] concat", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const u1 = encoder.encode("Hello ");
|
||||
const u2 = encoder.encode("World");
|
||||
const joined = concat(u1, u2);
|
||||
assertEquals(new TextDecoder().decode(joined), "Hello World");
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] concat empty arrays", () => {
|
||||
const u1 = new Uint8Array();
|
||||
const u2 = new Uint8Array();
|
||||
const joined = concat(u1, u2);
|
||||
assertEquals(joined.byteLength, 0);
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] concat multiple arrays", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const u1 = encoder.encode("Hello ");
|
||||
const u2 = encoder.encode("W");
|
||||
const u3 = encoder.encode("o");
|
||||
const u4 = encoder.encode("r");
|
||||
const u5 = encoder.encode("l");
|
||||
const u6 = encoder.encode("d");
|
||||
const joined = concat(u1, u2, u3, u4, u5, u6);
|
||||
assertEquals(new TextDecoder().decode(joined), "Hello World");
|
||||
assert(u1 !== joined);
|
||||
assert(u2 !== joined);
|
||||
});
|
||||
|
||||
Deno.test("[bytes] includesNeedle", () => {
|
||||
const encoder = new TextEncoder();
|
||||
const source = encoder.encode("deno.land");
|
||||
const pattern = encoder.encode("deno");
|
||||
|
||||
assert(includesNeedle(source, pattern));
|
||||
assert(includesNeedle(new Uint8Array([0, 1, 2, 3]), new Uint8Array([2, 3])));
|
||||
|
||||
assert(includesNeedle(source, pattern, -10));
|
||||
assert(!includesNeedle(source, pattern, -1));
|
||||
});
|
||||
|
||||
Deno.test("[bytes] copy", function () {
|
||||
const dst = new Uint8Array(4);
|
||||
|
||||
dst.fill(0);
|
||||
let src = Uint8Array.of(1, 2);
|
||||
let len = copy(src, dst, 0);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(1, 2, 0, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2);
|
||||
len = copy(src, dst, 1);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(0, 1, 2, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2, 3, 4, 5);
|
||||
len = copy(src, dst);
|
||||
assert(len === 4);
|
||||
assertEquals(dst, Uint8Array.of(1, 2, 3, 4));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(1, 2);
|
||||
len = copy(src, dst, 100);
|
||||
assert(len === 0);
|
||||
assertEquals(dst, Uint8Array.of(0, 0, 0, 0));
|
||||
|
||||
dst.fill(0);
|
||||
src = Uint8Array.of(3, 4);
|
||||
len = copy(src, dst, -2);
|
||||
assert(len === 2);
|
||||
assertEquals(dst, Uint8Array.of(3, 4, 0, 0));
|
||||
});
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert, assertEquals } from "../testing/asserts.ts";
|
||||
import { crypto as stdCrypto } from "./mod.ts";
|
||||
import * as bytes from "../bytes/mod.ts";
|
||||
import { repeat } from "../bytes/repeat.ts";
|
||||
import { dirname, fromFileUrl } from "../path/mod.ts";
|
||||
import { DigestAlgorithm, digestAlgorithms } from "./_wasm/mod.ts";
|
||||
const moduleDir = dirname(fromFileUrl(import.meta.url));
|
||||
@ -352,7 +352,7 @@ Deno.test("[crypto/digest] Memory use should remain reasonable even with many ca
|
||||
|
||||
// Simple periodic data, but the periods shouldn't line up with any block
|
||||
// or chunk sizes.
|
||||
const aboutAMeg = bytes.repeat(
|
||||
const aboutAMeg = repeat(
|
||||
new Uint8Array(1237).fill(0).map((_, i) => i % 251),
|
||||
839,
|
||||
);
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { crypto, type DigestAlgorithm } from "./mod.ts";
|
||||
import { toHashString } from "./util.ts";
|
||||
import { repeat } from "../bytes/mod.ts";
|
||||
import { repeat } from "../bytes/repeat.ts";
|
||||
import { assertEquals } from "../testing/asserts.ts";
|
||||
|
||||
const encoder = new TextEncoder();
|
||||
|
@ -1,7 +1,8 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
import { BytesList } from "../bytes/bytes_list.ts";
|
||||
import { concat, copy } from "../bytes/mod.ts";
|
||||
import { concat } from "../bytes/concat.ts";
|
||||
import { copy } from "../bytes/copy.ts";
|
||||
import type { Reader, ReaderSync, Writer, WriterSync } from "./types.d.ts";
|
||||
|
||||
// MIN_READ is the minimum ArrayBuffer size passed to a read call by
|
||||
|
@ -3,7 +3,7 @@
|
||||
// This code has been ported almost directly from Go's src/bytes/buffer_test.go
|
||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
import { copy } from "../bytes/mod.ts";
|
||||
import { copy } from "../bytes/copy.ts";
|
||||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { copy as copyBytes } from "../bytes/mod.ts";
|
||||
import { copy as copyBytes } from "../bytes/copy.ts";
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
|
||||
const DEFAULT_BUFFER_SIZE = 32 * 1024;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { copy } from "../bytes/mod.ts";
|
||||
import { copy } from "../bytes/copy.ts";
|
||||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { Encodings } from "./_node.ts";
|
||||
import { indexOfNeedle } from "../../bytes/mod.ts";
|
||||
import { indexOfNeedle } from "../../bytes/index_of_needle.ts";
|
||||
|
||||
export function numberToBytes(n: number): Uint8Array {
|
||||
if (n === 0) return new Uint8Array([0]);
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
import { copy } from "../bytes/mod.ts";
|
||||
import { copy } from "../bytes/copy.ts";
|
||||
|
||||
const MAX_SIZE = 2 ** 32 - 2;
|
||||
const DEFAULT_CHUNK_SIZE = 16_640;
|
||||
|
@ -19,7 +19,8 @@ import {
|
||||
writerFromStreamWriter,
|
||||
} from "./conversion.ts";
|
||||
import { Buffer } from "../io/buffer.ts";
|
||||
import { concat, copy as copyBytes } from "../bytes/mod.ts";
|
||||
import { concat } from "../bytes/concat.ts";
|
||||
import { copy as copyBytes } from "../bytes/copy.ts";
|
||||
|
||||
function repeat(c: string, bytes: number): Uint8Array {
|
||||
assertEquals(c.length, 1);
|
||||
|
@ -2,7 +2,7 @@
|
||||
// This module is browser compatible.
|
||||
|
||||
import { bytesToUuid, uuidToBytes } from "./_common.ts";
|
||||
import { concat } from "../bytes/mod.ts";
|
||||
import { concat } from "../bytes/concat.ts";
|
||||
import { assert } from "../_util/asserts.ts";
|
||||
|
||||
const UUID_RE =
|
||||
|
Loading…
Reference in New Issue
Block a user