UNPKG

@seriousme/opifex

Version:

MQTT client & server for Deno & NodeJS

62 lines 2.09 kB
/** * Encodes a number into a variable-length byte array using a modified base-128 encoding * @param n The number to encode * @returns Array of bytes representing the encoded number * @throws Error if the encoded length is greater than 4 bytes */ export function encodeLength(n) { const output = []; let x = n; do { let encodedByte = x % 0x80; x = Math.floor(x / 0x80); if (x > 0) { encodedByte = encodedByte | 0x80; } output.push(encodedByte); } while (x > 0); if (output.length > 4) { throw Error("length encoding failed"); } return output; } /** * Decodes a variable-length encoded number from a byte array * @param buf The byte array containing the encoded number * @param start The starting position in the buffer to begin decoding * @returns Object containing the decoded length and number of bytes used for encoding * @throws Error if decoding fails */ export function decodeLength(buf, start) { const decode = getLengthDecoder(); const lenBuf = buf.subarray(start); for (const byte of lenBuf) { const { done, length, numLengthBytes } = decode(byte); if (done) { return { length, numLengthBytes }; } } throw Error("length decoding failed"); } /** * Creates a stateful decoder function for processing variable-length encoded numbers * @returns Function that processes one byte at a time and returns decoding status * @throws Error if the encoded length is greater than 4 bytes */ export function getLengthDecoder() { let numLengthBytes = 1; let length = 0; let multiplier = 1; return function addLengthByte(encodedByte) { length += (encodedByte & 0x7f) * multiplier; multiplier *= 0x80; if ((encodedByte & 0x80) === 0) { return { done: true, length, numLengthBytes }; } if (numLengthBytes++ >= 4) { throw Error("length decoding failed"); } return { done: false, length, numLengthBytes }; }; } //# sourceMappingURL=length.js.map