/** Browser and Node compatible byte primitives. */ export const utf8 = (value) => new TextEncoder().encode(value); export function concat(...parts) { const length = parts.reduce((total, part) => total + part.length, 0); const out = new Uint8Array(length); let offset = 0; for (const part of parts) { out.set(part, offset); offset += part.length; } return out; } export function le32(value) { if (!Number.isInteger(value) || value < 0 || value > 0xffff_ffff) throw new RangeError("u32 required"); return Uint8Array.of(value & 0xff, (value >>> 8) & 0xff, (value >>> 16) & 0xff, (value >>> 24) & 0xff); } /** Encodes a safe non-negative integer as LE u64 without BigInt. */ export function le64(value) { if (!Number.isSafeInteger(value) || value < 0) throw new RangeError("non-negative safe integer required"); const lo = value >>> 0; const hi = Math.floor(value / 0x1_0000_0000); return Uint8Array.of(lo & 0xff, (lo >>> 8) & 0xff, (lo >>> 16) & 0xff, (lo >>> 24) & 0xff, hi & 0xff, (hi >>> 8) & 0xff, (hi >>> 16) & 0xff, (hi >>> 24) & 0xff); } export function le64Pair(low, high) { return Uint8Array.of(low & 0xff, (low >>> 8) & 0xff, (low >>> 16) & 0xff, (low >>> 24) & 0xff, high & 0xff, (high >>> 8) & 0xff, (high >>> 16) & 0xff, (high >>> 24) & 0xff); } export function readU32LE(bytes, offset) { if (offset < 0 || offset + 4 > bytes.length) throw new RangeError("u32 outside input"); return (bytes[offset] | (bytes[offset + 1] << 8) | (bytes[offset + 2] << 16) | (bytes[offset + 3] << 24)) >>> 0; } export function hex(bytes) { let out = ""; for (const b of bytes) out += b.toString(16).padStart(2, "0"); return out; }