ilusm.dev

cbin

Narrow big-endian row codec for legacy network packets - pack a row of typed fields to bytes and unpack bytes back, supporting u8, u16be, u32be, i32be, null-terminated strings, and raw byte slices.

Load with: use cbin

What this module does

cbin is a simple big-endian-only binary row codec aimed at legacy network protocols and packet formats. You describe a packet layout as a list of {t: "type", v: value} field objects and call cbinp to pack them into a binary string. To decode, you pass the binary string and a list of {t: "type"} spec objects to cbinu.

For richer binary encoding with little-endian, bit-lanes, alignment, views, and full schema support, see the bin module instead.

Quick example

use cbin

# Pack a simple packet: version u8, length u16be, name null-terminated string
pkt = cbinp([
    {t: "u8",    v: 1},
    {t: "u16be", v: 256},
    {t: "zs",    v: "hello"}
])

# Unpack using matching specs
r = cbinu(pkt, [{t: "u8"}, {t: "u16be"}, {t: "zs"}])
# r.vals = [1, 256, "hello"]

# Pack a signed 32-bit big-endian integer (negative)
neg_pkt = cbinp([{t: "i32be", v: -42}])

# Pack raw bytes directly
raw_pkt = cbinp([{t: "raw", v: "\x00\xFF\x7F"}])

Functions

Primitive encoders

cbinu(n) - u16be

Encodes an integer as a 2-byte big-endian string: chr(n / 256) + chr(n % 256).

cbinu(n) - u32be

Encodes an integer as a 4-byte big-endian string by encoding the high and low 16-bit halves with the u16be encoder.

Pack

cbinp(rows)

Packs a list of field objects into a binary string. Each field object has a t (type tag) and v (value):

  • "u8" - single byte, value wrapped modulo 256
  • "u16be" - 2-byte big-endian unsigned integer
  • "u32be" - 4-byte big-endian unsigned integer
  • "i32be" - 4-byte big-endian signed integer (negative values are offset by +2³² before encoding)
  • "zs" - null-terminated string (string value followed by a zero byte)
  • "raw" - raw bytes passed through as-is
Errors on unknown type tags.

Primitive decoders

cbind(s, pos) - u16be

Reads 2 bytes from s at pos. Returns {v: value, pos: pos + 2}.

cbind(s, pos) - u32be

Reads 4 bytes (two u16be reads chained). Returns {v: value, pos: pos + 4}.

Unpack

cbinu(s, specs, pos)

Unpacks fields from binary string s starting at pos according to specs (a list of {t: "type"} objects). Advances pos as each field is consumed. Supported types:

  • "u8" - 1 byte unsigned
  • "u16be" - 2 bytes unsigned
  • "u32be" - 4 bytes unsigned
  • "i32be" - 4 bytes signed (values ≥ 2³¹ are adjusted by subtracting 2³²)
  • "zs" - null-terminated string; errors if no null byte found
  • "raw" - raw bytes; spec must include ln (byte count)
Returns {vals: [decoded values], pos: end_position}.

cbinu(s, specs)

Unpacks from position 0 and checks that all bytes were consumed. Errors if there are trailing bytes. Returns only the values list.

Notes

  • cbin is big-endian only. For little-endian or mixed-endian formats, use the bin module.
  • The "raw" unpack spec requires a ln field on the spec object indicating how many bytes to read.
  • Requires trl, txt, and enc.