(chibi binary-record)

(syntax-let-optionals* () type-args expr)
(syntax-let-optionals* ((param default) . rest) (arg0 . args) expr)
(syntax-let-optionals* ((param default) . rest) () expr)
(syntax-let-optionals* (param . rest) (arg0 . args) expr)
(syntax-let-optionals* (param . rest) () expr)

(define-binary-record-type <name> [<bindings> ...] (block: <fields> ...))

Defines a new record type that supports serializing to and from binary ports. The generated procedures accept keyword-style arguments:

The fields are also similar to define-record-type but with an additional type:

(field (type args ...) getter setter)

Built-in types include:

In addition, the field can be a literal (char, string or bytevector), for instance as a file magic sequence or fixed separator. The fields (and any constants) are serialized in the order they appear in the block. For example, the header of a GIF file could be defined as:

 (define-binary-record-type gif-header
   (make: make-gif-header)
   (pred: gif-header?)
   (read: read-gif-header)
   (write: write-gif-header)
    (width (u16/le) gif-header-width)
    (height (u16/le) gif-header-height)
    (gct (u8) gif-header-gct)
    (bgcolor (u8) gif-header-gbcolor)
    (aspect-ratio (u8) gif-header-aspect-ratio)
ERROR on line 26 of file lib/srfi/9.scm: immutable binding: gif-header

For a more complex example see the (chibi tar) implementation.

The binary type itself is a macro used to expand to a predicate and reader/writer procedures, which can be defined with define-binary-type. For example,

 (define-binary-type (u8)
   (lambda (x) (and (exact-integer? x) (<= 0 x 255)))
=> #<undef>