3076ea72创建于 2025年12月1日历史提交
/**
 * Protobuf binary writer for ArkTS
 *
 * Provides varint/zigzag encoders, fixed-width writes and length-delimited
 * string/bytes with delimiter helpers for nested messages.
 */
import { encodeUTF8 } from './util'
export class Writer {
  private b: number[]
  constructor() { this.b = [] }
  get length(): number { return this.b.length }
  private push(v: number): void { this.b.push(v & 0xFF) }
  /** Write unsigned varint32 */
  uint32(v: number): Writer {
    while (v >= 0x80) { this.push((v & 0x7F) | 0x80); v >>>= 7 }
    this.push(v)
    return this
  }
  /** Write field tag (fieldNo<<3 | wireType) */
  tag(fieldNo: number, wireType: number): Writer { return this.uint32((fieldNo << 3) | wireType) }
  /** Write boolean (varint) */
  bool(v: boolean): Writer { return this.uint32(v ? 1 : 0) }
  /** Write int32 */
  int32(v: number): Writer { return this.uint32(v >>> 0) }
  /** Write sint32 (zigzag) */
  sint32(v: number): Writer { return this.uint32(((v << 1) ^ (v >> 31)) >>> 0) }
  /** Write signed varint64 as bigint */
  int64(v: bigint): Writer {
    let x = BigInt.asUintN(64, v)
    while (x > 0x7Fn) { this.push(Number((x & 0x7Fn) | 0x80n)); x >>= 7n }
    this.push(Number(x & 0x7Fn))
    return this
  }
  /** Write sint64 (zigzag) as bigint */
  sint64(v: bigint): Writer {
    const zz = (v << 1n) ^ (v >> 63n)
    return this.int64(zz)
  }
  /** Write signed varint64 from number (may lose precision) */
  int64Number(v: number): Writer { return this.int64(BigInt(v)) }
  /** Write fixed32 little-endian */
  fixed32(v: number): Writer { const ab = new ArrayBuffer(4); const dv = new DataView(ab); dv.setUint32(0, v >>> 0, true); const u = new Uint8Array(ab); for (let i = 0; i < 4; i++) this.push(u[i]); return this }
  /** Write sfixed32 little-endian */
  sfixed32(v: number): Writer { const ab = new ArrayBuffer(4); const dv = new DataView(ab); dv.setInt32(0, v | 0, true); const u = new Uint8Array(ab); for (let i = 0; i < 4; i++) this.push(u[i]); return this }
  /** Write fixed64 little-endian */
  fixed64(v: bigint): Writer { const ab = new ArrayBuffer(8); const dv = new DataView(ab); const lo = Number(v & 0xFFFFFFFFn); const hi = Number((v >> 32n) & 0xFFFFFFFFn); dv.setUint32(0, lo >>> 0, true); dv.setUint32(4, hi >>> 0, true); const u = new Uint8Array(ab); for (let i = 0; i < 8; i++) this.push(u[i]); return this }
  /** Write sfixed64 little-endian */
  sfixed64(v: bigint): Writer { const ab = new ArrayBuffer(8); const dv = new DataView(ab); const lo = Number(v & 0xFFFFFFFFn); const hi = Number((v >> 32n) & 0xFFFFFFFFn); dv.setInt32(0, lo | 0, true); dv.setInt32(4, hi | 0, true); const u = new Uint8Array(ab); for (let i = 0; i < 8; i++) this.push(u[i]); return this }
  /** Write float32 little-endian */
  float(v: number): Writer { const ab = new ArrayBuffer(4); const dv = new DataView(ab); dv.setFloat32(0, v, true); const u = new Uint8Array(ab); for (let i = 0; i < 4; i++) this.push(u[i]); return this }
  /** Write float64 little-endian */
  double(v: number): Writer { const ab = new ArrayBuffer(8); const dv = new DataView(ab); dv.setFloat64(0, v, true); const u = new Uint8Array(ab); for (let i = 0; i < 8; i++) this.push(u[i]); return this }
  /** Write length-delimited UTF-8 string */
  string(s: string): Writer {
    const e = encodeUTF8(s)
    this.uint32(e.length)
    for (let i = 0; i < e.length; i++) this.push(e[i])
    return this
  }
  /** Write length-delimited bytes */
  bytes(a: Uint8Array): Writer {
    this.uint32(a.length)
    for (let i = 0; i < a.length; i++) this.push(a[i])
    return this
  }
  /** Create a child writer for length-delimited section */
  fork(): Writer { return new Writer() }
  /** Write length prefix and append child buffer */
  ldelim(child: Writer): Writer {
    const buf = child.finish()
    this.uint32(buf.length)
    for (let i = 0; i < buf.length; i++) this.push(buf[i])
    return this
  }
  /** Finalize and get the composed buffer */
  finish(): Uint8Array { return Uint8Array.from(this.b) }
}