Skip to content

Commit a35e666

Browse files
docs: sync from coderbuzz/codex@200be78
1 parent 3d334e1 commit a35e666

2 files changed

Lines changed: 42 additions & 42 deletions

File tree

‎AI_KNOWLEDGE.md‎

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<!-- docs: sync from coderbuzz/codex@b1e2bde -->
1+
<!-- docs: sync from coderbuzz/codex@200be78 -->
22

3-
# Msgpack — AI Agent Knowledge File
3+
# Msgpack: AI Agent Knowledge File
44

55
**Package:** `@coderbuzz/msgpack`
66
**Purpose:** High-performance MessagePack serialization for TypeScript.\
@@ -16,8 +16,8 @@ functions. It maintains a single reusable internal encoder buffer to minimize
1616
allocations across encode calls.
1717

1818
```
19-
encode(value) → Uint8Array (copy of internal buffer — safe to hold)
20-
encodeUnsafe(value) → Uint8Array (view into internal buffer — zero-copy, volatile)
19+
encode(value) → Uint8Array (copy of internal buffer, safe to hold)
20+
encodeUnsafe(value) → Uint8Array (view into internal buffer, zero-copy, volatile)
2121
encodeInto(v, t, o) → number (write into pre-allocated buffer)
2222
decode(data) → unknown (deserialize MessagePack bytes)
2323
encodedSize(value) → number (pre-calculate byte count without allocating)
@@ -41,7 +41,7 @@ import { decode, encode, encodedSize, encodeInto, encodeUnsafe } from "@coderbuz
4141

4242
### `encode(value: unknown): Uint8Array`
4343

44-
Encodes any supported value to MessagePack binary. Returns a **copy** — safe
44+
Encodes any supported value to MessagePack binary. Returns a **copy**: safe
4545
to store or pass to async consumers.
4646

4747
```ts
@@ -53,12 +53,12 @@ const data = encode({ user: { name: "Alice", scores: [1, 2, 3] } });
5353

5454
**Rules:**
5555
- `null` and `undefined` both encode as nil (`0xc0`).
56-
- `Date` values encode as ISO strings via `.toISOString()` — NOT as MessagePack
56+
- `Date` values encode as ISO strings via `.toISOString()`, not as MessagePack
5757
timestamp extension.
5858
- `number` values > `Number.MAX_SAFE_INTEGER` lose precision. Use `bigint` for
5959
64-bit integers.
6060
- `-0` is encoded as float64 to preserve sign.
61-
- Objects with circular references will **stack overflow** — no detection.
61+
- Objects with circular references will **stack overflow**, with no detection.
6262

6363
---
6464

@@ -67,10 +67,10 @@ const data = encode({ user: { name: "Alice", scores: [1, 2, 3] } });
6767
Zero-copy encode. Returns a **view** (`subarray`) into the internal buffer.
6868

6969
```ts
70-
// Safe usage — immediate synchronous consumption
70+
// Safe usage: immediate synchronous consumption
7171
socket.write(encodeUnsafe(packet));
7272

73-
// UNSAFE — data will be corrupted on next encode
73+
// UNSAFE: data will be corrupted on next encode
7474
const unsafe = encodeUnsafe(data);
7575
await sendLater(unsafe); // bug!
7676
```
@@ -95,7 +95,7 @@ send(pool.subarray(0, offset));
9595

9696
**Rules:**
9797
- `offset` defaults to `0`.
98-
- No bounds checking on `target` — caller is responsible for buffer size.
98+
- No bounds checking on `target`: caller is responsible for buffer size.
9999
- Returns the number of bytes written.
100100

101101
---
@@ -119,7 +119,7 @@ const restored = decode(bytes); // => { hello: "world" }
119119

120120
### `encodedSize(value: unknown): number`
121121

122-
Pre-calculates encoded size without allocating. Exact — `encodedSize(val) === encode(val).length`.
122+
Pre-calculates encoded size without allocating. Exact: `encodedSize(val) === encode(val).length`.
123123

124124
```ts
125125
const size = encodedSize({ name: "Ken", age: 30 }); // pre-calc
@@ -232,7 +232,7 @@ new Response(encode(data), {
232232
import { encodeUnsafe } from "@coderbuzz/msgpack";
233233

234234
function send(socket: WebSocket, msg: unknown) {
235-
socket.send(encodeUnsafe(msg)); // safe — send is synchronous
235+
socket.send(encodeUnsafe(msg)); // safe: send is synchronous
236236
}
237237
```
238238

@@ -276,7 +276,7 @@ const jsonBytes = new TextEncoder().encode(JSON.stringify(data)); // ~18-20 byte
276276
| Truncated/malformed input | Out-of-bounds read (no bounds check) |
277277
| Very large array (> 2^32) | Not supported (JS limit) |
278278
| `Date` object | Encoded as ISO string, NOT timestamp ext |
279-
| `Symbol`, `Map`, `Set` | Not supported — will fail type check |
279+
| `Symbol`, `Map`, `Set` | Not supported: will fail type check |
280280

281281
---
282282

@@ -297,15 +297,15 @@ try {
297297
```
298298

299299
For decoding untrusted data, wrap in try-catch. The decoder has no bounds
300-
checking — malformed data may produce `RangeError` from `DataView` methods.
300+
checking: malformed data may produce `RangeError` from `DataView` methods.
301301

302302
---
303303

304304
## Internal Buffer Details
305305

306306
### Growth Algorithm
307307

308-
The encoder uses a single module-level reusable buffer (`buf: Uint8Array`, `dv: DataView`, `pos: number`). All encode functions share these globals — thread-safe because JS is single-threaded.
308+
The encoder uses a single module-level reusable buffer (`buf: Uint8Array`, `dv: DataView`, `pos: number`). All encode functions share these globals: thread-safe because JS is single-threaded.
309309

310310
```
311311
Initial: buf = new Uint8Array(65536) // 64 KB
@@ -317,8 +317,8 @@ The buffer never shrinks. It grows geometrically (doubles) when `pos + needed >
317317
**Lifecycle:**
318318
1. `encode()` call → `pos = 0`
319319
2. Write header + value(s) → `pos` advances
320-
3. Return `buf.slice(0, pos)` — copy for safety
321-
4. `encodeUnsafe()` returns `buf.subarray(0, pos)` — view, zero-copy
320+
3. Return `buf.slice(0, pos)`: copy for safety
321+
4. `encodeUnsafe()` returns `buf.subarray(0, pos)`: view, zero-copy
322322

323323
### Encoding Decision Tree
324324

@@ -363,7 +363,7 @@ decode byte at position
363363
└─ default → throw "MessagePack: unknown format byte 0xNN at offset N"
364364
```
365365

366-
**ASCII fast path (decode):** Strings ≤24 bytes where all bytes are ≤ 0x7F use `String.fromCharCode()` directly — avoids `TextDecoder`.
366+
**ASCII fast path (decode):** Strings ≤24 bytes where all bytes are ≤ 0x7F use `String.fromCharCode()` directly, avoiding `TextDecoder`.
367367

368368
### Performance Characteristics
369369

@@ -386,8 +386,8 @@ All benchmarks run on Apple M-series, Bun runtime. Measurements:
386386
- **Wire size** = raw byte count of encoded output (lower is better)
387387

388388
vs `@msgpack/msgpack`:
389-
- Encode: 2.04M ops/s vs 0.77M (2.7x faster) — buffer reuse + inline UTF-8
390-
- Decode: 0.90M ops/s vs 0.87M (1.04x faster) — ASCII fast path
389+
- Encode: 2.04M ops/s vs 0.77M (2.7x faster) via buffer reuse + inline UTF-8
390+
- Decode: 0.90M ops/s vs 0.87M (1.04x faster) via ASCII fast path
391391
- Wire size: identical (same MessagePack spec)
392392

393393
vs JSON:

‎README.md‎

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<!-- docs: sync from coderbuzz/codex@b1e2bde -->
1+
<!-- docs: sync from coderbuzz/codex@200be78 -->
22

3-
# Msgpack &mdash; `@coderbuzz/msgpack`
3+
# Msgpack: `@coderbuzz/msgpack`
44

55
> **High-performance MessagePack for TypeScript.** Smaller than JSON. 2x faster than `@msgpack/msgpack`. Zero unnecessary allocations.
66
> AI agents: see [AI_KNOWLEDGE.md](https://github.com/coderbuzz/msgpack/blob/main/AI_KNOWLEDGE.md) for expert context.
@@ -21,26 +21,26 @@
2121

2222
| Pain Point | @msgpack/msgpack | notepack | **@coderbuzz/msgpack** |
2323
|---|---|---|---|
24-
| Buffer reuse | Allocates new buffer per encode | Partial | **Full** — internal buffer recycles across encode calls |
25-
| Zero-copy encode | No | No | **`encodeUnsafe()`** — returns view of internal buffer, zero allocation |
26-
| Pre-allocation | No | No | **`encodeInto()`** — writes to caller-owned buffer |
27-
| Size pre-calculation | Manual estimate | Manual estimate | **`encodedSize()`** — exact byte count without allocating |
28-
| Integer encoding | Standard | Standard | **Smallest possible** — auto-selects fixint/uint8/16/32/int8/16/32/float64 |
29-
| Short ASCII strings | TextEncoder always | TextEncoder always | **Inline encoder** — avoids TextEncoder for strings <32 chars |
30-
| Decode fast path | None | None | **ASCII scan** — `String.fromCharCode()` for strings ≤24 bytes |
24+
| Buffer reuse | Allocates new buffer per encode | Partial | **Full**: internal buffer recycles across encode calls |
25+
| Zero-copy encode | No | No | **`encodeUnsafe()`**: returns view of internal buffer, zero allocation |
26+
| Pre-allocation | No | No | **`encodeInto()`**: writes to caller-owned buffer |
27+
| Size pre-calculation | Manual estimate | Manual estimate | **`encodedSize()`**: exact byte count without allocating |
28+
| Integer encoding | Standard | Standard | **Smallest possible**: auto-selects fixint/uint8/16/32/int8/16/32/float64 |
29+
| Short ASCII strings | TextEncoder always | TextEncoder always | **Inline encoder**: avoids TextEncoder for strings <32 chars |
30+
| Decode fast path | None | None | **ASCII scan**: `String.fromCharCode()` for strings ≤24 bytes |
3131
| ESM only | Yes | CJS | Yes |
3232
| Bundle size | ~10 KB gzip | ~5 KB | **<3 KB gzip** |
3333

3434
---
3535

3636
## Key Design Goals
3737

38-
- **Reusable internal buffer** — minimize GC pressure across encode calls
39-
- **Smallest possible integer encoding** — auto-selects optimal MessagePack format
40-
- **Zero-copy encode option** — `encodeUnsafe` for immediate consumption
41-
- **Pre-allocation support** — `encodeInto` writes to a caller-owned buffer
42-
- **Size pre-calculation** — `encodedSize` without allocating
43-
- **Fast paths** — inline UTF-8 encoder for short strings, ASCII decoder for small strings
38+
- **Reusable internal buffer**: minimize GC pressure across encode calls
39+
- **Smallest possible integer encoding**: auto-selects optimal MessagePack format
40+
- **Zero-copy encode option**: `encodeUnsafe` for immediate consumption
41+
- **Pre-allocation support**: `encodeInto` writes to a caller-owned buffer
42+
- **Size pre-calculation**: `encodedSize` without allocating
43+
- **Fast paths**: inline UTF-8 encoder for short strings, ASCII decoder for small strings
4444

4545
---
4646

@@ -92,7 +92,7 @@ const bytes = encode({ name: "Alice", age: 30, active: true });
9292
const value = decode(bytes);
9393
// => { name: "Alice", age: 30, active: true }
9494

95-
// Zero-copy (returns view — consume immediately)
95+
// Zero-copy (returns view, consume immediately)
9696
socket.send(encodeUnsafe({ event: "click", x: 10, y: 20 }));
9797

9898
// Pre-allocation (caller-owned buffer)
@@ -129,15 +129,15 @@ const bytes = encode({ hello: "world" });
129129
130130
### `encodeUnsafe(value: unknown): Uint8Array`
131131
132-
Zero-copy encode — returns a **view** (`subarray`) of the internal buffer. No allocation for the output.
132+
Zero-copy encode: returns a **view** (`subarray`) of the internal buffer. No allocation for the output.
133133
134134
**WARNING:** Invalidated on the next `encode*` call. Only for immediate consumption.
135135
136136
```ts
137137
// Good
138138
socket.write(encodeUnsafe(data));
139139

140-
// Bad — will be corrupted
140+
// Bad: will be corrupted
141141
const unsafe = encodeUnsafe(data);
142142
doSomethingLater(unsafe);
143143
```
@@ -250,10 +250,10 @@ function batchEncode(items: unknown[]): Uint8Array {
250250
251251
## Limitations
252252
253-
- **No MessagePack extension types** — Timestamp, custom extensions not supported. `Date` objects are ISO strings.
254-
- **No streaming/SAX decoder** — Entire message in memory.
255-
- **No bounds checking on decode** — Only decode trusted data.
256-
- **No CJS build** — ESM only. Node.js 18+ with `"type": "module"`.
253+
- **No MessagePack extension types**: Timestamp, custom extensions not supported. `Date` objects are ISO strings.
254+
- **No streaming/SAX decoder**: Entire message in memory.
255+
- **No bounds checking on decode**: Only decode trusted data.
256+
- **No CJS build**: ESM only. Node.js 18+ with `"type": "module"`.
257257
258258
---
259259

0 commit comments

Comments
 (0)