### Install and Build with Webpack Source: https://github.com/msgpack/msgpack-javascript/blob/main/example/webpack-example/README.md Install dependencies and build the project using webpack. Check the output size in the dist directory. ```shell npm install npx webpack ls -lh dist/ ``` -------------------------------- ### Install @msgpack/msgpack Source: https://context7.com/msgpack/msgpack-javascript/llms.txt Install the MessagePack library using npm. ```bash npm install @msgpack/msgpack ``` -------------------------------- ### Decode Multi Stream Example Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Process an unlimited stream of MessagePack-encoded items, emitting each decoded item individually. This is suitable for continuous data streams. ```typescript import { decodeMultiStream } from "@msgpack/msgpack"; const stream: AsyncIterator; // in an async function: for await (const item of decodeMultiStream(stream)) { console.log(item); } ``` -------------------------------- ### Encode and Decode Object with MessagePack Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Demonstrates basic usage of encoding a JavaScript object into MessagePack format and then decoding it back. Ensure `@msgpack/msgpack` is installed and imported. ```typescript import { deepStrictEqual } from "assert"; import { encode, decode } from "@msgpack/msgpack"; const object = { nil: null, integer: 1, float: Math.PI, string: "Hello, world!", binary: Uint8Array.from([1, 2, 3]), array: [10, 20, 30], map: { foo: "bar" }, timestampExt: new Date(), }; const encoded: Uint8Array = encode(object); deepStrictEqual(decode(encoded), object); ``` -------------------------------- ### Decode Array Stream Example Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Iterate over an asynchronous stream of MessagePack-encoded items that are known to be in an array. This is useful for processing large arrays efficiently. ```typescript import { decodeArrayStream } from "@msgpack/msgpack"; const stream: AsyncIterator; // in an async function: for await (const item of decodeArrayStream(stream)) { console.log(item); } ``` -------------------------------- ### Read Binary Data Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads a specified number of bytes from the buffer and returns them as a Uint8Array. It correctly calculates the starting position within the underlying ArrayBuffer. ```typescript readBinary(size: number): Uint8Array { const start = this.view.byteOffset + this.pos; this.pos += size; return new Uint8Array(this.view.buffer, start, size); } ``` -------------------------------- ### Encode and Decode with @msgpack/msgpack Encoder/Decoder Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Illustrates encoding and decoding using pre-instantiated encoder and decoder objects from @msgpack/msgpack. This can be more efficient for repeated operations. ```javascript buf = /* @msgpack/msgpack */ encoder.encode(obj); obj = /* @msgpack/msgpack */ decoder.decode(buf); ``` -------------------------------- ### Publish Package Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Executes the task to publish the MessagePack library. This command is typically run after version bumping and testing. ```bash make publish ``` -------------------------------- ### Run Tests Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Executes the test suite for the MessagePack library. This is a standard command for verifying library functionality. ```bash npm run test ``` -------------------------------- ### Encode and Decode with msgpack-lite Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Demonstrates basic encoding and decoding operations using the msgpack-lite library. This is useful for comparing performance with other serialization methods. ```javascript buf = require("msgpack-lite").encode(obj); obj = require("msgpack-lite").decode(buf); ``` -------------------------------- ### BigInt Handling with ExtensionCodec Source: https://context7.com/msgpack/msgpack-javascript/llms.txt Demonstrates two methods for handling BigInt values: using `useBigInt64: true` for fixed 8-byte encoding, or registering a custom ExtensionCodec for arbitrary-precision support via string fallback. ```typescript import { encode, decode, ExtensionCodec, DecodeError } from "@msgpack/msgpack"; // Option 1: useBigInt64 — simple, fixed 8-byte encoding const enc1 = encode({ n: 9007199254740993n }, { useBigInt64: true }); const dec1 = decode(enc1, { useBigInt64: true }) as { n: bigint }; console.log(dec1.n); // 9007199254740993n // Option 2: Custom ExtensionCodec — arbitrary precision via string fallback const BIGINT_EXT_TYPE = 0; const bigIntCodec = new ExtensionCodec(); bigIntCodec.register({ type: BIGINT_EXT_TYPE, encode(input: unknown): Uint8Array | null { if (typeof input !== "bigint") return null; // Fits in a safe integer? Store as number for space efficiency if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { return encode(Number(input)); } return encode(String(input)); // store as decimal string for large values }, decode(data: Uint8Array): bigint { const val = decode(data); if (typeof val === "number" || typeof val === "string") { return BigInt(val); } throw new DecodeError(`Unexpected BigInt source type: ${typeof val}`); }, }); const huge = BigInt("123456789012345678901234567890"); const enc2 = encode(huge, { extensionCodec: bigIntCodec }); const dec2 = decode(enc2, { extensionCodec: bigIntCodec }) as bigint; console.log(dec2 === huge); // true ``` -------------------------------- ### Run All Tests Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Runs tests across multiple Node.js versions and browsers. This command is used for comprehensive testing before releases. ```bash make test-all ``` -------------------------------- ### Fetch and Decode MsgPack Data Source: https://github.com/msgpack/msgpack-javascript/blob/main/example/fetch-example.html Fetches data from a URL, checks the content type, and decodes it as MsgPack using decodeAsync. Ensure the server responds with 'application/x-msgpack' content type. ```javascript const MSGPACK_TYPE = "application/x-msgpack"; const url = "http://127.0.0.1:8080/"; (async () => { // decode() { const response = await fetch(url); const contentType = response.headers.get("content-type"); if (contentType && contentType.startsWith(MSGPACK_TYPE) && response.body != null) { const object = await MessagePack.decodeAsync(response.body); console.log("decode:", object); } else { console.error("Something is wrong!"); } // decodeAsync() { const response = await fetch(url); const contentType = response.headers.get("content-type"); if (contentType && contentType.startsWith(MSGPACK_TYPE) && response.body != null) { const object = MessagePack.decode(await response.arrayBuffer()); console.log("decodeAsync:", object); } else { console.error("Something is wrong!"); } })() ``` -------------------------------- ### Load MessagePack via CDN Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Includes the MessagePack library from a CDN using a script tag. This makes the MessagePack module available globally. ```html ``` -------------------------------- ### Encoder and Decoder Instances Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Provides `Encoder` and `Decoder` classes for performance gains by reusing instances, which can be faster than the standalone `encode` and `decode` functions. ```APIDOC ## Reusing Encoder and Decoder instances ### Description The `Encoder` and `Decoder` classes allow for performance optimization by reusing instances across multiple encoding and decoding operations. Benchmarks suggest that reusing an `Encoder` can be about 20% faster than the `encode()` function, and reusing a `Decoder` can be about 2% faster than the `decode()` function. ### Usage Instantiate `Encoder` and `Decoder` once and use them for multiple operations. They accept the same options as their respective standalone functions (`encode` and `decode`). ### Example Usage ```typescript import { deepStrictEqual } from "assert"; import { Encoder, Decoder } from "@msgpack/msgpack"; const encoder = new Encoder(); const decoder = new Decoder(); const object = { key: "value" }; const encoded: Uint8Array = encoder.encode(object); deepStrictEqual(decoder.decode(encoded), object); ``` ### Options `Encoder` and `Decoder` instances accept the same options as the `encode()` and `decode()` functions, respectively. ``` -------------------------------- ### Update Dependencies Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Runs a script to update the project's dependencies. This is a maintenance task to keep the project up-to-date. ```bash npm run update-dependencies ``` -------------------------------- ### Edit Changelog Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Opens the changelog file for editing. This is part of the release process to document changes. ```bash code CHANGELOG.md ``` -------------------------------- ### Encode and Decode with @msgpack/msgpack Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Shows how to encode and decode data using the @msgpack/msgpack library. This is the primary library for MessagePack in JavaScript. ```javascript buf = require("@msgpack/msgpack").encode(obj); obj = require("@msgpack/msgpack").decode(buf); ``` -------------------------------- ### Decoding Logic for MsgPack Types Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This snippet demonstrates a switch-case-like structure for dispatching decoding based on the type byte. It handles unsigned and signed integers, extensions, strings, arrays, and maps. ```javascript } else if (type === 0xcd) { // uint 16 return this.nextU16(); } else if (type === 0xce) { // uint 32 return this.nextU32(); } else if (type === 0xcf) { // uint 64 return this.nextU64(); } else if (type === 0xd0) { // int 8 return this.nextI8(); } else if (type === 0xd1) { // int 16 return this.nextI16(); } else if (type === 0xd2) { // int 32 return this.nextI32(); } else if (type === 0xd3) { // int 64 return this.nextI64(); } else if (type === 0xd4) { // fixext 1 return this.decodeExtension(1); } else if (type === 0xd5) { // fixext 2 return this.decodeExtension(2); } else if (type === 0xd6) { // fixext 4 return this.decodeExtension(4); } else if (type === 0xd7) { // fixext 8 return this.decodeExtension(8); } else if (type === 0xd8) { // fixext 16 return this.decodeExtension(16); } else if (type === 0xd9) { // str 8 const length = this.nextU8(); return this.decodeUtf8String(length); } else if (type === 0xda) { // str 16 const length = this.nextU16(); return this.decodeUtf8String(length); } else if (type === 0xdb) { // str 32 const length = this.nextU32(); return this.decodeUtf8String(length); } else if (type === 0xdc) { // array 16 const size = this.nextU16(); return this.decodeArray(size); } else if (type === 0xdd) { // array 32 const size = this.nextU32(); return this.decodeArray(size); } else if (type === 0xde) { // map 16 const size = this.nextU16(); return this.decodeMap(size); } else if (type === 0xdf) { // map 32 const size = this.nextU32(); return this.decodeMap(size); } else if (type === 0xc7) { // ext 8 } else { throw new Error(`Unrecognized type byte: ${prettyByte(type)}`); } ``` -------------------------------- ### Initialize DecoderByType with Table Dispatching Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This code initializes a static `decoderByType` array within the `Decoder` class. It maps MessagePack data types to their corresponding decoding methods, optimizing the decoding process by using a lookup table instead of conditional checks. ```typescript static readonly decoderByType: ReadonlyArray = (function initializeDecoderByType() { const map: Array = []; for (let t = 0; t < 0x80; t++) { map[t] = Decoder.prototype.decodePositiveFixint; } for (let t = 0x80; t < 0x90; t++) { map[t] = Decoder.prototype.decodeFixmap; } for (let t = 0x90; t < 0xa0; t++) { map[t] = Decoder.prototype.decodeFixarray; } for (let t = 0xa0; t < 0xc0; t++) { map[t] = Decoder.prototype.decodeFixstr; } map[0xc0] = Decoder.prototype.decodeNil; map[0xc1] = Decoder.prototype.decodeNeverUsed; map[0xc2] = Decoder.prototype.decodeFalse; map[0xc3] = Decoder.prototype.decodeTrue; map[0xc4] = Decoder.prototype.decodeBin8; map[0xc5] = Decoder.prototype.decodeBin16; map[0xc6] = Decoder.prototype.decodeBin32; map[0xc7] = Decoder.prototype.decodeExt8; map[0xc8] = Decoder.prototype.decodeExt16; map[0xc9] = Decoder.prototype.decodeExt32; map[0xca] = Decoder.prototype.decodeFloat32; map[0xcb] = Decoder.prototype.decodeFloat64; map[0xcc] = Decoder.prototype.decodeUint8; map[0xcd] = Decoder.prototype.decodeUint16; map[0xce] = Decoder.prototype.decodeUint32; map[0xcf] = Decoder.prototype.decodeUint64; map[0xd0] = Decoder.prototype.decodeInt8; map[0xd1] = Decoder.prototype.decodeInt16; map[0xd2] = Decoder.prototype.decodeInt32; map[0xd3] = Decoder.prototype.decodeInt64; map[0xd4] = Decoder.prototype.decodeFixext1; map[0xd5] = Decoder.prototype.decodeFixext2; map[0xd6] = Decoder.prototype.decodeFixext4; map[0xd7] = Decoder.prototype.decodeFixext8; map[0xd8] = Decoder.prototype.decodeFixext16; map[0xd9] = Decoder.prototype.decodeStr8; map[0xda] = Decoder.prototype.decodeStr16; map[0xdb] = Decoder.prototype.decodeStr32; map[0xdc] = Decoder.prototype.decodeArray16; map[0xdd] = Decoder.prototype.decodeArray32; map[0xde] = Decoder.prototype.decodeMap16; map[0xdf] = Decoder.prototype.decodeMap32; for (let t = 0xe0; t < 0x100; t++) { map[t] = Decoder.prototype.decodeNegativeFixint; } return map; })(); ``` -------------------------------- ### Decoding Methods Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This section outlines the various methods used to decode specific MessagePack types. Each method corresponds to a particular MessagePack format byte. ```APIDOC ## Decoding Methods This section details the various methods used to decode specific MessagePack types. Each method corresponds to a particular MessagePack format byte. ### decodePositiveFixint **Description**: Decodes a positive fixint. **Method**: Internal **Parameters**: - type (number) - The type byte representing a positive fixint. ### decodeFixmap **Description**: Decodes a fixmap (fixed-length map). **Method**: Internal **Parameters**: - type (number) - The type byte representing a fixmap. ### decodeFixarray **Description**: Decodes a fixarray (fixed-length array). **Method**: Internal **Parameters**: - type (number) - The type byte representing a fixarray. ### decodeFixstr **Description**: Decodes a fixstr (fixed-length string). **Method**: Internal **Parameters**: - type (number) - The type byte representing a fixstr. ### decodeNil **Description**: Decodes a nil value. **Method**: Internal ### decodeNeverUsed **Description**: Handles the never-used MessagePack type byte. **Method**: Internal **Parameters**: - type (number) - The type byte that is never used. ### decodeFalse **Description**: Decodes a boolean false value. **Method**: Internal ### decodeTrue **Description**: Decodes a boolean true value. **Method**: Internal ### decodeBin8 **Description**: Decodes a binary string of 8-bit length. **Method**: Internal ### decodeBin16 **Description**: Decodes a binary string of 16-bit length. **Method**: Internal ### decodeBin32 **Description**: Decodes a binary string of 32-bit length. **Method**: Internal ### decodeExt8 **Description**: Decodes an extension type with 8-bit length. **Method**: Internal ### decodeExt16 **Description**: Decodes an extension type with 16-bit length. **Method**: Internal ### decodeExt32 **Description**: Decodes an extension type with 32-bit length. **Method**: Internal ### decodeFloat32 **Description**: Decodes a 32-bit floating-point number. **Method**: Internal ### decodeFloat64 **Description**: Decodes a 64-bit floating-point number. **Method**: Internal ### decodeUint8 **Description**: Decodes an unsigned 8-bit integer. **Method**: Internal ### decodeUint16 **Description**: Decodes an unsigned 16-bit integer. **Method**: Internal ### decodeUint32 **Description**: Decodes an unsigned 32-bit integer. **Method**: Internal ### decodeUint64 **Description**: Decodes an unsigned 64-bit integer. **Method**: Internal ### decodeInt8 **Description**: Decodes a signed 8-bit integer. **Method**: Internal ### decodeInt16 **Description**: Decodes a signed 16-bit integer. **Method**: Internal ### decodeInt32 **Description**: Decodes a signed 32-bit integer. **Method**: Internal ### decodeInt64 **Description**: Decodes a signed 64-bit integer. **Method**: Internal **Parameters**: - b1 (byte) - First byte of the 64-bit integer. - b2 (byte) - Second byte of the 64-bit integer. - b3 (byte) - Third byte of the 64-bit integer. - b4 (byte) - Fourth byte of the 64-bit integer. - b5 (byte) - Fifth byte of the 64-bit integer. - b6 (byte) - Sixth byte of the 64-bit integer. - b7 (byte) - Seventh byte of the 64-bit integer. - b8 (byte) - Eighth byte of the 64-bit integer. ### decodeFixext1 **Description**: Decodes a fixed-length extension type of 1 byte. **Method**: Internal ### decodeFixext2 **Description**: Decodes a fixed-length extension type of 2 bytes. **Method**: Internal ### decodeFixext4 **Description**: Decodes a fixed-length extension type of 4 bytes. **Method**: Internal ``` -------------------------------- ### Working with Raw/Unknown Extension Types using ExtData Source: https://context7.com/msgpack/msgpack-javascript/llms.txt ExtData serves as a container for raw or unknown extension types during decoding, and as a pass-through for encoding raw extension bytes. Construct ExtData directly to write raw extension bytes. ```typescript import { encode, decode, ExtData } from "@msgpack/msgpack"; // When decoding an unknown extension type, you get an ExtData back (no error thrown) // e.g., binary from a foreign encoder that uses ext type 42 const foreignBuffer: Uint8Array = /* ... binary from elsewhere */ new Uint8Array([0xd6, 0x2a, 0x01, 0x02, 0x03, 0x04]); // Decode without a codec for ext type 42 const result = decode(foreignBuffer); if (result instanceof ExtData) { console.log(result.type); // 42 console.log(result.data); // Uint8Array [1, 2, 3, 4] } // You can also round-trip ExtData directly const raw = new ExtData(42, Uint8Array.from([0xde, 0xad, 0xbe, 0xef])); const encoded = encode(raw); const decoded = decode(encoded); console.log(decoded instanceof ExtData); // true console.log((decoded as ExtData).type); // 42 ``` -------------------------------- ### Reading Unsigned 64-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads an unsigned 64-bit integer from the buffer. ```APIDOC ## readU64 ### Description Reads and returns an unsigned 64-bit integer from the current position. ### Method `readU64(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the unsigned 64-bit integer value. ``` -------------------------------- ### Refactor: Improve decoding of 64-bit integers Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This snippet shows the refactoring of `nextI64` to use `readU32` for reading 32-bit chunks, improving efficiency over reading individual bytes. ```javascript const high = this.readU32(); const low = this.readU32(); return high * 0x100000000 + low; } nextI64(): number { const b1 = this.readU8(); const b2 = this.readU8(); const b3 = this.readU8(); const b4 = this.readU8(); const b5 = this.readU8(); const b6 = this.readU8(); const b7 = this.readU8(); const b8 = this.readU8(); return decodeInt64(b1, b2, b3, b4, b5, b6, b7, b8); } ``` -------------------------------- ### Reading Signed 32-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads a signed 32-bit integer from the buffer. ```APIDOC ## readI32 ### Description Reads and returns a signed 32-bit integer from the current position. ### Method `readI32(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the signed 32-bit integer value. ``` -------------------------------- ### Reading Signed 16-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads a signed 16-bit integer from the buffer. ```APIDOC ## readI16 ### Description Reads and returns a signed 16-bit integer from the current position. ### Method `readI16(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the signed 16-bit integer value. ``` -------------------------------- ### Stateful Extension Encoding with Context Source: https://context7.com/msgpack/msgpack-javascript/llms.txt Use a context object to share state between extension codec callbacks during encoding and decoding, avoiding module-level globals. This is useful for object registries or crypto keys. ```typescript import { encode, decode, ExtensionCodec } from "@msgpack/msgpack"; class SerializationContext { private registry = new Map(); private objects: object[] = []; register(obj: object): number { if (!this.registry.has(obj)) { this.registry.set(obj, this.objects.length); this.objects.push(obj); } return this.registry.get(obj)!; } } class TrackedObject { constructor(public readonly id: string) {} } const extensionCodec = new ExtensionCodec(); extensionCodec.register({ type: 0, encode: (object, context): Uint8Array | null => { if (object instanceof TrackedObject) { const ref = context.register(object); return encode({ id: object.id, ref }, { extensionCodec, context }); } return null; }, decode: (data, _extType, context) => { const { id } = decode(data, { extensionCodec, context }) as { id: string; ref: number }; return new TrackedObject(id); }, }); const context = new SerializationContext(); const obj = new TrackedObject("user-42"); const encoded = encode({ item: obj }, { extensionCodec, context }); const decoded = decode(encoded, { extensionCodec, context }) as { item: TrackedObject }; console.log(decoded.item instanceof TrackedObject); // true console.log(decoded.item.id); // "user-42" ``` -------------------------------- ### Reading Binary Data Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Helper method to read binary data of a specified size. ```APIDOC ## readBinary ### Description Reads a specified number of bytes from the buffer as a Uint8Array. ### Method `readBinary(size: number): Uint8Array` ### Endpoint N/A (Method within a class) ### Parameters * **size** (number) - The number of bytes to read. ### Response Returns a `Uint8Array` containing the binary data. ``` -------------------------------- ### decodeAsync(stream, options?) Source: https://context7.com/msgpack/msgpack-javascript/llms.txt Asynchronously decodes a MessagePack object from a ReadableStream or AsyncIterable. It begins decoding as chunks arrive, making it efficient for network responses like those from the Fetch API. ```APIDOC ## decodeAsync(stream, options?) ### Description Async decode from a ReadableStream or AsyncIterable. Accepts a WHATWG `ReadableStream` or any `AsyncIterable | BufferSource>` and returns a `Promise` of the decoded object. Designed for use with the Fetch API — it begins decoding as chunks arrive, using CPU resources more efficiently than waiting for the full download. ### Parameters #### Path Parameters None #### Query Parameters - **stream** (ReadableStream | AsyncIterable | BufferSource>) - Required - The stream or async iterable to decode from. - **options** (object) - Optional - Configuration options for decoding. ### Request Example ```typescript import { decodeAsync } from "@msgpack/msgpack"; // Typical fetch + decodeAsync usage async function fetchMsgPack(url: string): Promise { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const contentType = response.headers.get("Content-Type") ?? ""; if (!contentType.includes("application/x-msgpack")) { throw new Error("Unexpected content type: " + contentType); } if (response.body == null) { throw new Error("Empty response body"); } // Streams in as chunks — no need to await the full download return await decodeAsync(response.body); } // Works equally well with any async iterable (e.g., Node.js Readable streams) async function decodeFromAsyncIterable(iter: AsyncIterable): Promise { return await decodeAsync(iter); } ``` ### Response #### Success Response (Promise) - A Promise that resolves to the decoded object. #### Response Example ```json { "example": "Decoded object from the stream" } ``` ``` -------------------------------- ### Reuse Encoder and Decoder Instances Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Instantiate Encoder and Decoder classes for performance gains by reusing instances. This is generally faster than using the standalone encode/decode functions. ```typescript import { deepStrictEqual } from "assert"; import { Encoder, Decoder } from "@msgpack/msgpack"; const encoder = new Encoder(); const decoder = new Decoder(); const encoded: Uint8Array = encoder.encode(object); deepStrictEqual(decoder.decode(encoded), object); ``` -------------------------------- ### Reading Extensions Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Helper method to read extension data with a given type and size. ```APIDOC ## readExtension ### Description Reads extension data of a specified size and type. ### Method `readExtension(size: number)` ### Endpoint N/A (Method within a class) ### Parameters * **size** (number) - The size of the extension data in bytes. ### Response Returns the decoded extension data. ``` -------------------------------- ### Optimized MsgPack Type Dispatching Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This snippet refactors the decoding logic to use a lookup table for efficient type dispatching. It handles positive fixint, fixmap, fixarray, fixstr, nil, false, true, binary, extension, float, unsigned integers, signed integers, and more. ```typescript const type = this.readU8(); return Decoder.decoderByType[type].call(this, type); } // positive fixint (0xxx xxxx) 0x00-0x7f decodePositiveFixint(type: number) { return type; } // fixmap (1000 xxxx) 0x80-0x8f decodeFixmap(type: number) { const size = type - 0x80; return this.readMap(size); } // fixarray (1001 xxxx) 0x90-0x9f decodeFixarray(type: number) { const size = type - 0x90; return this.readArray(size); } // fixstr (101x xxxx) 0xa0-0xbf decodeFixstr(type: number) { const length = type - 0xa0; return this.readUtf8String(length); } // nil (0xc0) decodeNil() { return null; } // never used (0xc1) decodeNeverUsed(type: number) { throw new Error(`Unrecognized type byte (${prettyByte(type)}) shown at ${this.pos}`); } // false (0xc2) decodeFalse() { return false; } // true (0xc3) decodeTrue() { return true; } // bin 8 (0xc4) decodeBin8() { const size = this.readU8(); return this.readBinary(size); } // bin 16 (0xc5) decodeBin16() { const size = this.readU16(); return this.readBinary(size); } // bin 32 (0xc6) decodeBin32() { const size = this.readU32(); return this.readBinary(size); } // ext 8 (0xc7) decodeExt8() { const size = this.readU8(); return this.readExtension(size); } // ext 16 (0xc8) decodeExt16() { const size = this.readU16(); return this.readExtension(size); } // ext 32 (0xc9) decodeExt32() { const size = this.readU32(); return this.readExtension(size); } // float 32 (0xca) decodeFloat32() { return this.readF32(); } // float 64 (0xcb) decodeFloat64() { return this.readF64(); } // uint 8 (0xcc) decodeUint8() { return this.readU8(); } // uint 16 (0xcd) decodeUint16() { return this.readU16(); } // uint 32 (0xce) decodeUint32() { return this.readU32(); } // uint 64 (0xcf) decodeUint64() { return this.readU64(); } // int 8 (0xd0) decodeInt8() { return this.readI8(); } // int 16 (0xd1) decodeInt16() { return this.readI16(); } // int 32 (0xd2) decodeInt32() { return this.readI32(); } // int 64 (0xd3) decodeInt64() { const b1 = this.readU8(); const b2 = this.readU8(); const b3 = this.readU8(); const b4 = this.readU8(); const b5 = this.readU8(); const b6 = this.readU8(); const b7 = this.readU8(); const b8 = this.readU8(); return decodeInt64(b1, b2, b3, b4, b5, b6, b7, b8); } // fixext 1 (0xd4) decodeFixext1() { return this.readExtension(1); } // fixext 2 (0xd5) decodeFixext2() { return this.readExtension(2); } // fixext 4 (0xd6) decodeFixext4() { ``` -------------------------------- ### Refactor: Rename float reading methods Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This snippet demonstrates the renaming of `nextFloat32` to `readF32` and `nextFloat64` to `readF64` for consistency in naming conventions. ```javascript readF32() { const pos = this.pos; this.pos += 4; return this.view.getFloat32(pos); } readF64() { const pos = this.pos; this.pos += 8; return this.view.getFloat64(pos); } ``` -------------------------------- ### Reading Unsigned 32-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads an unsigned 32-bit integer from the buffer. ```APIDOC ## readU32 ### Description Reads and returns an unsigned 32-bit integer from the current position. ### Method `readU32(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the unsigned 32-bit integer value. ``` -------------------------------- ### Bump Version Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Increments the package version using npm. Use 'patch', 'minor', or 'major' to specify the type of version bump. ```bash npm version patch|minor|major ``` -------------------------------- ### `decode(buffer: ArrayLike | BufferSource, options?: DecoderOptions): unknown` Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Decodes a MessagePack binary buffer into a JavaScript value. It accepts an `ArrayLike` or `BufferSource` and optional `DecoderOptions`. ```APIDOC ## decode ### Description Decodes a MessagePack binary buffer into a JavaScript value. ### Signature `decode(buffer: ArrayLike | BufferSource, options?: DecoderOptions): unknown` ### Parameters - **buffer** (ArrayLike | BufferSource): The MessagePack binary data to decode. - **options** (DecoderOptions, optional): Configuration options for the decoder. ``` -------------------------------- ### Reading Unsigned 16-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads an unsigned 16-bit integer from the buffer. ```APIDOC ## readU16 ### Description Reads and returns an unsigned 16-bit integer from the current position. ### Method `readU16(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the unsigned 16-bit integer value. ``` -------------------------------- ### Reading Signed 8-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads a single signed 8-bit integer from the buffer. ```APIDOC ## readI8 ### Description Reads and returns a signed 8-bit integer from the current position. ### Method `readI8(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the signed 8-bit integer value. ``` -------------------------------- ### `encode(value, options?)` — Serialize a value to MessagePack bytes Source: https://context7.com/msgpack/msgpack-javascript/llms.txt Encodes a JavaScript/TypeScript value into MessagePack binary format. Supports various options for customization like canonical output and buffer pre-allocation. ```APIDOC ## `encode(value, options?)` — Serialize a value to MessagePack bytes ### Description Encodes any serializable JavaScript/TypeScript value into a `Uint8Array` containing the MessagePack binary representation. Throws if the value contains non-serializable types (functions, symbols) unless an `ExtensionCodec` handles them. The returned `Uint8Array` is a slice of an internal buffer — use `byteOffset` and `byteLength` when converting to a Node.js `Buffer` to avoid copying. ### Method `encode` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **value** (any serializable type) - The value to encode. - **options** (object, optional) - Configuration options for encoding. - **sortKeys** (boolean) - If true, sorts object keys for canonical output. - **forceFloat32** (boolean) - If true, forces float64 to float32. Defaults to false. - **ignoreUndefined** (boolean) - If true, drops undefined properties. Defaults to false. - **maxDepth** (number) - Maximum nesting depth. Defaults to 100. - **initialBufferSize** (number) - Pre-allocates buffer size. Defaults to 256. - **useBigInt64** (boolean) - If true, encodes BigInt as Int64/Uint64. Defaults to false. ### Request Example ```typescript import { encode } from "@msgpack/msgpack"; const payload = { id: 42, name: "Alice", active: true, score: 98.6, tags: ["admin", "user"], metadata: { createdAt: new Date("2024-01-15T10:00:00Z") }, avatar: Uint8Array.from([0xff, 0xd8, 0xff]), nothing: null, }; const encoded: Uint8Array = encode(payload); console.log(`Encoded ${encoded.byteLength} bytes`); const encodedCanonical = encode(payload, { sortKeys: true, ignoreUndefined: true, maxDepth: 50, initialBufferSize: 4096, }); ``` ### Response #### Success Response (200) - **encoded** (`Uint8Array`) - The MessagePack encoded bytes. ``` -------------------------------- ### Map Temporal Module to Timestamp Extension Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Override the default Date mapping to use the Temporal module's Instant type as the MessagePack timestamp extension. This involves registering a custom codec that encodes and decodes Instant objects to and from the timestamp format. ```typescript import { Instant } from "@std-proposal/temporal"; import { deepStrictEqual } from "assert"; import { encode, decode, ExtensionCodec, EXT_TIMESTAMP, encodeTimeSpecToTimestamp, decodeTimestampToTimeSpec, } from "@msgpack/msgpack"; // to define a custom codec const extensionCodec = new ExtensionCodec(); extensionCodec.register({ type: EXT_TIMESTAMP, // override the default behavior! encode(input: unknown): Uint8Array | null { if (input instanceof Instant) { const sec = input.seconds; const nsec = Number(input.nanoseconds - BigInt(sec) * BigInt(1e9)); return encodeTimeSpecToTimestamp({ sec, nsec }); } else { return null; } }, decode(data: Uint8Array): Instant { const timeSpec = decodeTimestampToTimeSpec(data); const sec = BigInt(timeSpec.sec); const nsec = BigInt(timeSpec.nsec); return Instant.fromEpochNanoseconds(sec * BigInt(1e9) + nsec); }, }); // to use it const instant = Instant.fromEpochMilliseconds(Date.now()); const encoded = encode(instant, { extensionCodec }); const decoded = decode(encoded, { extensionCodec }); deepStrictEqual(decoded, instant); ``` -------------------------------- ### Handle BigInt with Custom ExtensionCodec Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Define and use a custom ExtensionCodec to handle BigInt values. This codec maps BigInts to MessagePack's extension type, encoding safe integers as numbers and larger/smaller BigInts as strings to preserve precision. ```typescript import { deepStrictEqual } from "assert"; import { encode, decode, ExtensionCodec, DecodeError } from "@msgpack/msgpack"; // to define a custom codec: const BIGINT_EXT_TYPE = 0; const extensionCodec = new ExtensionCodec(); extensionCodec.register({ type: BIGINT_EXT_TYPE, encode(input: unknown): Uint8Array | null { if (typeof input === "bigint") { if (input <= Number.MAX_SAFE_INTEGER && input >= Number.MIN_SAFE_INTEGER) { return encode(Number(input)); } else { return encode(String(input)); } } else { return null; } }, decode(data: Uint8Array): bigint { const val = decode(data); if (!(typeof val === "string" || typeof val === "number")) { throw new DecodeError(`unexpected BigInt source: ${val} (${typeof val})`); } return BigInt(val); }, }); // to use it: const value = BigInt(Number.MAX_SAFE_INTEGER) + BigInt(1); const encoded = encode(value, { extensionCodec }); deepStrictEqual(decode(encoded, { extensionCodec }), value); ``` -------------------------------- ### Original Decode Logic (Pre-Table Dispatch) Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error This code block shows the original, more verbose conditional logic for decoding MessagePack data. It handles various data types by checking the byte value and calling specific decode methods. This approach was refactored to use a table dispatch mechanism for better performance. ```typescript decode() { const type = this.nextU8(); if (type >= 0xe0) { // negative fixint (111x xxxx) 0xe0 - 0xff return type - 0x100; } else if (type < 0xc0) { if (type < 0x80) { // positive fixint (0xxx xxxx) 0x00 - 0x7f return type; } else if (type < 0x90) { // fixmap (1000 xxxx) 0x80 - 0x8f const size = type - 0x80; return this.decodeMap(size); } else if (type < 0xa0) { // fixarray (1001 xxxx) 0x90 - 0x9f const size = type - 0x90; return this.decodeArray(size); } else { // fixstr (101x xxxx) 0xa0 - 0xbf const length = type - 0xa0; return this.decodeUtf8String(length); } } if (type === 0xc0) { // nil return null; } else if (type === 0xc2) { // false return false; } else if (type === 0xc3) { // true return true; } else if (type === 0xc4) { // bin 8 const size = this.nextU8(); return this.decodeBinary(size); } else if (type === 0xc5) { // bin 16 const size = this.nextU16(); return this.decodeBinary(size); } else if (type === 0xc6) { // bin 32 const size = this.nextU32(); return this.decodeBinary(size); } else if (type === 0xc7) { // ext 8 const size = this.nextU8(); return this.decodeExtension(size); } else if (type === 0xc8) { // ext 16 const size = this.nextU16(); return this.decodeExtension(size); } else if (type === 0xc9) { // ext 32 const size = this.nextU32(); return this.decodeExtension(size); } else if (type === 0xca) { // float 32 return this.nextFloat32(); } else if (type === 0xcb) { // float 64 return this.nextFloat64(); } else if (type === 0xcc) { // uint 8 return this.nextU8(); ``` -------------------------------- ### ExtensionCodec Source: https://github.com/msgpack/msgpack-javascript/blob/main/README.md Enables handling of MessagePack Extension Types by providing the `ExtensionCodec` class for registering custom encoding and decoding logic for specific types. ```APIDOC ## Extension Types ### Description The `ExtensionCodec` class allows for the handling of MessagePack Extension Types, enabling custom serialization and deserialization logic for user-defined types. You can register custom handlers for specific extension types. ### Registering Extension Types Use the `register` method of an `ExtensionCodec` instance to define how to `encode` and `decode` custom types. Each registration requires a `type` (an integer between 0-127 for custom types), an `encode` function, and a `decode` function. ### Example: Handling `Set` and `Map` This example demonstrates how to set up custom extension types for `Set` and `Map` objects: ```typescript import { encode, decode, ExtensionCodec } from "@msgpack/msgpack"; const extensionCodec = new ExtensionCodec(); // Set const SET_EXT_TYPE = 0; // Custom extension type identifier (0-127) extensionCodec.register({ type: SET_EXT_TYPE, encode: (object: unknown): Uint8Array | null => { if (object instanceof Set) { // Encode Set elements as an array return encode([...object], { extensionCodec }); } else { return null; } }, decode: (data: Uint8Array) => { // Decode the array and convert it back to a Set const array = decode(data, { extensionCodec }) as Array; return new Set(array); }, }); // Map const MAP_EXT_TYPE = 1; // Another custom extension type identifier (0-127) extensionCodec.register({ type: MAP_EXT_TYPE, encode: (object: unknown): Uint8Array | null => { if (object instanceof Map) { // Encode Map entries as an array of [key, value] pairs return encode([...object], { extensionCodec }); } else { return null; } }, decode: (data: Uint8Array) => { // Decode the array of pairs and convert it back to a Map const array = decode(data, { extensionCodec }) as Array<[unknown, unknown]>; return new Map(array); }, }); // Example usage with custom types const originalData = [new Set([1, 2]), new Map([['a', 1]])]; const encoded = encode(originalData, { extensionCodec }); const decoded = decode(encoded, { extensionCodec }); console.log(decoded); // Output: [ Set { 1, 2 }, Map { 'a' => 1 } ] ``` ### Important Notes * Ensure that your `extensionCodec` is included in any recursive `encode` and `decode` calls when dealing with nested custom types. * Custom extension types must use type identifiers in the range `[0, 127]`. The range `[-1, -128]` is reserved for MessagePack's internal use. ``` -------------------------------- ### Reading Unsigned 8-bit Integer Source: https://github.com/msgpack/msgpack-javascript/wiki/History-of-Trial-and-Error Reads a single unsigned 8-bit integer from the buffer. ```APIDOC ## readU8 ### Description Reads and returns an unsigned 8-bit integer from the current position. ### Method `readU8(): number` ### Endpoint N/A (Method within a class) ### Parameters None ### Response Returns the unsigned 8-bit integer value. ```