# (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:

- `(make: <constructor-name>)`
- `(pred: <predicate-name>)`
- `(read: <reader-name>)`
- `(write: <writer-name>)`
- `(block: <fields> ...)`

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

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

Built-in types include:

- `(u8)` - a single byte in [0, 255]
- `(u16/le)` - a little-endian short integer
- `(u16/be)` - a big-endian short integer
- `(fixed-string <length>)` - a fixed-length utf-8 string
- `(padded-string <length> (pad <pad-char>))` - a utf-8 string padded to a given length
- `(octal <length>)` - an integer in octal string format
- `(decimal <length>)` - an integer in decimal string format
- `(hexadecimal <length>)` - an integer in hexadecimal string format

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)
       (block:
        "GIF89a"
        (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)))
       read-u8
       write-u8)

`=> #<undef>`

#### `defrec`