class

BinData

Inherits Reference / Object

Declarative reader/writer for structured binary data.

Subclass BinData, declare the wire layout with the field / bit_field / group / endian DSL, and the class learns how to (de)serialize itself from any IO:

class Packet < BinData
  endian big

  field size : UInt16, value: -> { payload.size }
  field payload : Bytes, length: -> { size }
end

packet = io.read_bytes(Packet) # decode
io.write_bytes(packet)         # encode

See #field for the supported field types and their options.

Constants

BIT_PARTS = [{more => {UInt8, nil}, tag_number => {UInt8, nil}}, {tag_class => {UInt8, nil}, constructed => {UInt8, nil}, tag_number => {UInt8, nil}}, {long => {UInt8, nil}, length_indicator => {UInt8, nil}}] of Nil
INDEX = [2]

Class methods

bit_fields
Source

Reads an instance from io (IO#read_bytes entry point). The type's declared endian is used; format is accepted but not applied.

Source
from_slice(bytes : Slice, format : IO::ByteFormat = IO::ByteFormat::SystemEndian)

Decodes an instance from a byte slice.

The declared endian of the type is used; the format argument is accepted for IO interoperability but does not override it.

Source

Instance methods

__format__
Source
max_content_length

Maximum number of bytes/elements any single field of this instance (and its nested BinData children) may allocate or read. 0, the default, means unlimited, so existing behaviour is unchanged. Set a positive cap before reading untrusted input to guard against allocation/exhaustion DoS:

packet = Packet.new
packet.max_content_length = 64 * 1024
packet.read(io)

The cap propagates into nested group/array BinData children so a small frame cannot smuggle an oversized one.

Source
max_content_length=(max_content_length : Int32)

Maximum number of bytes/elements any single field of this instance (and its nested BinData children) may allocate or read. 0, the default, means unlimited, so existing behaviour is unchanged. Set a positive cap before reading untrusted input to guard against allocation/exhaustion DoS:

packet = Packet.new
packet.max_content_length = 64 * 1024
packet.read(io)

The cap propagates into nested group/array BinData children so a small frame cannot smuggle an oversized one.

Source
read(io : IO) : IO

Reads the fields of this instance from io, in declaration order, and returns io. Raises BinData::ParseError (or BinData::VerificationException) on malformed input.

Source

Writes this instance to io (IO#write_bytes entry point). The type's declared endian is used; format is accepted but not applied.

Source
to_s(io)
Source
to_slice

Encodes this instance to a freshly allocated byte slice.

Source
write(io : IO)

Writes the fields of this instance to io in declaration order. Raises BinData::WriteError (or BinData::VerificationException) on failure.

Source

Macros

__add_enum_field(name, cls, onlyif, verify, value, encoding, enum_type)

this needs to be split out so we can resolve the enum base_type

Source
__build_methods__
Source
after_deserialize

Registers a callback run on the instance just after it is read, e.g. to expose a friendlier representation of the raw fields.

Source
array(name, length, onlyif = nil, verify = nil, value = nil)

DEPRECATED Use #field instead

Source
before_serialize

Registers a callback run on the instance just before it is written, e.g. to derive raw fields from a friendlier representation.

Source
bit_field(onlyif = nil, verify = nil, endian = nil, &block)

Groups bits / bool fields that are not byte-aligned. The total number of bits declared in the block must be divisible by 8. Use only when fields share a byte; byte-aligned values should be plain fields.

Bit fields follow the class endian: little byte-swaps the bitfield's bytes (the bitfield is read/written as a little-endian integer, fields taken from its most significant bit), while big / network / system / no declaration are big-endian. Pass endian: :little / :big to override a single bit field. Declare endian before the bit_field for the class default to apply.

Accepts the same onlyif / verify callbacks as field.

Source
bits(size, name, value = nil, default = nil)

Declares a size-bit field inside a bit_field block (1 to 128 bits).

The accessor is typed as the smallest unsigned integer that holds size bits. A name : EnumType declaration exposes the value as that enum.

bit_field do
  bits 5, reserved
  bits 2, input : Inputs = Inputs::HDMI
end
Source
bool(name, default = false)

Declares a single-bit boolean field inside a bit_field block.

Source
bytes(name, length, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
custom(name, onlyif = nil, verify = nil, value = nil)

DEPRECATED Use #field instead

Source
endian(format)

Sets the default byte order for every field of the type.

Accepts little, big, network (an alias for big-endian) or system. Individual fields may still override it with the field ..., endian: option.

class Header < BinData
  endian big
end
Source
enum_bits(size, name)

DEPRECATED Use #bits instead

Source
enum_field(size, name, onlyif = nil, verify = nil, value = nil)

DEPRECATED Use #field instead

Source
field(type_declaration, onlyif = nil, verify = nil, value = nil, length = nil, read_next = nil, encoding = nil, endian = nil)

Declares a binary field from a type declaration (name : Type [= default]).

The supported field types are:

  • integers (UInt8..UInt128, Int8..Int128) and floats (Float32/Float64)
  • String — null-terminated, or fixed-size with length: (and optional encoding:)
  • Bytes — requires a length: callback
  • Enum types — require a default value
  • Array/Set — require length: (fixed) or read_next: (variable)
  • any other BinData / IO-serializable type (custom field)

Options (all accept a Proc, evaluated against the instance):

  • onlyif — read/write the field only when the callback returns true
  • verify — raise BinData::VerificationException unless the callback returns true
  • value — compute the field's value just before writing (e.g. a length/checksum)
  • length — element/byte count for sized Bytes/String/Array/Set
  • read_next — keep reading array elements while the callback returns true
  • encoding — string encoding for fixed-size String fields
  • endian — override the type's byte order for this field (numeric fields)
field size : UInt16, value: -> { text.bytesize }
field text : String, length: -> { size }
Source
float32(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
float32be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
float32le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
float64(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
float64be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
float64le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
group(name, onlyif = nil, verify = nil, value = nil, &block)

Declares a nested, isolated group of fields as its own BinData class.

The group exposes a parent accessor for callbacks that need data from the enclosing type, and accepts the same onlyif / verify / value options as field. Useful for related or optional sub-structures.

group :header, onlyif: -> { start == 0xFF } do
  field version : UInt8
end
Source
int128(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int128be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int128le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int16(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int16be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int16le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int32(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int32be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int32le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int64(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int64be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int64le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int8(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int8be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
int8le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
remaining_bytes(name, onlyif = nil, verify = nil, default = nil)

Reads every remaining byte of the IO (until EOF) into a Bytes field. Must be the last field. Works with any IO, including streaming ones (sockets, pipes). Accepts onlyif / verify callbacks.

Source
skip(length, onlyif = nil, verify = nil)

Reads and discards length bytes (advancing the IO) without storing them, for sections you don't need to keep. There is no accessor. On write the region is emitted as length zero bytes, so the structure round-trips to the same size. Accepts onlyif / verify callbacks.

field section_size : UInt32
skip -> { section_size - 4 }
Source
string(name, onlyif = nil, verify = nil, length = nil, value = nil, encoding = nil, default = nil)

DEPRECATED Use #field instead

Source
uint128(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint128be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint128le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint16(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint16be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint16le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint32(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint32be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint32le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint64(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint64be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint64le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint8(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint8be(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
uint8le(name, onlyif = nil, verify = nil, value = nil, default = nil)

DEPRECATED Use #field instead

Source
variable_array(name, read_next, onlyif = nil, verify = nil, value = nil)

DEPRECATED Use #field instead

Source

Nested types