{"version":3,"sources":["../src/assertions.ts","../src/bytes.ts","../src/combine-codec.ts","../src/fix-codec.ts","../src/map-codec.ts","../src/reverse-codec.ts"],"names":[],"mappings":"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","sourcesContent":["import { CodecData } from './codec';\n\n/**\n * Asserts that a given byte array is not empty.\n */\nexport function assertByteArrayIsNotEmptyForCodec(codecDescription: string, bytes: Uint8Array, offset = 0) {\n    if (bytes.length - offset <= 0) {\n        // TODO: Coded error.\n        throw new Error(`Codec [${codecDescription}] cannot decode empty byte arrays.`);\n    }\n}\n\n/**\n * Asserts that a given byte array has enough bytes to decode.\n */\nexport function assertByteArrayHasEnoughBytesForCodec(\n    codecDescription: string,\n    expected: number,\n    bytes: Uint8Array,\n    offset = 0\n) {\n    const bytesLength = bytes.length - offset;\n    if (bytesLength < expected) {\n        // TODO: Coded error.\n        throw new Error(`Codec [${codecDescription}] expected ${expected} bytes, got ${bytesLength}.`);\n    }\n}\n\n/**\n * Asserts that a given codec is fixed-size codec.\n */\nexport function assertFixedSizeCodec(\n    data: Pick<CodecData, 'fixedSize'>,\n    message?: string\n): asserts data is { fixedSize: number } {\n    if (data.fixedSize === null) {\n        // TODO: Coded error.\n        throw new Error(message ?? 'Expected a fixed-size codec, got a variable-size one.');\n    }\n}\n","/**\n * Concatenates an array of `Uint8Array`s into a single `Uint8Array`.\n * Reuses the original byte array when applicable.\n */\nexport const mergeBytes = (byteArrays: Uint8Array[]): Uint8Array => {\n    const nonEmptyByteArrays = byteArrays.filter(arr => arr.length);\n    if (nonEmptyByteArrays.length === 0) {\n        return byteArrays.length ? byteArrays[0] : new Uint8Array();\n    }\n\n    if (nonEmptyByteArrays.length === 1) {\n        return nonEmptyByteArrays[0];\n    }\n\n    const totalLength = nonEmptyByteArrays.reduce((total, arr) => total + arr.length, 0);\n    const result = new Uint8Array(totalLength);\n    let offset = 0;\n    nonEmptyByteArrays.forEach(arr => {\n        result.set(arr, offset);\n        offset += arr.length;\n    });\n    return result;\n};\n\n/**\n * Pads a `Uint8Array` with zeroes to the specified length.\n * If the array is longer than the specified length, it is returned as-is.\n */\nexport const padBytes = (bytes: Uint8Array, length: number): Uint8Array => {\n    if (bytes.length >= length) return bytes;\n    const paddedBytes = new Uint8Array(length).fill(0);\n    paddedBytes.set(bytes);\n    return paddedBytes;\n};\n\n/**\n * Fixes a `Uint8Array` to the specified length.\n * If the array is longer than the specified length, it is truncated.\n * If the array is shorter than the specified length, it is padded with zeroes.\n */\nexport const fixBytes = (bytes: Uint8Array, length: number): Uint8Array =>\n    padBytes(bytes.length <= length ? bytes : bytes.slice(0, length), length);\n","import { Codec, Decoder, Encoder } from './codec';\n\n/**\n * Combines an encoder and a decoder into a codec.\n * The encoder and decoder must have the same fixed size, max size and description.\n * If a description is provided, it will override the encoder and decoder descriptions.\n */\nexport function combineCodec<From, To extends From = From>(\n    encoder: Encoder<From>,\n    decoder: Decoder<To>,\n    description?: string\n): Codec<From, To> {\n    if (encoder.fixedSize !== decoder.fixedSize) {\n        // TODO: Coded error.\n        throw new Error(\n            `Encoder and decoder must have the same fixed size, got [${encoder.fixedSize}] and [${decoder.fixedSize}].`\n        );\n    }\n\n    if (encoder.maxSize !== decoder.maxSize) {\n        // TODO: Coded error.\n        throw new Error(\n            `Encoder and decoder must have the same max size, got [${encoder.maxSize}] and [${decoder.maxSize}].`\n        );\n    }\n\n    if (description === undefined && encoder.description !== decoder.description) {\n        // TODO: Coded error.\n        throw new Error(\n            `Encoder and decoder must have the same description, got [${encoder.description}] and [${decoder.description}]. ` +\n                `Pass a custom description as a third argument if you want to override the description and bypass this error.`\n        );\n    }\n\n    return {\n        decode: decoder.decode,\n        description: description ?? encoder.description,\n        encode: encoder.encode,\n        fixedSize: encoder.fixedSize,\n        maxSize: encoder.maxSize,\n    };\n}\n","import { assertByteArrayHasEnoughBytesForCodec } from './assertions';\nimport { fixBytes } from './bytes';\nimport { Codec, CodecData, Decoder, Encoder } from './codec';\nimport { combineCodec } from './combine-codec';\n\nfunction fixCodecHelper(data: CodecData, fixedBytes: number, description?: string): CodecData {\n    return {\n        description: description ?? `fixed(${fixedBytes}, ${data.description})`,\n        fixedSize: fixedBytes,\n        maxSize: fixedBytes,\n    };\n}\n\n/**\n * Creates a fixed-size encoder from a given encoder.\n *\n * @param encoder - The encoder to wrap into a fixed-size encoder.\n * @param fixedBytes - The fixed number of bytes to write.\n * @param description - A custom description for the encoder.\n */\nexport function fixEncoder<T>(encoder: Encoder<T>, fixedBytes: number, description?: string): Encoder<T> {\n    return {\n        ...fixCodecHelper(encoder, fixedBytes, description),\n        encode: (value: T) => fixBytes(encoder.encode(value), fixedBytes),\n    };\n}\n\n/**\n * Creates a fixed-size decoder from a given decoder.\n *\n * @param decoder - The decoder to wrap into a fixed-size decoder.\n * @param fixedBytes - The fixed number of bytes to read.\n * @param description - A custom description for the decoder.\n */\nexport function fixDecoder<T>(decoder: Decoder<T>, fixedBytes: number, description?: string): Decoder<T> {\n    return {\n        ...fixCodecHelper(decoder, fixedBytes, description),\n        decode: (bytes: Uint8Array, offset = 0) => {\n            assertByteArrayHasEnoughBytesForCodec('fixCodec', fixedBytes, bytes, offset);\n            // Slice the byte array to the fixed size if necessary.\n            if (offset > 0 || bytes.length > fixedBytes) {\n                bytes = bytes.slice(offset, offset + fixedBytes);\n            }\n            // If the nested decoder is fixed-size, pad and truncate the byte array accordingly.\n            if (decoder.fixedSize !== null) {\n                bytes = fixBytes(bytes, decoder.fixedSize);\n            }\n            // Decode the value using the nested decoder.\n            const [value] = decoder.decode(bytes, 0);\n            return [value, offset + fixedBytes];\n        },\n    };\n}\n\n/**\n * Creates a fixed-size codec from a given codec.\n *\n * @param codec - The codec to wrap into a fixed-size codec.\n * @param fixedBytes - The fixed number of bytes to read/write.\n * @param description - A custom description for the codec.\n */\nexport function fixCodec<T, U extends T = T>(\n    codec: Codec<T, U>,\n    fixedBytes: number,\n    description?: string\n): Codec<T, U> {\n    return combineCodec(fixEncoder(codec, fixedBytes, description), fixDecoder(codec, fixedBytes, description));\n}\n","import { Codec, Decoder, Encoder } from './codec';\n\n/**\n * Converts an encoder A to a encoder B by mapping their values.\n */\nexport function mapEncoder<T, U>(encoder: Encoder<T>, unmap: (value: U) => T): Encoder<U> {\n    return {\n        description: encoder.description,\n        encode: (value: U) => encoder.encode(unmap(value)),\n        fixedSize: encoder.fixedSize,\n        maxSize: encoder.maxSize,\n    };\n}\n\n/**\n * Converts an decoder A to a decoder B by mapping their values.\n */\nexport function mapDecoder<T, U>(\n    decoder: Decoder<T>,\n    map: (value: T, bytes: Uint8Array, offset: number) => U\n): Decoder<U> {\n    return {\n        decode: (bytes: Uint8Array, offset = 0) => {\n            const [value, length] = decoder.decode(bytes, offset);\n            return [map(value, bytes, offset), length];\n        },\n        description: decoder.description,\n        fixedSize: decoder.fixedSize,\n        maxSize: decoder.maxSize,\n    };\n}\n\n/**\n * Converts a codec A to a codec B by mapping their values.\n */\nexport function mapCodec<NewFrom, OldFrom, To extends NewFrom & OldFrom>(\n    codec: Codec<OldFrom, To>,\n    unmap: (value: NewFrom) => OldFrom\n): Codec<NewFrom, To>;\nexport function mapCodec<NewFrom, OldFrom, NewTo extends NewFrom = NewFrom, OldTo extends OldFrom = OldFrom>(\n    codec: Codec<OldFrom, OldTo>,\n    unmap: (value: NewFrom) => OldFrom,\n    map: (value: OldTo, bytes: Uint8Array, offset: number) => NewTo\n): Codec<NewFrom, NewTo>;\nexport function mapCodec<NewFrom, OldFrom, NewTo extends NewFrom = NewFrom, OldTo extends OldFrom = OldFrom>(\n    codec: Codec<OldFrom, OldTo>,\n    unmap: (value: NewFrom) => OldFrom,\n    map?: (value: OldTo, bytes: Uint8Array, offset: number) => NewTo\n): Codec<NewFrom, NewTo> {\n    return {\n        decode: map ? mapDecoder(codec, map).decode : (codec.decode as unknown as Decoder<NewTo>['decode']),\n        description: codec.description,\n        encode: mapEncoder(codec, unmap).encode,\n        fixedSize: codec.fixedSize,\n        maxSize: codec.maxSize,\n    };\n}\n","import { assertFixedSizeCodec } from './assertions';\nimport { mergeBytes } from './bytes';\nimport { Codec, Decoder, Encoder } from './codec';\nimport { combineCodec } from './combine-codec';\n\n/**\n * Reverses the bytes of a fixed-size encoder.\n */\nexport function reverseEncoder<T>(encoder: Encoder<T>): Encoder<T> {\n    assertFixedSizeCodec(encoder, 'Cannot reverse a codec of variable size.');\n    return {\n        ...encoder,\n        encode: (value: T) => encoder.encode(value).reverse(),\n    };\n}\n\n/**\n * Reverses the bytes of a fixed-size decoder.\n */\nexport function reverseDecoder<T>(decoder: Decoder<T>): Decoder<T> {\n    assertFixedSizeCodec(decoder, 'Cannot reverse a codec of variable size.');\n    return {\n        ...decoder,\n        decode: (bytes: Uint8Array, offset = 0) => {\n            const reverseEnd = offset + decoder.fixedSize;\n            if (offset === 0 && bytes.length === reverseEnd) {\n                return decoder.decode(bytes.reverse(), offset);\n            }\n            const newBytes = mergeBytes([\n                ...(offset === 0 ? [] : [bytes.slice(0, offset)]),\n                bytes.slice(offset, reverseEnd).reverse(),\n                ...(bytes.length === reverseEnd ? [] : [bytes.slice(reverseEnd)]),\n            ]);\n            return decoder.decode(newBytes, offset);\n        },\n    };\n}\n\n/**\n * Reverses the bytes of a fixed-size codec.\n */\nexport function reverseCodec<T, U extends T = T>(codec: Codec<T, U>): Codec<T, U> {\n    return combineCodec(reverseEncoder(codec), reverseDecoder(codec));\n}\n"]}
