Skip to content
REFERENCE / ZLIB × LEAN

Bits.lean

Source snapshot · 0ca49ce809246868 · Source at the matching commit ↗

Lean source with line numbers. Follow a line number to locate a statement, or an import to read its dependency.

1/-!
2# Format: bits, bytes and numbers
3
4Heap-free, pointer-free vocabulary for the data format of `docs/spec/format/README.md`
5(RFC 1950, 1951, 1952). Everything here is total and structurally recursive.
6
7The reader functions return `none` when the input is too short. A reader that
8succeeds returns the value and the bits that are left.
9-/
10
11namespace ZlibF.Spec
12
13/-- The 8 bits of a byte, least significant bit first.
14RFC 1951, 3.1.1 and `F-bit-order`: data elements are packed starting at the
15least significant bit of each byte. -/
16def byteBits (b : UInt8) : List Bool :=
17  (List.range 8).map fun i => b.toNat.testBit i
18
19/-- The bit sequence of a byte sequence, first bit first (`F-bit-order`). -/
20def bytesToBits (bs : List UInt8) : List Bool :=
21  bs.flatMap byteBits
22
23/-- `readBits n inp` reads an `n`-bit number packed least significant bit first
24(RFC 1951, 3.1.1; `F-bit-order`: lengths, extra bits, `HLIT`, `LEN`, ...).
25It is NOT used for Huffman codes, which are packed most significant bit first. -/
26def readBits : Nat → List Bool → Option (Nat × List Bool)
27  | 0, inp => some (0, inp)
28  | _ + 1, [] => none
29  | n + 1, b :: r =>
30    match readBits n r with
31    | none => none
32    | some (v, r') => some ((if b then 1 else 0) + 2 * v, r')
33
34/-- `readBytes n inp` reads `n` whole bytes (8 bits each, least significant bit
35first), as the body of a stored block (RFC 1951, 3.2.4). -/
36def readBytes : Nat → List Bool → Option (List UInt8 × List Bool)
37  | 0, inp => some ([], inp)
38  | n + 1, inp =>
39    match readBits 8 inp with
40    | none => none
41    | some (v, r) =>
42      match readBytes n r with
43      | none => none
44      | some (bs, r') => some (v.toUInt8 :: bs, r')
45
46/-- `readNats w n inp` reads `n` numbers of `w` bits each (least significant bit first). -/
47def readNats (w : Nat) : Nat → List Bool → Option (List Nat × List Bool)
48  | 0, inp => some ([], inp)
49  | n + 1, inp =>
50    match readBits w inp with
51    | none => none
52    | some (v, r) =>
53      match readNats w n r with
54      | none => none
55      | some (vs, r') => some (v :: vs, r')
56
57/-- The `len`-bit representation of `v`, MOST significant bit first. This is the
58order in which the bits of a Huffman code are read from the stream
59(RFC 1951, 3.1.1; `F-bit-order`). -/
60def natToBitsMSB (len v : Nat) : List Bool :=
61  (List.range len).map fun i => v.testBit (len - 1 - i)
62
63/-- Big-endian 4 bytes (zlib trailer and dictionary id, RFC 1950, 2.2). -/
64def be32 (n : Nat) : List UInt8 :=
65  [(n / 2 ^ 24 % 256).toUInt8, (n / 2 ^ 16 % 256).toUInt8, (n / 2 ^ 8 % 256).toUInt8, (n % 256).toUInt8]
66
67/-- Little-endian 4 bytes (gzip trailer, RFC 1952, 2.3.1). -/
68def le32 (n : Nat) : List UInt8 :=
69  [(n % 256).toUInt8, (n / 2 ^ 8 % 256).toUInt8, (n / 2 ^ 16 % 256).toUInt8, (n / 2 ^ 24 % 256).toUInt8]
70
71/-- Little-endian 2 bytes (gzip `XLEN` and header CRC, RFC 1952, 2.3.1). -/
72def le16 (n : Nat) : List UInt8 :=
73  [(n % 256).toUInt8, (n / 2 ^ 8 % 256).toUInt8]
74
75end ZlibF.Spec
ZLIB × LEAN

Global contents

READING NOWBits.lean