chickadee » jiffi » define-enum-packer

(define-enum-packer ...)syntax

Defines a procedure that will "pack" a list of enums (or a single enum) into a single integer, aka a bitfield. The packer converts each enum into an integer, then combines them using bitwise-ior. This supplements define-enum-group for cases where the enums are bitmasks or flags.

See also define-enum-unpacker to go in the opposite direction, converting an integer into a list of symbols.

Usage:

(define-enum-packer PACKER
  (SYMBOL->INT)
  allow-ints: ALLOW-INTS)     ; optional

PACKER is the procedure name to define as the enum packer.

SYMBOL->INT is an existing procedure that converts a symbol into an integer value, such as a procedure defined with define-enum-group. It must accept a second argument, which will be the not-found-callback procedure passed to the packer, or #f if no callback was passed to the packer.

If ALLOW-INTS is #t, the packer will accept integers as well as symbols. If the packer encounters an integer, either in the list of enums or as a single argument, the integer will be used without trying to convert it. This allows users to pack the bitfield manually, for optimization or special cases. If ALLOW-INTS is #f or the keyword clause is omitted, then the packer will always try to convert the enums using SYMBOL->INT regardless of type.

Example:

(foreign-declare "
typedef enum {
  FOO_KMOD_NONE   = 0b0000,
  FOO_KMOD_LCTRL  = 0b0001,
  FOO_KMOD_RCTRL  = 0b0010,
  FOO_KMOD_CTRL   = 0b0011
} FOO_KeyMod;
")

(define-enum-group
  type: int
  symbol->int: keymod->int
  int->symbol: int->keymod
  ((none   FOO_KMOD_NONE)
   (lctrl  FOO_KMOD_LCTRL)
   (rctrl  FOO_KMOD_RCTRL)
   (ctrl   FOO_KMOD_CTRL)))

(define-enum-packer pack-keymods
  (keymod->int)
  allow-ints: #t)

(pack-keymods '(lctrl))            ; ⇒ 1
(pack-keymods 'lctrl)              ; ⇒ 1
(pack-keymods '(rctrl lctrl))      ; ⇒ 3
(pack-keymods '(lctrl 6))          ; ⇒ 7
(pack-keymods '())                 ; ⇒ 0
(pack-keymods 42)                  ; ⇒ 42

(pack-keymods '(lctrl foo))        ; error!
(pack-keymods '(lctrl foo)
              (lambda (sym) 16))   ; ⇒ 17