Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Basic Pattern Matching Examples

Fixed-Size Fields

The simplest case involves extracting fixed-size segments:

(defun parse-rgb (pixel)
  "Extract RGB components from a 24-bit pixel."
  (binary ((r (size 8)) (g (size 8)) (b (size 8))) pixel)
  `#m(red ,r green ,g blue ,b))

Testing this function:

lfe> (parse-rgb #B(255 0 128))
#m(red 255 green 0 blue 128)

Variable-Length Fields

Things become more interesting when the size of one field determines the size of another—a common pattern in length-prefixed data structures:

(defun parse-length-value (data)
  "Parse a length-prefixed value (Pascal string style)."
  (binary ((len (size 8)) (value (size len) binary) rest binary) data)
  `#(,value ,rest))

Note the delightful sequence of events: first we extract len (8 bits), then immediately use that value to determine how many bits to extract into value. This is rather like opening a package that contains instructions for how big the package is—recursive, slightly mind-bending, but ultimately quite useful.

lfe> (set msg (binary ((5 (size 8)) (#"Hello" binary) (#" World" binary))))
#B(5 72 101 108 108 111 32 87 111 114 108 100)

lfe> (parse-length-value msg)
#(#B(72 101 108 108 111) #B(32 87 111 114 108 100))