Skip to main content
Module

std/bytes/mod.ts

Deno standard library
Go to Latest
File
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.// This module is browser compatible.
/** * Provides helper functions to manipulate `Uint8Array` byte slices that are not * included on the `Uint8Array` prototype. * * @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 "./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 "./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 "./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 "./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 "./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 "./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 "./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 "./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 "./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";