BinData
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
Class methods
Reads an instance from io (IO#read_bytes entry point). The type's
declared endian is used; format is accepted but not applied.
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.
Instance methods
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.
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.
Reads the fields of this instance from io, in declaration order, and
returns io. Raises BinData::ParseError (or BinData::VerificationException)
on malformed input.
Writes this instance to io (IO#write_bytes entry point). The type's
declared endian is used; format is accepted but not applied.
Macros
this needs to be split out so we can resolve the enum base_type
Registers a callback run on the instance just after it is read, e.g. to expose a friendlier representation of the raw fields.
Registers a callback run on the instance just before it is written, e.g. to derive raw fields from a friendlier representation.
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.
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
DEPRECATED Use #field instead
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
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 withlength:(and optionalencoding:)Bytes— requires alength:callbackEnumtypes — require a default valueArray/Set— requirelength:(fixed) orread_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::VerificationExceptionunless 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
Stringfields - endian — override the type's byte order for this field (numeric fields)
field size : UInt16, value: -> { text.bytesize }
field text : String, length: -> { size }
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
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
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
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.
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 }
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead
DEPRECATED Use #field instead