preserves/_includes/cheatsheet-binary.md

1.8 KiB

For a value V, we write «V» for the binary encoding of V.

                      «#f» = [0x80]
                      «#t» = [0x81]

                     «#!V» = [0x86] ++ «V»

  «V» if V ∈ Float         = [0x87, 0x04] ++ binary32(V)
  «V» if V ∈ Double        = [0x87, 0x08] ++ binary64(V)

  «V» if V ∈ SignedInteger = [0xB0] ++ varint(|intbytes(V)|) ++ intbytes(V)
  «V» if V ∈ String        = [0xB1] ++ varint(|utf8(V)|) ++ utf8(V)
  «V» if V ∈ ByteString    = [0xB2] ++ varint(|V|) ++ V
  «V» if V ∈ Symbol        = [0xB3] ++ varint(|utf8(V)|) ++ utf8(V)

           «<L F_1...F_m>» = [0xB4] ++ «L» ++ «F_1» ++...++ «F_m» ++ [0x84]
             «[X_1...X_m]» = [0xB5] ++ «X_1» ++...++ «X_m» ++ [0x84]
            «#{E_1...E_m}» = [0xB6] ++ «E_1» ++...++ «E_m» ++ [0x84]
     «{K_1:V_1...K_m:V_m}» = [0xB7] ++ «K_1» ++ «V_1» ++...++ «K_m» ++ «V_m» ++ [0x84]

                 varint(v) = e(v, 128)

                   e(v, d) = [v + d] if v < 128
                             e(v >> 7, 0) ++ [(v & 0x7F) + d] if v ≥ 128

The functions binary32(F) and binary64(D) yield big-endian 4- and 8-byte IEEE 754 binary representations of F and D, respectively.

The function intbytes(x) is a big-endian two's-complement signed binary representation of x, taking exactly as many whole bytes as needed to unambiguously identify the value and its sign. In particular, intbytes(0) is the empty byte sequence.

Annotations. To annotate an encoded value «V» (which MUST NOT itself already be annotated) with some sequence of Values V_1...V_m (which MUST be non-empty), surround «V» as follows:

           «@V_1...@V_m V» = [0xBF] ++ «V» ++ «V_1» ++...++ «V_m» ++ [0x84]