Skip to content
heff

std.flate

DEFLATE (RFC 1951), decompressed: the compressed data of zlib, gzip, zip and PNG, as Go’s compress/flate reads it — its blocks stored, of the fixed Huffman codes or of codes of their own, until the one marked last. Written in heff, a code looked up by a table of the bits it may begin with. Import it by a name, import std.flate as Flate.

import bytes as Bytes
import std.flate as Flate
-- | >>> greeting
-- | Right "hello, hello, hello!"
greeting : Either Flate.CorruptInput String
greeting = case Flate.decompress b[203, "H", 205, 201, 201, 215, "Q", 200, "@", 162, 20, 1] of
Right out -> Right (show out)
Left e -> Left e

CorruptInput

type CorruptInput = { offset : Int, message : String }

Where the input is not DEFLATE data: the byte where it went wrong, counted from the start of the input, and what is wrong.

decompressAt

decompressAt : Bytes -> (from : Int) -> Either CorruptInput (Bytes, Int)

The DEFLATE data of the bytes from byte from on (from 0, where it is below): the bytes it holds, and the byte after its last block, its last bits padded to a byte — where what holds it, a zlib stream’s checksum or a gzip member’s trailer, goes on. Where it is wrong, the offset is counted from the start of all the bytes.

>>> decompressAt b[0, 0, 1, 12, 0, 243, 255, "hello, world", "trailer"] (from := 2)
Right (MkPair b["hello, world"] 19)

decompress

decompress : Bytes -> Either CorruptInput Bytes

The DEFLATE data the bytes begin with, decompressed; any bytes after its last block are not looked at.

(a stored block, a block of the fixed codes, one of codes of its own, a length copied over what it copies — 29 as from one — and no bytes)

>>> decompress b[1, 12, 0, 243, 255, "hello, world"]
Right b["hello, world"]
>>> decompress b[203, "H", 205, 201, 201, 215, "Q", 200, "@", 162, 20, 1]
Right b["hello, hello, hello!"]
>>> decompress b[21, 135, "1", 1, 0, 0, 12, 130, 178, 194, 250, "w", 152, 28, 2, 170, 28, 131, 228, "TT", 229, 166, 187, "<"]
Right b["bbbacabbabaacababaaaacaababbaaabaabbcaaa"]
>>> decompress b["KL", 196, 7, 0]
Right b["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"]
>>> decompress b[3, 0]
Right b[]

(where it is not DEFLATE data: a block of type 3; a stored block’s length and its complement not agreeing; too few bytes; more codes than there are; lengths with more codes, or fewer, than their code has room for; a length repeated with none before it; no code for the end of a block; a literal/length or distance code of no symbol; a distance further back than the bytes written)

>>> decompress b[7]
Left { offset = 0, message = "invalid block type 3" }
>>> decompress b[1, 12, 0, 0, 0, "hello, world"]
Left { offset = 1, message = "stored block length does not match its complement" }
>>> decompress b[1, 12, 0, 243, 255, "hel"]
Left { offset = 8, message = "unexpected end of input" }
>>> decompress b[245, 0, 0, 0]
Left { offset = 0, message = "more than 286 literal/length codes" }
>>> decompress b[5, 30, 0, 0]
Left { offset = 0, message = "more than 30 distance codes" }
>>> decompress b[5, 0, 146, 4]
Left { offset = 2, message = "over-subscribed code length code" }
>>> decompress b[5, 0, 4, 0]
Left { offset = 2, message = "incomplete code length code" }
>>> decompress b[5, 0, 2, "$"]
Left { offset = 3, message = "a length repeated before any" }
>>> decompress b[5, 192, 183, "m", 24, 0, 0, 192, "0", 242, 255, 167, "I"]
Left { offset = 8, message = "over-subscribed literal/length code" }
>>> decompress b[5, 192, 183, "m", 24, 0, 0, 192, "0", 242, 255, 171, 9]
Left { offset = 8, message = "no code for the end of a block" }
>>> decompress b[5, 192, 183, "m", 24, 0, 0, 192, 176, 252, 127, "u", 8]
Left { offset = 8, message = "incomplete literal/length code" }
>>> decompress b[5, 193, 183, "m", 24, 0, 0, 192, "0", 254, 127, "5", 13]
Left { offset = 8, message = "incomplete distance code" }
>>> decompress b[27, 3]
Left { offset = 0, message = "invalid literal/length symbol 286" }
>>> decompress b["K", 4, ">"]
Left { offset = 2, message = "invalid distance symbol 30" }
>>> decompress b["K", 4, "B", 0]
Left { offset = 2, message = "distance too far back" }
>>> decompress b[203, "H", 205, 201]
Left { offset = 4, message = "unexpected end of input" }
>>> decompress b[]
Left { offset = 0, message = "unexpected end of input" }