@naeemo/capnp 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":[],"sources":["../src/core/pointer.ts","../src/core/segment.ts","../src/core/message-builder.ts","../src/core/list.ts","../src/core/message-reader.ts","../src/core/union.ts"],"sourcesContent":["/**\n * Cap'n Proto 指针编解码\n * 纯 TypeScript 实现\n */\n\nexport enum PointerTag {\n STRUCT = 0,\n LIST = 1,\n FAR = 2,\n OTHER = 3,\n}\n\nexport enum ElementSize {\n VOID = 0,\n BIT = 1,\n BYTE = 2,\n TWO_BYTES = 3,\n FOUR_BYTES = 4,\n EIGHT_BYTES = 5,\n POINTER = 6,\n COMPOSITE = 7,\n}\n\nexport interface StructPointer {\n tag: PointerTag.STRUCT;\n offset: number; // 字偏移(有符号)\n dataWords: number; // 数据段字数\n pointerCount: number; // 指针段字数\n}\n\nexport interface ListPointer {\n tag: PointerTag.LIST;\n offset: number;\n elementSize: ElementSize;\n elementCount: number;\n}\n\nexport interface FarPointer {\n tag: PointerTag.FAR;\n doubleFar: boolean;\n targetSegment: number;\n targetOffset: number;\n}\n\nexport type Pointer = StructPointer | ListPointer | FarPointer | { tag: PointerTag.OTHER };\n\n/**\n * 解码指针(64位)\n */\nexport function decodePointer(ptr: bigint): Pointer {\n const tag = Number(ptr & BigInt(3)) as PointerTag;\n\n switch (tag) {\n case PointerTag.STRUCT: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const dataWords = Number((ptr >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((ptr >> BigInt(48)) & BigInt(0xffff));\n return { tag, offset: signedOffset, dataWords, pointerCount };\n }\n\n case PointerTag.LIST: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const elementSize = Number((ptr >> BigInt(32)) & BigInt(7)) as ElementSize;\n const elementCount = Number((ptr >> BigInt(35)) & BigInt(0x1fffffff));\n return { tag, offset: signedOffset, elementSize, elementCount };\n }\n\n case PointerTag.FAR: {\n const doubleFar = Boolean((ptr >> BigInt(2)) & BigInt(1));\n const targetOffset = Number((ptr >> BigInt(3)) & BigInt(0x1fffffff));\n const targetSegment = Number((ptr >> BigInt(32)) & BigInt(0xffffffff));\n return { tag, doubleFar, targetSegment, targetOffset };\n }\n\n default:\n return { tag: PointerTag.OTHER };\n }\n}\n\n/**\n * 编码 Struct 指针\n */\nexport function encodeStructPointer(\n offset: number,\n dataWords: number,\n pointerCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n (BigInt(dataWords) << BigInt(32)) |\n (BigInt(pointerCount) << BigInt(48))\n );\n}\n\n/**\n * 编码 List 指针\n */\nexport function encodeListPointer(\n offset: number,\n elementSize: ElementSize,\n elementCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n BigInt(1) | // LIST tag\n (BigInt(elementSize) << BigInt(32)) |\n (BigInt(elementCount) << BigInt(35))\n );\n}\n\n/**\n * 编码 Far 指针\n */\nexport function encodeFarPointer(segment: number, offset: number, doubleFar = false): bigint {\n const offsetBits = BigInt(offset) & BigInt(0x1fffffff);\n const segmentBits = BigInt(segment) & BigInt(0xffffffff);\n\n return (\n (segmentBits << BigInt(32)) |\n (offsetBits << BigInt(3)) |\n (doubleFar ? BigInt(1) << BigInt(2) : BigInt(0)) |\n BigInt(2)\n ); // FAR tag\n}\n","/**\n * Cap'n Proto Segment 管理\n * 纯 TypeScript 实现\n */\n\nexport const WORD_SIZE = 8;\n\nexport class Segment {\n private buffer: ArrayBuffer;\n private view: DataView;\n private _size: number; // 当前已使用字节数\n\n constructor(initialCapacity = 1024) {\n this.buffer = new ArrayBuffer(initialCapacity);\n this.view = new DataView(this.buffer);\n this._size = 0;\n }\n\n /**\n * 从现有 buffer 创建(用于读取)\n */\n static fromBuffer(buffer: ArrayBuffer): Segment {\n const seg = new Segment(0);\n seg.buffer = buffer;\n seg.view = new DataView(buffer);\n seg._size = buffer.byteLength;\n return seg;\n }\n\n /**\n * 确保容量足够\n */\n private ensureCapacity(minBytes: number): void {\n if (this.buffer.byteLength >= minBytes) return;\n\n // 双倍扩展\n let newCapacity = this.buffer.byteLength * 2;\n while (newCapacity < minBytes) {\n newCapacity *= 2;\n }\n\n const newBuffer = new ArrayBuffer(newCapacity);\n new Uint8Array(newBuffer).set(new Uint8Array(this.buffer, 0, this._size));\n this.buffer = newBuffer;\n this.view = new DataView(newBuffer);\n }\n\n /**\n * 分配空间,返回字偏移\n */\n allocate(words: number): number {\n const bytes = words * WORD_SIZE;\n const offset = this._size;\n this.ensureCapacity(offset + bytes);\n this._size = offset + bytes;\n return offset / WORD_SIZE;\n }\n\n /**\n * 获取字(64位)\n */\n getWord(wordOffset: number): bigint {\n const byteOffset = wordOffset * WORD_SIZE;\n const low = BigInt(this.view.getUint32(byteOffset, true));\n const high = BigInt(this.view.getUint32(byteOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 设置字(64位)\n */\n setWord(wordOffset: number, value: bigint): void {\n const byteOffset = wordOffset * WORD_SIZE;\n this.view.setUint32(byteOffset, Number(value & BigInt(0xffffffff)), true);\n this.view.setUint32(byteOffset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 获取原始 buffer(只读到 _size)\n */\n asUint8Array(): Uint8Array {\n return new Uint8Array(this.buffer, 0, this._size);\n }\n\n /**\n * 获取字数量\n */\n get wordCount(): number {\n return this._size / WORD_SIZE;\n }\n\n /**\n * 获取字节数量\n */\n get byteLength(): number {\n return this._size;\n }\n\n /**\n * 获取 DataView\n */\n get dataView(): DataView {\n return this.view;\n }\n}\n","/**\n * Cap'n Proto MessageBuilder\n * 纯 TypeScript 实现\n */\n\nimport { ListBuilder } from './list.js';\nimport { ElementSize, PointerTag, encodeListPointer, encodeStructPointer } from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageBuilder {\n private segment: Segment;\n private rootSet = false;\n\n constructor() {\n // 预留消息头空间(假设单段)\n this.segment = new Segment(1024);\n // 预留 8 字节给段大小\n this.segment.allocate(1);\n }\n\n /**\n * 初始化根结构\n */\n initRoot(dataWords: number, pointerCount: number): StructBuilder {\n if (this.rootSet) {\n throw new Error('Root already initialized');\n }\n\n // 分配根结构空间\n const size = dataWords + pointerCount;\n const structOffset = this.segment.allocate(size);\n\n // 在位置 0 写入根指针\n const rootPtr = encodeStructPointer(structOffset - 1, dataWords, pointerCount);\n this.segment.setWord(0, rootPtr);\n\n this.rootSet = true;\n\n return new StructBuilder(this, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 序列化为 ArrayBuffer\n */\n toArrayBuffer(): ArrayBuffer {\n const segmentData = this.segment.asUint8Array();\n const wordCount = this.segment.wordCount;\n\n // 构建消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const header = new ArrayBuffer(8);\n const headerView = new DataView(header);\n headerView.setUint32(0, 0, true); // 段数量-1 = 0(单段)\n headerView.setUint32(4, wordCount, true); // 第一段大小\n\n // 合并头和数据\n const result = new Uint8Array(8 + segmentData.byteLength);\n result.set(new Uint8Array(header), 0);\n result.set(segmentData, 8);\n\n return result.buffer;\n }\n\n /**\n * 获取段(内部使用)\n */\n getSegment(): Segment {\n return this.segment;\n }\n}\n\n/**\n * 结构构建器\n */\nexport class StructBuilder {\n constructor(\n private message: MessageBuilder,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 设置 bool 字段\n */\n setBool(bitOffset: number, value: boolean): void {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment();\n const view = segment.dataView;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n\n const current = view.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n view.setUint8(offset, newValue);\n }\n\n /**\n * 设置 int8 字段\n */\n setInt8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 int16 字段\n */\n setInt16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int32 字段\n */\n setInt32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int64 字段\n */\n setInt64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setInt32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 uint8 字段\n */\n setUint8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 uint16 字段\n */\n setUint16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint32 字段\n */\n setUint32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint64 字段\n */\n setUint64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setUint32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 float32 字段\n */\n setFloat32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 float64 字段\n */\n setFloat64(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat64(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 获取 uint16 字段(用于 UnionBuilder 读取 tag)\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment();\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 设置文本字段\n */\n setText(pointerIndex: number, value: string): void {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 编码文本\n const bytes = new TextEncoder().encode(`${value}\\0`);\n const wordCount = Math.ceil(bytes.length / WORD_SIZE);\n const listOffset = segment.allocate(wordCount);\n\n // 写入文本数据\n new Uint8Array(segment.dataView.buffer, listOffset * WORD_SIZE, bytes.length).set(bytes);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, ElementSize.BYTE, bytes.length);\n segment.setWord(ptrOffset, ptr);\n }\n\n /**\n * 初始化嵌套结构\n */\n initStruct(pointerIndex: number, dataWords: number, pointerCount: number): StructBuilder {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 分配结构空间\n const size = dataWords + pointerCount;\n const structOffset = segment.allocate(size);\n\n // 写入指针\n const ptr = encodeStructPointer(structOffset - ptrOffset - 1, dataWords, pointerCount);\n segment.setWord(ptrOffset, ptr);\n\n return new StructBuilder(this.message, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 初始化列表\n */\n initList<T>(\n pointerIndex: number,\n elementSize: ElementSize,\n elementCount: number,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListBuilder<T> {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 计算列表大小\n let elementWords = 1;\n if (elementSize === ElementSize.BYTE) elementWords = 1;\n else if (elementSize === ElementSize.TWO_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.FOUR_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.EIGHT_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.COMPOSITE && structSize) {\n elementWords = structSize.dataWords + structSize.pointerCount;\n }\n\n const totalWords = elementWords * elementCount;\n const listOffset = segment.allocate(totalWords);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, elementSize, elementCount);\n segment.setWord(ptrOffset, ptr);\n\n return new ListBuilder<T>(this.message, elementSize, elementCount, structSize, listOffset);\n }\n}\n","/**\n * Cap'n Proto List 实现\n * 纯 TypeScript\n */\n\nimport { type MessageBuilder, StructBuilder } from './message-builder.js';\nimport { type MessageReader, StructReader } from './message-reader.js';\nimport { ElementSize, type ListPointer, PointerTag, decodePointer } from './pointer.js';\nimport { type Segment, WORD_SIZE } from './segment.js';\n\n/**\n * ListReader - 读取列表\n */\nexport class ListReader<T> {\n private segment: Segment;\n private startOffset: number; // 字偏移\n\n constructor(\n private message: MessageReader,\n segmentIndex: number,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segment = message.getSegment(segmentIndex)!;\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 获取元素(基础类型)\n */\n getPrimitive(index: number): number | bigint {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const byte = this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0 ? 1 : 0;\n }\n\n case ElementSize.BYTE:\n return this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + index);\n\n case ElementSize.TWO_BYTES:\n return this.segment.dataView.getUint16(this.startOffset * WORD_SIZE + index * 2, true);\n\n case ElementSize.FOUR_BYTES:\n return this.segment.dataView.getUint32(this.startOffset * WORD_SIZE + index * 4, true);\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const low = BigInt(this.segment.dataView.getUint32(offset, true));\n const high = BigInt(this.segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素\n */\n getStruct(index: number): StructReader {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructReader(this.message, 0, offset, dataWords, pointerCount);\n }\n\n /**\n * 迭代器\n */\n *[Symbol.iterator](): Iterator<T> {\n for (let i = 0; i < this.elementCount; i++) {\n yield this.getPrimitive(i) as T;\n }\n }\n}\n\n/**\n * ListBuilder - 构建列表\n */\nexport class ListBuilder<_T> {\n private segment: Segment;\n private startOffset: number;\n\n constructor(\n private message: MessageBuilder,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segment = message.getSegment();\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 设置基础类型元素\n */\n setPrimitive(index: number, value: number | bigint): void {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const offset = this.startOffset * WORD_SIZE + byteOffset;\n const current = this.segment.dataView.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n this.segment.dataView.setUint8(offset, newValue);\n break;\n }\n\n case ElementSize.BYTE:\n this.segment.dataView.setUint8(this.startOffset * WORD_SIZE + index, Number(value));\n break;\n\n case ElementSize.TWO_BYTES:\n this.segment.dataView.setUint16(\n this.startOffset * WORD_SIZE + index * 2,\n Number(value),\n true\n );\n break;\n\n case ElementSize.FOUR_BYTES:\n this.segment.dataView.setUint32(\n this.startOffset * WORD_SIZE + index * 4,\n Number(value),\n true\n );\n break;\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const bigValue = value as bigint;\n this.segment.dataView.setUint32(offset, Number(bigValue & BigInt(0xffffffff)), true);\n this.segment.dataView.setUint32(offset + 4, Number(bigValue >> BigInt(32)), true);\n break;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素(用于修改)\n */\n getStruct(index: number): StructBuilder {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructBuilder(this.message, 0, offset, dataWords, pointerCount);\n }\n}\n","/**\n * Cap'n Proto MessageReader\n * 纯 TypeScript 实现\n */\n\nimport { ListReader } from './list.js';\nimport {\n type ElementSize,\n type ListPointer,\n PointerTag,\n type StructPointer,\n decodePointer,\n} from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageReader {\n private segments: Segment[];\n\n constructor(buffer: ArrayBuffer | Uint8Array) {\n const uint8Array = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n\n // 初始化空段数组(用于无效消息)\n this.segments = [];\n\n // 检查最小大小(至少需要8字节的头部)\n if (uint8Array.byteLength < 8) {\n // 消息太小,视为空消息\n return;\n }\n\n // 解析消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);\n const firstWordLow = view.getUint32(0, true);\n const firstWordHigh = view.getUint32(4, true);\n\n const segmentCount = (firstWordLow & 0xffffffff) + 1;\n const firstSegmentSize = firstWordHigh;\n\n let offset = 8;\n const segmentSizes: number[] = [firstSegmentSize];\n\n // 读取剩余段大小\n for (let i = 1; i < segmentCount; i++) {\n if (offset + 4 > uint8Array.byteLength) {\n // 消息过早结束,视为空消息\n this.segments = [];\n return;\n }\n segmentSizes.push(view.getUint32(offset, true));\n offset += 4;\n }\n\n // 对齐到 8 字节\n offset = (offset + 7) & ~7;\n\n // 检查是否有足够的空间容纳段表\n if (offset > uint8Array.byteLength) {\n this.segments = [];\n return;\n }\n\n // 创建段\n this.segments = [];\n for (const size of segmentSizes) {\n if (offset + size * WORD_SIZE > uint8Array.byteLength) {\n // 段数据不足,截断或视为空消息\n // 官方实现:返回已读取的部分\n break;\n }\n const segmentBuffer = uint8Array.slice(offset, offset + size * WORD_SIZE);\n this.segments.push(Segment.fromBuffer(segmentBuffer.buffer));\n offset += size * WORD_SIZE;\n }\n }\n\n /**\n * 获取根结构\n */\n getRoot(_dataWords: number, _pointerCount: number): StructReader {\n // root 指针在位置 0,解析它找到实际数据位置\n const segment = this.segments[0];\n const ptr = decodePointer(segment.getWord(0));\n\n if (ptr.tag !== PointerTag.STRUCT) {\n throw new Error('Root pointer is not a struct');\n }\n\n const structPtr = ptr as StructPointer;\n const dataOffset = 1 + structPtr.offset; // 跳过指针本身\n\n return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);\n }\n\n /**\n * 获取段\n */\n getSegment(index: number): Segment | undefined {\n return this.segments[index];\n }\n\n /**\n * 段数量\n */\n get segmentCount(): number {\n return this.segments.length;\n }\n}\n\n/**\n * 结构读取器\n */\nexport class StructReader {\n constructor(\n private message: MessageReader,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 获取 bool 字段\n */\n getBool(bitOffset: number): boolean {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const byte = segment.dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0;\n }\n\n /**\n * 获取 int8 字段\n */\n getInt8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt8(this.wordOffset * WORD_SIZE + byteOffset);\n }\n\n /**\n * 获取 int16 字段\n */\n getInt16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 int32 字段\n */\n getInt32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 int64 字段\n */\n getInt64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n const low = BigInt(segment.dataView.getUint32(offset, true));\n const high = BigInt(segment.dataView.getInt32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 uint8 字段\n */\n getUint8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset);\n }\n\n /**\n * 获取 uint16 字段\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 uint32 字段\n */\n getUint32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 uint64 字段\n */\n getUint64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n const low = BigInt(segment.dataView.getUint32(offset, true));\n const high = BigInt(segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 float32 字段\n */\n getFloat32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getFloat32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 float64 字段\n */\n getFloat64(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getFloat64(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取文本字段\n */\n getText(pointerIndex: number): string {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const ptrValue = segment.getWord(ptrOffset);\n\n // Check for null pointer (all zeros)\n if (ptrValue === 0n) return '';\n\n const ptr = decodePointer(ptrValue);\n if (ptr.tag !== PointerTag.LIST) return '';\n\n const listPtr = ptr as ListPointer;\n const targetOffset = ptrOffset + 1 + listPtr.offset;\n\n // 读取文本字节\n const bytes = new Uint8Array(\n segment.dataView.buffer,\n targetOffset * WORD_SIZE,\n listPtr.elementCount - 1\n );\n return new TextDecoder().decode(bytes);\n }\n\n /**\n * 获取嵌套结构\n */\n getStruct(\n pointerIndex: number,\n _dataWords: number,\n _pointerCount: number\n ): StructReader | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const ptrValue = segment.getWord(ptrOffset);\n\n // Check for null pointer (all zeros)\n if (ptrValue === 0n) return undefined;\n\n const ptr = decodePointer(ptrValue);\n if (ptr.tag !== PointerTag.STRUCT) return undefined;\n\n const structPtr = ptr as StructPointer;\n const targetOffset = ptrOffset + 1 + structPtr.offset;\n\n return new StructReader(\n this.message,\n this.segmentIndex,\n targetOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n /**\n * 获取列表\n */\n getList<T>(\n pointerIndex: number,\n _elementSize: ElementSize,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListReader<T> | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const ptrValue = segment.getWord(ptrOffset);\n\n // Check for null pointer (all zeros)\n if (ptrValue === 0n) return undefined;\n\n const ptr = decodePointer(ptrValue);\n if (ptr.tag !== PointerTag.LIST) return undefined;\n\n const listPtr = ptr as ListPointer;\n const targetOffset = ptrOffset + 1 + listPtr.offset;\n\n return new ListReader<T>(\n this.message,\n this.segmentIndex,\n listPtr.elementSize,\n listPtr.elementCount,\n structSize,\n targetOffset\n );\n }\n}\n","/**\n * Cap'n Proto Union 支持\n * 纯 TypeScript 实现\n */\n\nimport { MessageBuilder, type StructBuilder } from './message-builder.js';\nimport { MessageReader, type StructReader } from './message-reader.js';\nimport { ElementSize } from './pointer.js';\n\n/**\n * UnionReader - 读取 Union 的 tag 和 variant\n */\nexport class UnionReader {\n constructor(\n private struct: StructReader,\n private tagOffset: number, // tag 的字节偏移\n private variants: Map<number, string> // tag 值 -> variant 名称\n ) {}\n\n /**\n * 获取当前激活的 variant tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 获取当前激活的 variant 名称\n */\n getVariantName(): string | undefined {\n return this.variants.get(this.getTag());\n }\n\n /**\n * 检查是否是某个 variant\n */\n is(variantTag: number): boolean {\n return this.getTag() === variantTag;\n }\n}\n\n/**\n * UnionBuilder - 设置 Union 的 tag 和 variant\n */\nexport class UnionBuilder {\n constructor(\n private struct: StructBuilder,\n private tagOffset: number\n ) {}\n\n /**\n * 获取当前 tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 设置 tag\n */\n setTag(tag: number): void {\n this.struct.setUint16(this.tagOffset, tag);\n }\n\n /**\n * 初始化某个 variant(自动设置 tag)\n */\n initVariant(tag: number, initFn: () => void): void {\n this.setTag(tag);\n initFn();\n }\n}\n\n/**\n * 创建 UnionReader 的工厂函数\n */\nexport function createUnionReader(\n struct: StructReader,\n tagOffset: number,\n variants: Record<number, string>\n): UnionReader {\n return new UnionReader(\n struct,\n tagOffset,\n new Map(Object.entries(variants).map(([k, v]) => [Number(k), v]))\n );\n}\n\n/**\n * 创建 UnionBuilder 的工厂函数\n */\nexport function createUnionBuilder(struct: StructBuilder, tagOffset: number): UnionBuilder {\n return new UnionBuilder(struct, tagOffset);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../src/core/pointer.ts","../src/core/segment.ts","../src/core/message-builder.ts","../src/core/list.ts","../src/core/message-reader.ts","../src/core/union.ts"],"sourcesContent":["/**\n * Cap'n Proto 指针编解码\n * 纯 TypeScript 实现\n */\n\nexport enum PointerTag {\n STRUCT = 0,\n LIST = 1,\n FAR = 2,\n OTHER = 3,\n}\n\nexport enum ElementSize {\n VOID = 0,\n BIT = 1,\n BYTE = 2,\n TWO_BYTES = 3,\n FOUR_BYTES = 4,\n EIGHT_BYTES = 5,\n POINTER = 6,\n COMPOSITE = 7,\n INLINE_COMPOSITE = 7, // Alias for COMPOSITE\n}\n\nexport interface StructPointer {\n tag: PointerTag.STRUCT;\n offset: number; // 字偏移(有符号)\n dataWords: number; // 数据段字数\n pointerCount: number; // 指针段字数\n}\n\nexport interface ListPointer {\n tag: PointerTag.LIST;\n offset: number;\n elementSize: ElementSize;\n elementCount: number;\n}\n\nexport interface FarPointer {\n tag: PointerTag.FAR;\n doubleFar: boolean;\n targetSegment: number;\n targetOffset: number;\n}\n\nexport type Pointer = StructPointer | ListPointer | FarPointer | { tag: PointerTag.OTHER };\n\n/**\n * 解码指针(64位)\n */\nexport function decodePointer(ptr: bigint): Pointer {\n const tag = Number(ptr & BigInt(3)) as PointerTag;\n\n switch (tag) {\n case PointerTag.STRUCT: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const dataWords = Number((ptr >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((ptr >> BigInt(48)) & BigInt(0xffff));\n return { tag, offset: signedOffset, dataWords, pointerCount };\n }\n\n case PointerTag.LIST: {\n const offset = Number(ptr >> BigInt(2)) & 0x3fffffff;\n const signedOffset = offset >= 0x20000000 ? offset - 0x40000000 : offset;\n const elementSize = Number((ptr >> BigInt(32)) & BigInt(7)) as ElementSize;\n const elementCount = Number((ptr >> BigInt(35)) & BigInt(0x1fffffff));\n return { tag, offset: signedOffset, elementSize, elementCount };\n }\n\n case PointerTag.FAR: {\n const doubleFar = Boolean((ptr >> BigInt(2)) & BigInt(1));\n const targetOffset = Number((ptr >> BigInt(3)) & BigInt(0x1fffffff));\n const targetSegment = Number((ptr >> BigInt(32)) & BigInt(0xffffffff));\n return { tag, doubleFar, targetSegment, targetOffset };\n }\n\n default:\n return { tag: PointerTag.OTHER };\n }\n}\n\n/**\n * 编码 Struct 指针\n */\nexport function encodeStructPointer(\n offset: number,\n dataWords: number,\n pointerCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n (BigInt(dataWords) << BigInt(32)) |\n (BigInt(pointerCount) << BigInt(48))\n );\n}\n\n/**\n * 编码 List 指针\n */\nexport function encodeListPointer(\n offset: number,\n elementSize: ElementSize,\n elementCount: number\n): bigint {\n const offsetBits = BigInt(offset < 0 ? offset + 0x40000000 : offset) & BigInt(0x3fffffff);\n return (\n (offsetBits << BigInt(2)) |\n BigInt(1) | // LIST tag\n (BigInt(elementSize) << BigInt(32)) |\n (BigInt(elementCount) << BigInt(35))\n );\n}\n\n/**\n * 编码 Far 指针\n */\nexport function encodeFarPointer(segment: number, offset: number, doubleFar = false): bigint {\n const offsetBits = BigInt(offset) & BigInt(0x1fffffff);\n const segmentBits = BigInt(segment) & BigInt(0xffffffff);\n\n return (\n (segmentBits << BigInt(32)) |\n (offsetBits << BigInt(3)) |\n (doubleFar ? BigInt(1) << BigInt(2) : BigInt(0)) |\n BigInt(2)\n ); // FAR tag\n}\n","/**\n * Cap'n Proto Segment 管理\n * 纯 TypeScript 实现\n */\n\nexport const WORD_SIZE = 8;\n\nexport class Segment {\n private buffer: ArrayBuffer;\n private view: DataView;\n private _size: number; // 当前已使用字节数\n\n constructor(initialCapacity = 1024) {\n this.buffer = new ArrayBuffer(initialCapacity);\n this.view = new DataView(this.buffer);\n this._size = 0;\n }\n\n /**\n * 从现有 buffer 创建(用于读取)\n */\n static fromBuffer(buffer: ArrayBuffer): Segment {\n const seg = new Segment(0);\n seg.buffer = buffer;\n seg.view = new DataView(buffer);\n seg._size = buffer.byteLength;\n return seg;\n }\n\n /**\n * 确保容量足够\n */\n private ensureCapacity(minBytes: number): void {\n if (this.buffer.byteLength >= minBytes) return;\n\n // 双倍扩展\n let newCapacity = this.buffer.byteLength * 2;\n while (newCapacity < minBytes) {\n newCapacity *= 2;\n }\n\n const newBuffer = new ArrayBuffer(newCapacity);\n new Uint8Array(newBuffer).set(new Uint8Array(this.buffer, 0, this._size));\n this.buffer = newBuffer;\n this.view = new DataView(newBuffer);\n }\n\n /**\n * 分配空间,返回字偏移\n */\n allocate(words: number): number {\n const bytes = words * WORD_SIZE;\n const offset = this._size;\n this.ensureCapacity(offset + bytes);\n this._size = offset + bytes;\n return offset / WORD_SIZE;\n }\n\n /**\n * 获取字(64位)\n */\n getWord(wordOffset: number): bigint {\n const byteOffset = wordOffset * WORD_SIZE;\n const low = BigInt(this.view.getUint32(byteOffset, true));\n const high = BigInt(this.view.getUint32(byteOffset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 设置字(64位)\n */\n setWord(wordOffset: number, value: bigint): void {\n const byteOffset = wordOffset * WORD_SIZE;\n this.view.setUint32(byteOffset, Number(value & BigInt(0xffffffff)), true);\n this.view.setUint32(byteOffset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 获取原始 buffer(只读到 _size)\n */\n asUint8Array(): Uint8Array {\n return new Uint8Array(this.buffer, 0, this._size);\n }\n\n /**\n * 获取字数量\n */\n get wordCount(): number {\n return this._size / WORD_SIZE;\n }\n\n /**\n * 获取字节数量\n */\n get byteLength(): number {\n return this._size;\n }\n\n /**\n * 获取 DataView\n */\n get dataView(): DataView {\n return this.view;\n }\n}\n","/**\n * Cap'n Proto MessageBuilder\n * 纯 TypeScript 实现\n */\n\nimport { ListBuilder } from './list.js';\nimport { ElementSize, PointerTag, encodeListPointer, encodeStructPointer } from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageBuilder {\n private segment: Segment;\n private rootSet = false;\n\n constructor() {\n // 预留消息头空间(假设单段)\n this.segment = new Segment(1024);\n // 预留 8 字节给段大小\n this.segment.allocate(1);\n }\n\n /**\n * 初始化根结构\n */\n initRoot(dataWords: number, pointerCount: number): StructBuilder {\n if (this.rootSet) {\n throw new Error('Root already initialized');\n }\n\n // 分配根结构空间\n const size = dataWords + pointerCount;\n const structOffset = this.segment.allocate(size);\n\n // 在位置 0 写入根指针\n const rootPtr = encodeStructPointer(structOffset - 1, dataWords, pointerCount);\n this.segment.setWord(0, rootPtr);\n\n this.rootSet = true;\n\n return new StructBuilder(this, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 序列化为 ArrayBuffer\n */\n toArrayBuffer(): ArrayBuffer {\n const segmentData = this.segment.asUint8Array();\n const wordCount = this.segment.wordCount;\n\n // 构建消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const header = new ArrayBuffer(8);\n const headerView = new DataView(header);\n headerView.setUint32(0, 0, true); // 段数量-1 = 0(单段)\n headerView.setUint32(4, wordCount, true); // 第一段大小\n\n // 合并头和数据\n const result = new Uint8Array(8 + segmentData.byteLength);\n result.set(new Uint8Array(header), 0);\n result.set(segmentData, 8);\n\n return result.buffer;\n }\n\n /**\n * 获取段(内部使用)\n */\n getSegment(): Segment {\n return this.segment;\n }\n}\n\n/**\n * 结构构建器\n */\nexport class StructBuilder {\n constructor(\n private message: MessageBuilder,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 设置 bool 字段\n */\n setBool(bitOffset: number, value: boolean): void {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment();\n const view = segment.dataView;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n\n const current = view.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n view.setUint8(offset, newValue);\n }\n\n /**\n * 设置 int8 字段\n */\n setInt8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 int16 字段\n */\n setInt16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int32 字段\n */\n setInt32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setInt32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 int64 字段\n */\n setInt64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setInt32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 uint8 字段\n */\n setUint8(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint8(this.wordOffset * WORD_SIZE + byteOffset, value);\n }\n\n /**\n * 设置 uint16 字段\n */\n setUint16(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint16(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint32 字段\n */\n setUint32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setUint32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 uint64 字段\n */\n setUint64(byteOffset: number, value: bigint): void {\n const segment = this.message.getSegment();\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n segment.dataView.setUint32(offset, Number(value & BigInt(0xffffffff)), true);\n segment.dataView.setUint32(offset + 4, Number(value >> BigInt(32)), true);\n }\n\n /**\n * 设置 float32 字段\n */\n setFloat32(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat32(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 设置 float64 字段\n */\n setFloat64(byteOffset: number, value: number): void {\n const segment = this.message.getSegment();\n segment.dataView.setFloat64(this.wordOffset * WORD_SIZE + byteOffset, value, true);\n }\n\n /**\n * 获取 uint16 字段(用于 UnionBuilder 读取 tag)\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment();\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 设置文本字段\n */\n setText(pointerIndex: number, value: string): void {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 编码文本\n const bytes = new TextEncoder().encode(`${value}\\0`);\n const wordCount = Math.ceil(bytes.length / WORD_SIZE);\n const listOffset = segment.allocate(wordCount);\n\n // 写入文本数据\n new Uint8Array(segment.dataView.buffer, listOffset * WORD_SIZE, bytes.length).set(bytes);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, ElementSize.BYTE, bytes.length);\n segment.setWord(ptrOffset, ptr);\n }\n\n /**\n * 初始化嵌套结构\n */\n initStruct(pointerIndex: number, dataWords: number, pointerCount: number): StructBuilder {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 分配结构空间\n const size = dataWords + pointerCount;\n const structOffset = segment.allocate(size);\n\n // 写入指针\n const ptr = encodeStructPointer(structOffset - ptrOffset - 1, dataWords, pointerCount);\n segment.setWord(ptrOffset, ptr);\n\n return new StructBuilder(this.message, 0, structOffset, dataWords, pointerCount);\n }\n\n /**\n * 初始化列表\n */\n initList<T>(\n pointerIndex: number,\n elementSize: ElementSize,\n elementCount: number,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListBuilder<T> {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const segment = this.message.getSegment();\n\n // 计算列表大小\n let elementWords = 1;\n if (elementSize === ElementSize.BYTE) elementWords = 1;\n else if (elementSize === ElementSize.TWO_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.FOUR_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.EIGHT_BYTES) elementWords = 1;\n else if (elementSize === ElementSize.COMPOSITE && structSize) {\n elementWords = structSize.dataWords + structSize.pointerCount;\n }\n\n const totalWords = elementWords * elementCount;\n const listOffset = segment.allocate(totalWords);\n\n // 写入指针\n const ptr = encodeListPointer(listOffset - ptrOffset - 1, elementSize, elementCount);\n segment.setWord(ptrOffset, ptr);\n\n return new ListBuilder<T>(this.message, elementSize, elementCount, structSize, listOffset);\n }\n}\n","/**\n * Cap'n Proto List 实现\n * 纯 TypeScript\n */\n\nimport { type MessageBuilder, StructBuilder } from './message-builder.js';\nimport { type MessageReader, StructReader } from './message-reader.js';\nimport { ElementSize, type ListPointer, PointerTag, decodePointer } from './pointer.js';\nimport { type Segment, WORD_SIZE } from './segment.js';\n\n/**\n * ListReader - 读取列表\n */\nexport class ListReader<T> {\n private segment: Segment;\n private startOffset: number; // 字偏移\n private segmentIndex: number;\n\n constructor(\n private message: MessageReader,\n segmentIndex: number,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segmentIndex = segmentIndex;\n this.segment = message.getSegment(segmentIndex)!;\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 获取元素(基础类型)\n */\n getPrimitive(index: number): number | bigint {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const byte = this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0 ? 1 : 0;\n }\n\n case ElementSize.BYTE:\n return this.segment.dataView.getUint8(this.startOffset * WORD_SIZE + index);\n\n case ElementSize.TWO_BYTES:\n return this.segment.dataView.getUint16(this.startOffset * WORD_SIZE + index * 2, true);\n\n case ElementSize.FOUR_BYTES:\n return this.segment.dataView.getUint32(this.startOffset * WORD_SIZE + index * 4, true);\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const low = BigInt(this.segment.dataView.getUint32(offset, true));\n const high = BigInt(this.segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素\n */\n getStruct(index: number): StructReader {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructReader(this.message, this.segmentIndex, offset, dataWords, pointerCount);\n }\n\n /**\n * 迭代器\n */\n *[Symbol.iterator](): Iterator<T> {\n for (let i = 0; i < this.elementCount; i++) {\n yield this.getPrimitive(i) as T;\n }\n }\n}\n\n/**\n * ListBuilder - 构建列表\n */\nexport class ListBuilder<_T> {\n private segment: Segment;\n private startOffset: number;\n\n constructor(\n private message: MessageBuilder,\n private elementSize: ElementSize,\n private elementCount: number,\n private structSize: { dataWords: number; pointerCount: number } | undefined,\n wordOffset: number\n ) {\n this.segment = message.getSegment();\n this.startOffset = wordOffset;\n }\n\n /**\n * 列表长度\n */\n get length(): number {\n return this.elementCount;\n }\n\n /**\n * 设置基础类型元素\n */\n setPrimitive(index: number, value: number | bigint): void {\n if (index < 0 || index >= this.elementCount) {\n throw new RangeError('Index out of bounds');\n }\n\n switch (this.elementSize) {\n case ElementSize.BIT: {\n const byteOffset = Math.floor(index / 8);\n const bitInByte = index % 8;\n const offset = this.startOffset * WORD_SIZE + byteOffset;\n const current = this.segment.dataView.getUint8(offset);\n const newValue = value ? current | (1 << bitInByte) : current & ~(1 << bitInByte);\n this.segment.dataView.setUint8(offset, newValue);\n break;\n }\n\n case ElementSize.BYTE:\n this.segment.dataView.setUint8(this.startOffset * WORD_SIZE + index, Number(value));\n break;\n\n case ElementSize.TWO_BYTES:\n this.segment.dataView.setUint16(\n this.startOffset * WORD_SIZE + index * 2,\n Number(value),\n true\n );\n break;\n\n case ElementSize.FOUR_BYTES:\n this.segment.dataView.setUint32(\n this.startOffset * WORD_SIZE + index * 4,\n Number(value),\n true\n );\n break;\n\n case ElementSize.EIGHT_BYTES: {\n const offset = this.startOffset * WORD_SIZE + index * 8;\n const bigValue = value as bigint;\n this.segment.dataView.setUint32(offset, Number(bigValue & BigInt(0xffffffff)), true);\n this.segment.dataView.setUint32(offset + 4, Number(bigValue >> BigInt(32)), true);\n break;\n }\n\n default:\n throw new Error(`Unsupported element size: ${this.elementSize}`);\n }\n }\n\n /**\n * 获取结构元素(用于修改)\n */\n getStruct(index: number): StructBuilder {\n if (!this.structSize) {\n throw new Error('Not a struct list');\n }\n\n const { dataWords, pointerCount } = this.structSize;\n const size = dataWords + pointerCount;\n const offset = this.startOffset + index * size;\n\n return new StructBuilder(this.message, 0, offset, dataWords, pointerCount);\n }\n}\n","/**\n * Cap'n Proto MessageReader\n * 纯 TypeScript 实现\n */\n\nimport { ListReader } from './list.js';\nimport {\n ElementSize,\n type FarPointer,\n type ListPointer,\n PointerTag,\n type StructPointer,\n decodePointer,\n} from './pointer.js';\nimport { Segment, WORD_SIZE } from './segment.js';\n\nexport class MessageReader {\n private segments: Segment[];\n\n constructor(buffer: ArrayBuffer | Uint8Array) {\n const uint8Array = buffer instanceof ArrayBuffer ? new Uint8Array(buffer) : buffer;\n\n // 初始化空段数组(用于无效消息)\n this.segments = [];\n\n // 检查最小大小(至少需要8字节的头部)\n if (uint8Array.byteLength < 8) {\n // 消息太小,视为空消息\n return;\n }\n\n // 解析消息头\n // 第一个字:段数量-1(低32位)和第一段大小(高32位)\n const view = new DataView(uint8Array.buffer, uint8Array.byteOffset, uint8Array.byteLength);\n const firstWordLow = view.getUint32(0, true);\n const firstWordHigh = view.getUint32(4, true);\n\n const segmentCount = (firstWordLow & 0xffffffff) + 1;\n const firstSegmentSize = firstWordHigh;\n\n let offset = 8;\n const segmentSizes: number[] = [firstSegmentSize];\n\n // 读取剩余段大小\n for (let i = 1; i < segmentCount; i++) {\n if (offset + 4 > uint8Array.byteLength) {\n // 消息过早结束,视为空消息\n this.segments = [];\n return;\n }\n segmentSizes.push(view.getUint32(offset, true));\n offset += 4;\n }\n\n // 对齐到 8 字节\n offset = (offset + 7) & ~7;\n\n // 检查是否有足够的空间容纳段表\n if (offset > uint8Array.byteLength) {\n this.segments = [];\n return;\n }\n\n // 创建段\n this.segments = [];\n for (const size of segmentSizes) {\n if (offset + size * WORD_SIZE > uint8Array.byteLength) {\n // 段数据不足,截断或视为空消息\n // 官方实现:返回已读取的部分\n break;\n }\n const segmentBuffer = uint8Array.slice(offset, offset + size * WORD_SIZE);\n this.segments.push(Segment.fromBuffer(segmentBuffer.buffer));\n offset += size * WORD_SIZE;\n }\n }\n\n /**\n * 获取根结构\n */\n getRoot(_dataWords: number, _pointerCount: number): StructReader {\n // root 指针在位置 0,解析它找到实际数据位置\n const segment = this.segments[0];\n const ptr = decodePointer(segment.getWord(0));\n\n if (ptr.tag === PointerTag.STRUCT) {\n const structPtr = ptr as StructPointer;\n const dataOffset = 1 + structPtr.offset; // 跳过指针本身\n return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);\n }\n\n if (ptr.tag === PointerTag.FAR) {\n // Far pointer: 指向另一个 segment 中的 landing pad\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) {\n throw new Error(`Far pointer references non-existent segment ${farPtr.targetSegment}`);\n }\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 本身也是一个 far 指针\n // landing pad 位置: targetOffset 指向的位置\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) {\n throw new Error('Double-far landing pad is not a far pointer');\n }\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) {\n throw new Error(\n `Double-far references non-existent segment ${innerFarPtr.targetSegment}`\n );\n }\n // 实际的 struct 指针在 innerFarPtr.targetOffset\n const structPtr = decodePointer(\n finalSegment.getWord(innerFarPtr.targetOffset)\n ) as StructPointer;\n const dataOffset = innerFarPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n innerFarPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n // Single-far: landing pad 是实际的 struct 指针\n const structPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset)) as StructPointer;\n const dataOffset = farPtr.targetOffset + 1 + structPtr.offset;\n return new StructReader(\n this,\n farPtr.targetSegment,\n dataOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n throw new Error(`Root pointer is not a struct or far pointer: ${ptr.tag}`);\n }\n\n /**\n * 获取段\n */\n getSegment(index: number): Segment | undefined {\n return this.segments[index];\n }\n\n /**\n * 解析指针,处理 far pointer 间接寻址\n * 返回 { segmentIndex, wordOffset, pointer },其中 pointer 是实际的 struct/list 指针\n */\n resolvePointer(\n segmentIndex: number,\n wordOffset: number\n ): { segmentIndex: number; wordOffset: number; pointer: StructPointer | ListPointer } | null {\n const segment = this.getSegment(segmentIndex);\n if (!segment) return null;\n\n const ptrValue = segment.getWord(wordOffset);\n if (ptrValue === 0n) return null;\n\n const ptr = decodePointer(ptrValue);\n\n if (ptr.tag === PointerTag.STRUCT || ptr.tag === PointerTag.LIST) {\n // 直接指针,计算目标偏移\n const targetOffset = wordOffset + 1 + ptr.offset;\n return {\n segmentIndex,\n wordOffset: targetOffset,\n pointer: ptr as StructPointer | ListPointer,\n };\n }\n\n if (ptr.tag === PointerTag.FAR) {\n const farPtr = ptr as FarPointer;\n const targetSegment = this.getSegment(farPtr.targetSegment);\n if (!targetSegment) return null;\n\n if (farPtr.doubleFar) {\n // Double-far: landing pad 指向另一个 far 指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.FAR) return null;\n const innerFarPtr = landingPadPtr as FarPointer;\n const finalSegment = this.getSegment(innerFarPtr.targetSegment);\n if (!finalSegment) return null;\n const finalPtr = decodePointer(finalSegment.getWord(innerFarPtr.targetOffset));\n if (finalPtr.tag !== PointerTag.STRUCT && finalPtr.tag !== PointerTag.LIST) return null;\n const targetOffset = innerFarPtr.targetOffset + 1 + finalPtr.offset;\n return {\n segmentIndex: innerFarPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: finalPtr as StructPointer | ListPointer,\n };\n }\n // Single-far: landing pad 是实际的指针\n const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));\n if (landingPadPtr.tag !== PointerTag.STRUCT && landingPadPtr.tag !== PointerTag.LIST)\n return null;\n const targetOffset = farPtr.targetOffset + 1 + landingPadPtr.offset;\n return {\n segmentIndex: farPtr.targetSegment,\n wordOffset: targetOffset,\n pointer: landingPadPtr as StructPointer | ListPointer,\n };\n }\n\n return null;\n }\n\n /**\n * 段数量\n */\n get segmentCount(): number {\n return this.segments.length;\n }\n}\n\n/**\n * 结构读取器\n */\nexport class StructReader {\n constructor(\n private message: MessageReader,\n private segmentIndex: number,\n private wordOffset: number,\n private dataWords: number,\n private pointerCount: number\n ) {}\n\n /**\n * 获取 bool 字段\n */\n getBool(bitOffset: number): boolean {\n const byteOffset = Math.floor(bitOffset / 8);\n const bitInByte = bitOffset % 8;\n const segment = this.message.getSegment(this.segmentIndex)!;\n const byte = segment.dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset);\n return (byte & (1 << bitInByte)) !== 0;\n }\n\n /**\n * 获取 int8 字段\n */\n getInt8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt8(this.wordOffset * WORD_SIZE + byteOffset);\n }\n\n /**\n * 获取 int16 字段\n */\n getInt16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 int32 字段\n */\n getInt32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getInt32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 int64 字段\n */\n getInt64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n const low = BigInt(segment.dataView.getUint32(offset, true));\n const high = BigInt(segment.dataView.getInt32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 uint8 字段\n */\n getUint8(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint8(this.wordOffset * WORD_SIZE + byteOffset);\n }\n\n /**\n * 获取 uint16 字段\n */\n getUint16(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint16(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 uint32 字段\n */\n getUint32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getUint32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 uint64 字段\n */\n getUint64(byteOffset: number): bigint {\n const segment = this.message.getSegment(this.segmentIndex)!;\n const offset = this.wordOffset * WORD_SIZE + byteOffset;\n const low = BigInt(segment.dataView.getUint32(offset, true));\n const high = BigInt(segment.dataView.getUint32(offset + 4, true));\n return (high << BigInt(32)) | low;\n }\n\n /**\n * 获取 float32 字段\n */\n getFloat32(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getFloat32(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取 float64 字段\n */\n getFloat64(byteOffset: number): number {\n const segment = this.message.getSegment(this.segmentIndex)!;\n return segment.dataView.getFloat64(this.wordOffset * WORD_SIZE + byteOffset, true);\n }\n\n /**\n * 获取文本字段\n */\n getText(pointerIndex: number): string {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return '';\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return '';\n\n const listPtr = pointer as ListPointer;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // Text is stored as List(UInt8) with NUL terminator\n // elementCount includes the NUL terminator\n const byteLength = listPtr.elementCount > 0 ? listPtr.elementCount - 1 : 0;\n if (byteLength === 0) return '';\n\n // 读取文本字节\n const bytes = new Uint8Array(segment.dataView.buffer, wordOffset * WORD_SIZE, byteLength);\n return new TextDecoder().decode(bytes);\n }\n\n /**\n * 获取嵌套结构\n */\n getStruct(\n pointerIndex: number,\n _dataWords: number,\n _pointerCount: number\n ): StructReader | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.STRUCT) return undefined;\n\n const structPtr = pointer as StructPointer;\n\n return new StructReader(\n this.message,\n segmentIndex,\n wordOffset,\n structPtr.dataWords,\n structPtr.pointerCount\n );\n }\n\n /**\n * 获取列表\n */\n getList<T>(\n pointerIndex: number,\n _elementSize: ElementSize,\n structSize?: { dataWords: number; pointerCount: number }\n ): ListReader<T> | undefined {\n const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;\n const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);\n\n if (!resolved) return undefined;\n\n const { segmentIndex, wordOffset, pointer } = resolved;\n if (pointer.tag !== PointerTag.LIST) return undefined;\n\n const listPtr = pointer as ListPointer;\n let targetOffset = wordOffset;\n let elementCount = listPtr.elementCount;\n let actualStructSize = structSize;\n const segment = this.message.getSegment(segmentIndex)!;\n\n // For INLINE_COMPOSITE lists, read the tag word\n if (listPtr.elementSize === ElementSize.COMPOSITE) {\n const tagWord = segment.getWord(targetOffset);\n // Tag word: elementCount (32 bits) | dataWords (16 bits) | pointerCount (16 bits)\n elementCount = Number(tagWord & BigInt(0xffffffff));\n const dataWords = Number((tagWord >> BigInt(32)) & BigInt(0xffff));\n const pointerCount = Number((tagWord >> BigInt(48)) & BigInt(0xffff));\n actualStructSize = { dataWords, pointerCount };\n targetOffset += 1; // Skip tag word\n }\n\n return new ListReader<T>(\n this.message,\n segmentIndex,\n listPtr.elementSize,\n elementCount,\n actualStructSize,\n targetOffset\n );\n }\n}\n","/**\n * Cap'n Proto Union 支持\n * 纯 TypeScript 实现\n */\n\nimport { MessageBuilder, type StructBuilder } from './message-builder.js';\nimport { MessageReader, type StructReader } from './message-reader.js';\nimport { ElementSize } from './pointer.js';\n\n/**\n * UnionReader - 读取 Union 的 tag 和 variant\n */\nexport class UnionReader {\n constructor(\n private struct: StructReader,\n private tagOffset: number, // tag 的字节偏移\n private variants: Map<number, string> // tag 值 -> variant 名称\n ) {}\n\n /**\n * 获取当前激活的 variant tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 获取当前激活的 variant 名称\n */\n getVariantName(): string | undefined {\n return this.variants.get(this.getTag());\n }\n\n /**\n * 检查是否是某个 variant\n */\n is(variantTag: number): boolean {\n return this.getTag() === variantTag;\n }\n}\n\n/**\n * UnionBuilder - 设置 Union 的 tag 和 variant\n */\nexport class UnionBuilder {\n constructor(\n private struct: StructBuilder,\n private tagOffset: number\n ) {}\n\n /**\n * 获取当前 tag\n */\n getTag(): number {\n return this.struct.getUint16(this.tagOffset);\n }\n\n /**\n * 设置 tag\n */\n setTag(tag: number): void {\n this.struct.setUint16(this.tagOffset, tag);\n }\n\n /**\n * 初始化某个 variant(自动设置 tag)\n */\n initVariant(tag: number, initFn: () => void): void {\n this.setTag(tag);\n initFn();\n }\n}\n\n/**\n * 创建 UnionReader 的工厂函数\n */\nexport function createUnionReader(\n struct: StructReader,\n tagOffset: number,\n variants: Record<number, string>\n): UnionReader {\n return new UnionReader(\n struct,\n tagOffset,\n new Map(Object.entries(variants).map(([k, v]) => [Number(k), v]))\n );\n}\n\n/**\n * 创建 UnionBuilder 的工厂函数\n */\nexport function createUnionBuilder(struct: StructBuilder, tagOffset: number): UnionBuilder {\n return new UnionBuilder(struct, tagOffset);\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -19,6 +19,7 @@ let ElementSize = /* @__PURE__ */ function(ElementSize) {
19
19
  ElementSize[ElementSize["EIGHT_BYTES"] = 5] = "EIGHT_BYTES";
20
20
  ElementSize[ElementSize["POINTER"] = 6] = "POINTER";
21
21
  ElementSize[ElementSize["COMPOSITE"] = 7] = "COMPOSITE";
22
+ ElementSize[ElementSize["INLINE_COMPOSITE"] = 7] = "INLINE_COMPOSITE";
22
23
  return ElementSize;
23
24
  }({});
24
25
  /**
@@ -360,11 +361,13 @@ var StructBuilder = class StructBuilder {
360
361
  var ListReader = class {
361
362
  segment;
362
363
  startOffset;
364
+ segmentIndex;
363
365
  constructor(message, segmentIndex, elementSize, elementCount, structSize, wordOffset) {
364
366
  this.message = message;
365
367
  this.elementSize = elementSize;
366
368
  this.elementCount = elementCount;
367
369
  this.structSize = structSize;
370
+ this.segmentIndex = segmentIndex;
368
371
  this.segment = message.getSegment(segmentIndex);
369
372
  this.startOffset = wordOffset;
370
373
  }
@@ -404,7 +407,7 @@ var ListReader = class {
404
407
  const { dataWords, pointerCount } = this.structSize;
405
408
  const size = dataWords + pointerCount;
406
409
  const offset = this.startOffset + index * size;
407
- return new StructReader(this.message, 0, offset, dataWords, pointerCount);
410
+ return new StructReader(this.message, this.segmentIndex, offset, dataWords, pointerCount);
408
411
  }
409
412
  /**
410
413
  * 迭代器
@@ -525,10 +528,30 @@ var MessageReader = class {
525
528
  getRoot(_dataWords, _pointerCount) {
526
529
  const segment = this.segments[0];
527
530
  const ptr = decodePointer(segment.getWord(0));
528
- if (ptr.tag !== PointerTag.STRUCT) throw new Error("Root pointer is not a struct");
529
- const structPtr = ptr;
530
- const dataOffset = 1 + structPtr.offset;
531
- return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);
531
+ if (ptr.tag === PointerTag.STRUCT) {
532
+ const structPtr = ptr;
533
+ const dataOffset = 1 + structPtr.offset;
534
+ return new StructReader(this, 0, dataOffset, structPtr.dataWords, structPtr.pointerCount);
535
+ }
536
+ if (ptr.tag === PointerTag.FAR) {
537
+ const farPtr = ptr;
538
+ const targetSegment = this.getSegment(farPtr.targetSegment);
539
+ if (!targetSegment) throw new Error(`Far pointer references non-existent segment ${farPtr.targetSegment}`);
540
+ if (farPtr.doubleFar) {
541
+ const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));
542
+ if (landingPadPtr.tag !== PointerTag.FAR) throw new Error("Double-far landing pad is not a far pointer");
543
+ const innerFarPtr = landingPadPtr;
544
+ const finalSegment = this.getSegment(innerFarPtr.targetSegment);
545
+ if (!finalSegment) throw new Error(`Double-far references non-existent segment ${innerFarPtr.targetSegment}`);
546
+ const structPtr = decodePointer(finalSegment.getWord(innerFarPtr.targetOffset));
547
+ const dataOffset = innerFarPtr.targetOffset + 1 + structPtr.offset;
548
+ return new StructReader(this, innerFarPtr.targetSegment, dataOffset, structPtr.dataWords, structPtr.pointerCount);
549
+ }
550
+ const structPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));
551
+ const dataOffset = farPtr.targetOffset + 1 + structPtr.offset;
552
+ return new StructReader(this, farPtr.targetSegment, dataOffset, structPtr.dataWords, structPtr.pointerCount);
553
+ }
554
+ throw new Error(`Root pointer is not a struct or far pointer: ${ptr.tag}`);
532
555
  }
533
556
  /**
534
557
  * 获取段
@@ -537,6 +560,51 @@ var MessageReader = class {
537
560
  return this.segments[index];
538
561
  }
539
562
  /**
563
+ * 解析指针,处理 far pointer 间接寻址
564
+ * 返回 { segmentIndex, wordOffset, pointer },其中 pointer 是实际的 struct/list 指针
565
+ */
566
+ resolvePointer(segmentIndex, wordOffset) {
567
+ const segment = this.getSegment(segmentIndex);
568
+ if (!segment) return null;
569
+ const ptrValue = segment.getWord(wordOffset);
570
+ if (ptrValue === 0n) return null;
571
+ const ptr = decodePointer(ptrValue);
572
+ if (ptr.tag === PointerTag.STRUCT || ptr.tag === PointerTag.LIST) return {
573
+ segmentIndex,
574
+ wordOffset: wordOffset + 1 + ptr.offset,
575
+ pointer: ptr
576
+ };
577
+ if (ptr.tag === PointerTag.FAR) {
578
+ const farPtr = ptr;
579
+ const targetSegment = this.getSegment(farPtr.targetSegment);
580
+ if (!targetSegment) return null;
581
+ if (farPtr.doubleFar) {
582
+ const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));
583
+ if (landingPadPtr.tag !== PointerTag.FAR) return null;
584
+ const innerFarPtr = landingPadPtr;
585
+ const finalSegment = this.getSegment(innerFarPtr.targetSegment);
586
+ if (!finalSegment) return null;
587
+ const finalPtr = decodePointer(finalSegment.getWord(innerFarPtr.targetOffset));
588
+ if (finalPtr.tag !== PointerTag.STRUCT && finalPtr.tag !== PointerTag.LIST) return null;
589
+ const targetOffset = innerFarPtr.targetOffset + 1 + finalPtr.offset;
590
+ return {
591
+ segmentIndex: innerFarPtr.targetSegment,
592
+ wordOffset: targetOffset,
593
+ pointer: finalPtr
594
+ };
595
+ }
596
+ const landingPadPtr = decodePointer(targetSegment.getWord(farPtr.targetOffset));
597
+ if (landingPadPtr.tag !== PointerTag.STRUCT && landingPadPtr.tag !== PointerTag.LIST) return null;
598
+ const targetOffset = farPtr.targetOffset + 1 + landingPadPtr.offset;
599
+ return {
600
+ segmentIndex: farPtr.targetSegment,
601
+ wordOffset: targetOffset,
602
+ pointer: landingPadPtr
603
+ };
604
+ }
605
+ return null;
606
+ }
607
+ /**
540
608
  * 段数量
541
609
  */
542
610
  get segmentCount() {
@@ -633,14 +701,15 @@ var StructReader = class StructReader {
633
701
  */
634
702
  getText(pointerIndex) {
635
703
  const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;
636
- const segment = this.message.getSegment(this.segmentIndex);
637
- const ptrValue = segment.getWord(ptrOffset);
638
- if (ptrValue === 0n) return "";
639
- const ptr = decodePointer(ptrValue);
640
- if (ptr.tag !== PointerTag.LIST) return "";
641
- const listPtr = ptr;
642
- const targetOffset = ptrOffset + 1 + listPtr.offset;
643
- const bytes = new Uint8Array(segment.dataView.buffer, targetOffset * WORD_SIZE, listPtr.elementCount - 1);
704
+ const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);
705
+ if (!resolved) return "";
706
+ const { segmentIndex, wordOffset, pointer } = resolved;
707
+ if (pointer.tag !== PointerTag.LIST) return "";
708
+ const listPtr = pointer;
709
+ const segment = this.message.getSegment(segmentIndex);
710
+ const byteLength = listPtr.elementCount > 0 ? listPtr.elementCount - 1 : 0;
711
+ if (byteLength === 0) return "";
712
+ const bytes = new Uint8Array(segment.dataView.buffer, wordOffset * WORD_SIZE, byteLength);
644
713
  return new TextDecoder().decode(bytes);
645
714
  }
646
715
  /**
@@ -648,26 +717,37 @@ var StructReader = class StructReader {
648
717
  */
649
718
  getStruct(pointerIndex, _dataWords, _pointerCount) {
650
719
  const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;
651
- const ptrValue = this.message.getSegment(this.segmentIndex).getWord(ptrOffset);
652
- if (ptrValue === 0n) return void 0;
653
- const ptr = decodePointer(ptrValue);
654
- if (ptr.tag !== PointerTag.STRUCT) return void 0;
655
- const structPtr = ptr;
656
- const targetOffset = ptrOffset + 1 + structPtr.offset;
657
- return new StructReader(this.message, this.segmentIndex, targetOffset, structPtr.dataWords, structPtr.pointerCount);
720
+ const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);
721
+ if (!resolved) return void 0;
722
+ const { segmentIndex, wordOffset, pointer } = resolved;
723
+ if (pointer.tag !== PointerTag.STRUCT) return void 0;
724
+ const structPtr = pointer;
725
+ return new StructReader(this.message, segmentIndex, wordOffset, structPtr.dataWords, structPtr.pointerCount);
658
726
  }
659
727
  /**
660
728
  * 获取列表
661
729
  */
662
730
  getList(pointerIndex, _elementSize, structSize) {
663
731
  const ptrOffset = this.wordOffset + this.dataWords + pointerIndex;
664
- const ptrValue = this.message.getSegment(this.segmentIndex).getWord(ptrOffset);
665
- if (ptrValue === 0n) return void 0;
666
- const ptr = decodePointer(ptrValue);
667
- if (ptr.tag !== PointerTag.LIST) return void 0;
668
- const listPtr = ptr;
669
- const targetOffset = ptrOffset + 1 + listPtr.offset;
670
- return new ListReader(this.message, this.segmentIndex, listPtr.elementSize, listPtr.elementCount, structSize, targetOffset);
732
+ const resolved = this.message.resolvePointer(this.segmentIndex, ptrOffset);
733
+ if (!resolved) return void 0;
734
+ const { segmentIndex, wordOffset, pointer } = resolved;
735
+ if (pointer.tag !== PointerTag.LIST) return void 0;
736
+ const listPtr = pointer;
737
+ let targetOffset = wordOffset;
738
+ let elementCount = listPtr.elementCount;
739
+ let actualStructSize = structSize;
740
+ const segment = this.message.getSegment(segmentIndex);
741
+ if (listPtr.elementSize === ElementSize.COMPOSITE) {
742
+ const tagWord = segment.getWord(targetOffset);
743
+ elementCount = Number(tagWord & BigInt(4294967295));
744
+ actualStructSize = {
745
+ dataWords: Number(tagWord >> BigInt(32) & BigInt(65535)),
746
+ pointerCount: Number(tagWord >> BigInt(48) & BigInt(65535))
747
+ };
748
+ targetOffset += 1;
749
+ }
750
+ return new ListReader(this.message, segmentIndex, listPtr.elementSize, elementCount, actualStructSize, targetOffset);
671
751
  }
672
752
  };
673
753