import { toUint8Array, toUint8ArrayCopy } from "./buffer-source.js"; function clampIndex(value, fallback, length) { const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback; if (normalized <= 0) { return 0; } if (normalized >= length) { return length; } return normalized; } function normalizeForwardRange(length, options) { const start = clampIndex(options?.start, 0, length); const end = clampIndex(options?.end, length, length); return end >= start ? [start, end] : [start, start]; } function normalizeReverseRange(length, options) { const start = clampIndex(options?.start, length, length); const end = clampIndex(options?.end, 0, length); return start >= end ? [end, start] : [start, start]; } function normalizeSliceIndex(value, fallback, length) { const normalized = Number.isFinite(value) ? Math.trunc(value) : fallback; if (normalized < 0) { return Math.max(length + normalized, 0); } if (normalized > length) { return length; } return normalized; } function encodeAscii(text) { const bytes = new Uint8Array(text.length); for (let i = 0; i < text.length; i++) { bytes[i] = text.charCodeAt(i) & 0xff; } return bytes; } function encodeUtf8(text) { return new TextEncoder().encode(text); } function toPatternBytes(pattern, options) { if (typeof pattern === "string") { return options?.encoding === "utf8" ? encodeUtf8(pattern) : encodeAscii(pattern); } return toUint8Array(pattern); } function bytesEqualAt(data, pattern, offset) { for (let index = 0; index < pattern.byteLength; index++) { if (data[offset + index] !== pattern[index]) { return false; } } return true; } export function indexOf(data, pattern, options) { const bytes = toUint8Array(data); const needle = toPatternBytes(pattern, options); const [start, end] = normalizeForwardRange(bytes.byteLength, options); if (needle.byteLength === 0) { return start; } const lastOffset = end - needle.byteLength; if (lastOffset < start) { return -1; } for (let offset = start; offset <= lastOffset; offset++) { if (bytesEqualAt(bytes, needle, offset)) { return offset; } } return -1; } export function lastIndexOf(data, pattern, options) { const bytes = toUint8Array(data); const needle = toPatternBytes(pattern, options); const [end, start] = normalizeReverseRange(bytes.byteLength, options); if (needle.byteLength === 0) { return start; } const firstOffset = start - needle.byteLength; if (firstOffset < end) { return -1; } for (let offset = firstOffset; offset >= end; offset--) { if (bytesEqualAt(bytes, needle, offset)) { return offset; } } return -1; } export function includes(data, pattern, options) { return indexOf(data, pattern, options) !== -1; } export function startsWith(data, pattern, options) { const bytes = toUint8Array(data); const needle = toPatternBytes(pattern, options); if (needle.byteLength > bytes.byteLength) { return false; } return bytesEqualAt(bytes, needle, 0); } export function endsWith(data, pattern, options) { const bytes = toUint8Array(data); const needle = toPatternBytes(pattern, options); if (needle.byteLength > bytes.byteLength) { return false; } return bytesEqualAt(bytes, needle, bytes.byteLength - needle.byteLength); } export function slice(data, start, end) { const bytes = toUint8Array(data); const normalizedStart = normalizeSliceIndex(start, 0, bytes.byteLength); const normalizedEnd = normalizeSliceIndex(end, bytes.byteLength, bytes.byteLength); if (normalizedEnd <= normalizedStart) { return bytes.subarray(normalizedStart, normalizedStart); } return bytes.subarray(normalizedStart, normalizedEnd); } export function tail(data, length) { const bytes = toUint8Array(data); const normalizedLength = Number.isFinite(length) ? Math.max(0, Math.trunc(length)) : 0; if (normalizedLength >= bytes.byteLength) { return bytes; } return bytes.subarray(bytes.byteLength - normalizedLength); } export function copy(data) { return toUint8ArrayCopy(data); } export function compare(a, b) { const left = toUint8Array(a); const right = toUint8Array(b); const limit = Math.min(left.byteLength, right.byteLength); for (let index = 0; index < limit; index++) { if (left[index] < right[index]) { return -1; } if (left[index] > right[index]) { return 1; } } if (left.byteLength < right.byteLength) { return -1; } if (left.byteLength > right.byteLength) { return 1; } return 0; }