From 2328f40b7a0b301ad176e2657694457667be862e Mon Sep 17 00:00:00 2001 From: LemonBoy Date: Mon, 7 Sep 2020 19:07:27 +0200 Subject: [PATCH 1/2] std: Add DEFLATE and zlib decompressors --- lib/std/compress.zig | 13 + lib/std/compress/deflate.zig | 521 ++++++++++++++ lib/std/compress/rfc1951.txt | 955 +++++++++++++++++++++++++ lib/std/compress/rfc1951.txt.fixed.z.9 | Bin 0 -> 12836 bytes lib/std/compress/rfc1951.txt.z.0 | Bin 0 -> 36960 bytes lib/std/compress/rfc1951.txt.z.9 | Bin 0 -> 11111 bytes lib/std/compress/zlib.zig | 178 +++++ lib/std/std.zig | 1 + 8 files changed, 1668 insertions(+) create mode 100644 lib/std/compress.zig create mode 100644 lib/std/compress/deflate.zig create mode 100644 lib/std/compress/rfc1951.txt create mode 100644 lib/std/compress/rfc1951.txt.fixed.z.9 create mode 100644 lib/std/compress/rfc1951.txt.z.0 create mode 100644 lib/std/compress/rfc1951.txt.z.9 create mode 100644 lib/std/compress/zlib.zig diff --git a/lib/std/compress.zig b/lib/std/compress.zig new file mode 100644 index 0000000000..5518f807df --- /dev/null +++ b/lib/std/compress.zig @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2015-2020 Zig Contributors +// This file is part of [zig](https://ziglang.org/), which is MIT licensed. +// The MIT license requires this copyright notice to be included in all copies +// and substantial portions of the software. +const std = @import("std.zig"); + +pub const deflate = @import("compress/deflate.zig"); +pub const zlib = @import("compress/zlib.zig"); + +test "" { + _ = zlib; +} diff --git a/lib/std/compress/deflate.zig b/lib/std/compress/deflate.zig new file mode 100644 index 0000000000..bad23349e8 --- /dev/null +++ b/lib/std/compress/deflate.zig @@ -0,0 +1,521 @@ +// SPDX-License-Identifier: MIT +// Copyright (c) 2015-2020 Zig Contributors +// This file is part of [zig](https://ziglang.org/), which is MIT licensed. +// The MIT license requires this copyright notice to be included in all copies +// and substantial portions of the software. +// +// Decompressor for DEFLATE data streams (RFC1951) +// +// Heavily inspired by the simple decompressor puff.c by Mark Adler + +const std = @import("std"); +const io = std.io; +const math = std.math; +const mem = std.mem; + +const assert = std.debug.assert; + +const MAXBITS = 15; +const MAXLCODES = 286; +const MAXDCODES = 30; +const MAXCODES = MAXLCODES + MAXDCODES; +const FIXLCODES = 288; + +const Huffman = struct { + count: [MAXBITS + 1]u16, + symbol: [MAXCODES]u16, + + fn construct(self: *Huffman, length: []const u16) !void { + for (self.count) |*val| { + val.* = 0; + } + + for (length) |val| { + self.count[val] += 1; + } + + if (self.count[0] == length.len) + return; + + var left: isize = 1; + for (self.count[1..]) |val| { + left *= 2; + left -= @as(isize, @bitCast(i16, val)); + if (left < 0) + return error.InvalidTree; + } + + var offs: [MAXBITS + 1]u16 = undefined; + { + var len: usize = 1; + offs[1] = 0; + while (len < MAXBITS) : (len += 1) { + offs[len + 1] = offs[len] + self.count[len]; + } + } + + for (length) |val, symbol| { + if (val != 0) { + self.symbol[offs[val]] = @truncate(u16, symbol); + offs[val] += 1; + } + } + } +}; + +pub fn InflateStream(comptime ReaderType: type) type { + return struct { + const Self = @This(); + + pub const Error = ReaderType.Error || error{ + EndOfStream, + BadCounts, + InvalidBlockType, + InvalidDistance, + InvalidFixedCode, + InvalidLength, + InvalidStoredSize, + InvalidSymbol, + InvalidTree, + MissingEOBCode, + NoLastLength, + OutOfCodes, + }; + pub const Reader = io.Reader(*Self, Error, read); + + bit_reader: io.BitReader(.Little, ReaderType), + + // True if the decoder met the end of the compressed stream, no further + // data can be decompressed + seen_eos: bool, + + state: union(enum) { + // Parse a compressed block header and set up the internal state for + // decompressing its contents. + DecodeBlockHeader: void, + // Decode all the symbols in a compressed block. + DecodeBlockData: void, + // Copy N bytes of uncompressed data from the underlying stream into + // the window. + Copy: usize, + // Copy 1 byte into the window. + CopyLit: u8, + // Copy L bytes from the window itself, starting from D bytes + // behind. + CopyFrom: struct { distance: u16, length: u16 }, + }, + + // Sliding window for the LZ77 algorithm + window: struct { + const WSelf = @This(); + + // invariant: buffer length is always a power of 2 + buf: []u8, + // invariant: ri <= wi + wi: usize = 0, // Write index + ri: usize = 0, // Read index + el: usize = 0, // Number of readable elements + + fn readable(self: *WSelf) usize { + return self.el; + } + + fn writable(self: *WSelf) usize { + return self.buf.len - self.el; + } + + // Insert a single byte into the window. + // Returns 1 if there's enough space for the new byte and 0 + // otherwise. + fn append(self: *WSelf, value: u8) usize { + if (self.writable() < 1) return 0; + self.appendUnsafe(value); + return 1; + } + + // Insert a single byte into the window. + // Assumes there's enough space. + fn appendUnsafe(self: *WSelf, value: u8) void { + self.buf[self.wi] = value; + self.wi = (self.wi + 1) & (self.buf.len - 1); + self.el += 1; + } + + // Fill dest[] with data from the window, starting from the read + // position. This updates the read pointer. + // Returns the number of read bytes or 0 if there's nothing to read + // yet. + fn read(self: *WSelf, dest: []u8) usize { + const N = math.min(dest.len, self.readable()); + + if (N == 0) return 0; + + if (self.ri + N < self.buf.len) { + // The data doesn't wrap around + mem.copy(u8, dest, self.buf[self.ri .. self.ri + N]); + } else { + // The data wraps around the buffer, split the copy + std.mem.copy(u8, dest, self.buf[self.ri..]); + // How much data we've copied from `ri` to the end + const r = self.buf.len - self.ri; + std.mem.copy(u8, dest[r..], self.buf[0 .. N - r]); + } + + self.ri = (self.ri + N) & (self.buf.len - 1); + self.el -= N; + + return N; + } + + // Copy `length` bytes starting from `distance` bytes behind the + // write pointer. + // Be careful as the length may be greater than the distance, that's + // how the compressor encodes run-length encoded sequences. + fn copyFrom(self: *WSelf, distance: usize, length: usize) usize { + const N = math.min(length, self.writable()); + + if (N == 0) return 0; + + // TODO: Profile and, if needed, replace with smarter juggling + // of the window memory for the non-overlapping case. + var i: usize = 0; + while (i < N) : (i += 1) { + const index = (self.wi -% distance) % self.buf.len; + self.appendUnsafe(self.buf[index]); + } + + return N; + } + }, + + // Compressor-local Huffman tables used to decompress blocks with + // dynamic codes. + huffman_tables: [2]Huffman = undefined, + + // Huffman tables used for decoding length/distance pairs. + hdist: *Huffman, + hlen: *Huffman, + + fn stored(self: *Self) !void { + // Discard the remaining bits, the lenght field is always + // byte-aligned (and so is the data) + self.bit_reader.alignToByte(); + + const length = (try self.bit_reader.readBitsNoEof(u16, 16)); + const length_cpl = (try self.bit_reader.readBitsNoEof(u16, 16)); + + if (length != ~length_cpl) + return error.InvalidStoredSize; + + self.state = .{ .Copy = length }; + } + + fn fixed(self: *Self) !void { + comptime var lencode: Huffman = undefined; + comptime var distcode: Huffman = undefined; + + // The Huffman codes are specified in the RFC1951, section 3.2.6 + comptime { + @setEvalBranchQuota(100000); + + const len_lengths = // + [_]u16{8} ** 144 ++ + [_]u16{9} ** 112 ++ + [_]u16{7} ** 24 ++ + [_]u16{8} ** 8; + assert(len_lengths.len == FIXLCODES); + try lencode.construct(len_lengths[0..]); + + const dist_lengths = [_]u16{5} ** MAXDCODES; + try distcode.construct(dist_lengths[0..]); + } + + self.hlen = &lencode; + self.hdist = &distcode; + self.state = .DecodeBlockData; + } + + fn dynamic(self: *Self) !void { + // Number of length codes + const nlen = (try self.bit_reader.readBitsNoEof(usize, 5)) + 257; + // Number of distance codes + const ndist = (try self.bit_reader.readBitsNoEof(usize, 5)) + 1; + // Number of code length codes + const ncode = (try self.bit_reader.readBitsNoEof(usize, 4)) + 4; + + if (nlen > MAXLCODES or ndist > MAXDCODES) + return error.BadCounts; + + // Permutation of code length codes + const ORDER = [19]u16{ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, + 12, 3, 13, 2, 14, 1, 15, + }; + + // Build the Huffman table to decode the code length codes + var lencode: Huffman = undefined; + { + var lengths = std.mem.zeroes([19]u16); + + // Read the code lengths, missing ones are left as zero + for (ORDER[0..ncode]) |val| { + lengths[val] = try self.bit_reader.readBitsNoEof(u16, 3); + } + + try lencode.construct(lengths[0..]); + } + + // Read the length/literal and distance code length tables. + // Zero the table by default so we can avoid explicitly writing out + // zeros for codes 17 and 18 + var lengths = std.mem.zeroes([MAXCODES]u16); + + var i: usize = 0; + while (i < nlen + ndist) { + const symbol = try self.decode(&lencode); + + switch (symbol) { + 0...15 => { + lengths[i] = symbol; + i += 1; + }, + 16 => { + // repeat last length 3..6 times + if (i == 0) return error.NoLastLength; + + const last_length = lengths[i - 1]; + const repeat = 3 + (try self.bit_reader.readBitsNoEof(usize, 2)); + const last_index = i + repeat; + while (i < last_index) : (i += 1) { + lengths[i] = last_length; + } + }, + 17 => { + // repeat zero 3..10 times + i += 3 + (try self.bit_reader.readBitsNoEof(usize, 3)); + }, + 18 => { + // repeat zero 11..138 times + i += 11 + (try self.bit_reader.readBitsNoEof(usize, 7)); + }, + else => return error.InvalidSymbol, + } + } + + if (i > nlen + ndist) + return error.InvalidLength; + + // Check if the end of block code is present + if (lengths[256] == 0) + return error.MissingEOBCode; + + try self.huffman_tables[0].construct(lengths[0..nlen]); + try self.huffman_tables[1].construct(lengths[nlen .. nlen + ndist]); + + self.hlen = &self.huffman_tables[0]; + self.hdist = &self.huffman_tables[1]; + self.state = .DecodeBlockData; + } + + fn codes(self: *Self, lencode: *Huffman, distcode: *Huffman) !bool { + // Size base for length codes 257..285 + const LENS = [29]u16{ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, + }; + // Extra bits for length codes 257..285 + const LEXT = [29]u16{ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, + }; + // Offset base for distance codes 0..29 + const DISTS = [30]u16{ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577, + }; + // Extra bits for distance codes 0..29 + const DEXT = [30]u16{ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, + }; + + while (true) { + const symbol = try self.decode(lencode); + + switch (symbol) { + 0...255 => { + // Literal value + const c = @truncate(u8, symbol); + if (self.window.append(c) == 0) { + self.state = .{ .CopyLit = c }; + return false; + } + }, + 256 => { + // End of block symbol + return true; + }, + 257...285 => { + // Length/distance pair + const length_symbol = symbol - 257; + const length = LENS[length_symbol] + + try self.bit_reader.readBitsNoEof(u16, LEXT[length_symbol]); + + const distance_symbol = try self.decode(distcode); + const distance = DISTS[distance_symbol] + + try self.bit_reader.readBitsNoEof(u16, DEXT[distance_symbol]); + + if (distance > self.window.buf.len) + return error.InvalidDistance; + + const written = self.window.copyFrom(distance, length); + if (written != length) { + self.state = .{ + .CopyFrom = .{ + .distance = distance, + .length = length - @truncate(u16, written), + }, + }; + return false; + } + }, + else => return error.InvalidFixedCode, + } + } + } + + fn decode(self: *Self, h: *Huffman) !u16 { + var len: usize = 1; + var code: usize = 0; + var first: usize = 0; + var index: usize = 0; + + while (len <= MAXBITS) : (len += 1) { + code |= try self.bit_reader.readBitsNoEof(usize, 1); + const count = h.count[len]; + if (code < first + count) + return h.symbol[index + (code - first)]; + index += count; + first += count; + first <<= 1; + code <<= 1; + } + + return error.OutOfCodes; + } + + fn step(self: *Self) !void { + while (true) { + switch (self.state) { + .DecodeBlockHeader => { + // The compressed stream is done + if (self.seen_eos) return; + + const last = try self.bit_reader.readBitsNoEof(u1, 1); + const kind = try self.bit_reader.readBitsNoEof(u2, 2); + + self.seen_eos = last != 0; + + // The next state depends on the block type + switch (kind) { + 0 => try self.stored(), + 1 => try self.fixed(), + 2 => try self.dynamic(), + 3 => return error.InvalidBlockType, + } + }, + .DecodeBlockData => { + if (!try self.codes(self.hlen, self.hdist)) { + return; + } + + self.state = .DecodeBlockHeader; + }, + .Copy => |*length| { + const N = math.min(self.window.writable(), length.*); + + // TODO: This loop can be more efficient. On the other + // hand uncompressed blocks are not that common so... + var i: usize = 0; + while (i < N) : (i += 1) { + var tmp: [1]u8 = undefined; + if ((try self.bit_reader.read(&tmp)) != 1) { + // Unexpected end of stream, keep this error + // consistent with the use of readBitsNoEof + return error.EndOfStream; + } + self.window.appendUnsafe(tmp[0]); + } + + if (N != length.*) { + length.* -= N; + return; + } + + self.state = .DecodeBlockHeader; + }, + .CopyLit => |c| { + if (self.window.append(c) == 0) { + return; + } + + self.state = .DecodeBlockData; + }, + .CopyFrom => |*info| { + const written = self.window.copyFrom(info.distance, info.length); + if (written != info.length) { + info.length -= @truncate(u16, written); + return; + } + + self.state = .DecodeBlockData; + }, + } + } + } + + fn init(source: ReaderType, window_slice: []u8) Self { + assert(math.isPowerOfTwo(window_slice.len)); + + return Self{ + .bit_reader = io.bitReader(.Little, source), + .window = .{ .buf = window_slice }, + .seen_eos = false, + .state = .DecodeBlockHeader, + .hdist = undefined, + .hlen = undefined, + }; + } + + // Implements the io.Reader interface + pub fn read(self: *Self, buffer: []u8) Error!usize { + if (buffer.len == 0) + return 0; + + // Try reading as much as possible from the window + var read_amt: usize = self.window.read(buffer); + while (read_amt < buffer.len) { + // Run the state machine, we can detect the "effective" end of + // stream condition by checking if any progress was made. + // Why "effective"? Because even though `seen_eos` is true we + // may still have to finish processing other decoding steps. + try self.step(); + // No progress was made + if (self.window.readable() == 0) + break; + + read_amt += self.window.read(buffer[read_amt..]); + } + + return read_amt; + } + + pub fn reader(self: *Self) Reader { + return .{ .context = self }; + } + }; +} + +pub fn inflateStream(reader: anytype, window_slice: []u8) InflateStream(@TypeOf(reader)) { + return InflateStream(@TypeOf(reader)).init(reader, window_slice); +} diff --git a/lib/std/compress/rfc1951.txt b/lib/std/compress/rfc1951.txt new file mode 100644 index 0000000000..403c8c722f --- /dev/null +++ b/lib/std/compress/rfc1951.txt @@ -0,0 +1,955 @@ + + + + + + +Network Working Group P. Deutsch +Request for Comments: 1951 Aladdin Enterprises +Category: Informational May 1996 + + + DEFLATE Compressed Data Format Specification version 1.3 + +Status of This Memo + + This memo provides information for the Internet community. This memo + does not specify an Internet standard of any kind. Distribution of + this memo is unlimited. + +IESG Note: + + The IESG takes no position on the validity of any Intellectual + Property Rights statements contained in this document. + +Notices + + Copyright (c) 1996 L. Peter Deutsch + + Permission is granted to copy and distribute this document for any + purpose and without charge, including translations into other + languages and incorporation into compilations, provided that the + copyright notice and this notice are preserved, and that any + substantive changes or deletions from the original are clearly + marked. + + A pointer to the latest version of this and related documentation in + HTML format can be found at the URL + . + +Abstract + + This specification defines a lossless compressed data format that + compresses data using a combination of the LZ77 algorithm and Huffman + coding, with efficiency comparable to the best currently available + general-purpose compression methods. The data can be produced or + consumed, even for an arbitrarily long sequentially presented input + data stream, using only an a priori bounded amount of intermediate + storage. The format can be implemented readily in a manner not + covered by patents. + + + + + + + + +Deutsch Informational [Page 1] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +Table of Contents + + 1. Introduction ................................................... 2 + 1.1. Purpose ................................................... 2 + 1.2. Intended audience ......................................... 3 + 1.3. Scope ..................................................... 3 + 1.4. Compliance ................................................ 3 + 1.5. Definitions of terms and conventions used ................ 3 + 1.6. Changes from previous versions ............................ 4 + 2. Compressed representation overview ............................. 4 + 3. Detailed specification ......................................... 5 + 3.1. Overall conventions ....................................... 5 + 3.1.1. Packing into bytes .................................. 5 + 3.2. Compressed block format ................................... 6 + 3.2.1. Synopsis of prefix and Huffman coding ............... 6 + 3.2.2. Use of Huffman coding in the "deflate" format ....... 7 + 3.2.3. Details of block format ............................. 9 + 3.2.4. Non-compressed blocks (BTYPE=00) ................... 11 + 3.2.5. Compressed blocks (length and distance codes) ...... 11 + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) .... 12 + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) .. 13 + 3.3. Compliance ............................................... 14 + 4. Compression algorithm details ................................. 14 + 5. References .................................................... 16 + 6. Security Considerations ....................................... 16 + 7. Source code ................................................... 16 + 8. Acknowledgements .............................................. 16 + 9. Author's Address .............................................. 17 + +1. Introduction + + 1.1. Purpose + + The purpose of this specification is to define a lossless + compressed data format that: + * Is independent of CPU type, operating system, file system, + and character set, and hence can be used for interchange; + * Can be produced or consumed, even for an arbitrarily long + sequentially presented input data stream, using only an a + priori bounded amount of intermediate storage, and hence + can be used in data communications or similar structures + such as Unix filters; + * Compresses data with efficiency comparable to the best + currently available general-purpose compression methods, + and in particular considerably better than the "compress" + program; + * Can be implemented readily in a manner not covered by + patents, and hence can be practiced freely; + + + +Deutsch Informational [Page 2] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + * Is compatible with the file format produced by the current + widely used gzip utility, in that conforming decompressors + will be able to read data produced by the existing gzip + compressor. + + The data format defined by this specification does not attempt to: + + * Allow random access to compressed data; + * Compress specialized data (e.g., raster graphics) as well + as the best currently available specialized algorithms. + + A simple counting argument shows that no lossless compression + algorithm can compress every possible input data set. For the + format defined here, the worst case expansion is 5 bytes per 32K- + byte block, i.e., a size increase of 0.015% for large data sets. + English text usually compresses by a factor of 2.5 to 3; + executable files usually compress somewhat less; graphical data + such as raster images may compress much more. + + 1.2. Intended audience + + This specification is intended for use by implementors of software + to compress data into "deflate" format and/or decompress data from + "deflate" format. + + The text of the specification assumes a basic background in + programming at the level of bits and other primitive data + representations. Familiarity with the technique of Huffman coding + is helpful but not required. + + 1.3. Scope + + The specification specifies a method for representing a sequence + of bytes as a (usually shorter) sequence of bits, and a method for + packing the latter bit sequence into bytes. + + 1.4. Compliance + + Unless otherwise indicated below, a compliant decompressor must be + able to accept and decompress any data set that conforms to all + the specifications presented here; a compliant compressor must + produce data sets that conform to all the specifications presented + here. + + 1.5. Definitions of terms and conventions used + + Byte: 8 bits stored or transmitted as a unit (same as an octet). + For this specification, a byte is exactly 8 bits, even on machines + + + +Deutsch Informational [Page 3] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + which store a character on a number of bits different from eight. + See below, for the numbering of bits within a byte. + + String: a sequence of arbitrary bytes. + + 1.6. Changes from previous versions + + There have been no technical changes to the deflate format since + version 1.1 of this specification. In version 1.2, some + terminology was changed. Version 1.3 is a conversion of the + specification to RFC style. + +2. Compressed representation overview + + A compressed data set consists of a series of blocks, corresponding + to successive blocks of input data. The block sizes are arbitrary, + except that non-compressible blocks are limited to 65,535 bytes. + + Each block is compressed using a combination of the LZ77 algorithm + and Huffman coding. The Huffman trees for each block are independent + of those for previous or subsequent blocks; the LZ77 algorithm may + use a reference to a duplicated string occurring in a previous block, + up to 32K input bytes before. + + Each block consists of two parts: a pair of Huffman code trees that + describe the representation of the compressed data part, and a + compressed data part. (The Huffman trees themselves are compressed + using Huffman encoding.) The compressed data consists of a series of + elements of two types: literal bytes (of strings that have not been + detected as duplicated within the previous 32K input bytes), and + pointers to duplicated strings, where a pointer is represented as a + pair . The representation used in the + "deflate" format limits distances to 32K bytes and lengths to 258 + bytes, but does not limit the size of a block, except for + uncompressible blocks, which are limited as noted above. + + Each type of value (literals, distances, and lengths) in the + compressed data is represented using a Huffman code, using one code + tree for literals and lengths and a separate code tree for distances. + The code trees for each block appear in a compact form just before + the compressed data for that block. + + + + + + + + + + +Deutsch Informational [Page 4] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +3. Detailed specification + + 3.1. Overall conventions In the diagrams below, a box like this: + + +---+ + | | <-- the vertical bars might be missing + +---+ + + represents one byte; a box like this: + + +==============+ + | | + +==============+ + + represents a variable number of bytes. + + Bytes stored within a computer do not have a "bit order", since + they are always treated as a unit. However, a byte considered as + an integer between 0 and 255 does have a most- and least- + significant bit, and since we write numbers with the most- + significant digit on the left, we also write bytes with the most- + significant bit on the left. In the diagrams below, we number the + bits of a byte so that bit 0 is the least-significant bit, i.e., + the bits are numbered: + + +--------+ + |76543210| + +--------+ + + Within a computer, a number may occupy multiple bytes. All + multi-byte numbers in the format described here are stored with + the least-significant byte first (at the lower memory address). + For example, the decimal number 520 is stored as: + + 0 1 + +--------+--------+ + |00001000|00000010| + +--------+--------+ + ^ ^ + | | + | + more significant byte = 2 x 256 + + less significant byte = 8 + + 3.1.1. Packing into bytes + + This document does not address the issue of the order in which + bits of a byte are transmitted on a bit-sequential medium, + since the final data format described here is byte- rather than + + + +Deutsch Informational [Page 5] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + bit-oriented. However, we describe the compressed block format + in below, as a sequence of data elements of various bit + lengths, not a sequence of bytes. We must therefore specify + how to pack these data elements into bytes to form the final + compressed byte sequence: + + * Data elements are packed into bytes in order of + increasing bit number within the byte, i.e., starting + with the least-significant bit of the byte. + * Data elements other than Huffman codes are packed + starting with the least-significant bit of the data + element. + * Huffman codes are packed starting with the most- + significant bit of the code. + + In other words, if one were to print out the compressed data as + a sequence of bytes, starting with the first byte at the + *right* margin and proceeding to the *left*, with the most- + significant bit of each byte on the left as usual, one would be + able to parse the result from right to left, with fixed-width + elements in the correct MSB-to-LSB order and Huffman codes in + bit-reversed order (i.e., with the first bit of the code in the + relative LSB position). + + 3.2. Compressed block format + + 3.2.1. Synopsis of prefix and Huffman coding + + Prefix coding represents symbols from an a priori known + alphabet by bit sequences (codes), one code for each symbol, in + a manner such that different symbols may be represented by bit + sequences of different lengths, but a parser can always parse + an encoded string unambiguously symbol-by-symbol. + + We define a prefix code in terms of a binary tree in which the + two edges descending from each non-leaf node are labeled 0 and + 1 and in which the leaf nodes correspond one-for-one with (are + labeled with) the symbols of the alphabet; then the code for a + symbol is the sequence of 0's and 1's on the edges leading from + the root to the leaf labeled with that symbol. For example: + + + + + + + + + + + +Deutsch Informational [Page 6] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + /\ Symbol Code + 0 1 ------ ---- + / \ A 00 + /\ B B 1 + 0 1 C 011 + / \ D 010 + A /\ + 0 1 + / \ + D C + + A parser can decode the next symbol from an encoded input + stream by walking down the tree from the root, at each step + choosing the edge corresponding to the next input bit. + + Given an alphabet with known symbol frequencies, the Huffman + algorithm allows the construction of an optimal prefix code + (one which represents strings with those symbol frequencies + using the fewest bits of any possible prefix codes for that + alphabet). Such a code is called a Huffman code. (See + reference [1] in Chapter 5, references for additional + information on Huffman codes.) + + Note that in the "deflate" format, the Huffman codes for the + various alphabets must not exceed certain maximum code lengths. + This constraint complicates the algorithm for computing code + lengths from symbol frequencies. Again, see Chapter 5, + references for details. + + 3.2.2. Use of Huffman coding in the "deflate" format + + The Huffman codes used for each alphabet in the "deflate" + format have two additional rules: + + * All codes of a given bit length have lexicographically + consecutive values, in the same order as the symbols + they represent; + + * Shorter codes lexicographically precede longer codes. + + + + + + + + + + + + +Deutsch Informational [Page 7] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + We could recode the example above to follow this rule as + follows, assuming that the order of the alphabet is ABCD: + + Symbol Code + ------ ---- + A 10 + B 0 + C 110 + D 111 + + I.e., 0 precedes 10 which precedes 11x, and 110 and 111 are + lexicographically consecutive. + + Given this rule, we can define the Huffman code for an alphabet + just by giving the bit lengths of the codes for each symbol of + the alphabet in order; this is sufficient to determine the + actual codes. In our example, the code is completely defined + by the sequence of bit lengths (2, 1, 3, 3). The following + algorithm generates the codes as integers, intended to be read + from most- to least-significant bit. The code lengths are + initially in tree[I].Len; the codes are produced in + tree[I].Code. + + 1) Count the number of codes for each code length. Let + bl_count[N] be the number of codes of length N, N >= 1. + + 2) Find the numerical value of the smallest code for each + code length: + + code = 0; + bl_count[0] = 0; + for (bits = 1; bits <= MAX_BITS; bits++) { + code = (code + bl_count[bits-1]) << 1; + next_code[bits] = code; + } + + 3) Assign numerical values to all codes, using consecutive + values for all codes of the same length with the base + values determined at step 2. Codes that are never used + (which have a bit length of zero) must not be assigned a + value. + + for (n = 0; n <= max_code; n++) { + len = tree[n].Len; + if (len != 0) { + tree[n].Code = next_code[len]; + next_code[len]++; + } + + + +Deutsch Informational [Page 8] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + } + + Example: + + Consider the alphabet ABCDEFGH, with bit lengths (3, 3, 3, 3, + 3, 2, 4, 4). After step 1, we have: + + N bl_count[N] + - ----------- + 2 1 + 3 5 + 4 2 + + Step 2 computes the following next_code values: + + N next_code[N] + - ------------ + 1 0 + 2 0 + 3 2 + 4 14 + + Step 3 produces the following code values: + + Symbol Length Code + ------ ------ ---- + A 3 010 + B 3 011 + C 3 100 + D 3 101 + E 3 110 + F 2 00 + G 4 1110 + H 4 1111 + + 3.2.3. Details of block format + + Each block of compressed data begins with 3 header bits + containing the following data: + + first bit BFINAL + next 2 bits BTYPE + + Note that the header bits do not necessarily begin on a byte + boundary, since a block does not necessarily occupy an integral + number of bytes. + + + + + +Deutsch Informational [Page 9] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + BFINAL is set if and only if this is the last block of the data + set. + + BTYPE specifies how the data are compressed, as follows: + + 00 - no compression + 01 - compressed with fixed Huffman codes + 10 - compressed with dynamic Huffman codes + 11 - reserved (error) + + The only difference between the two compressed cases is how the + Huffman codes for the literal/length and distance alphabets are + defined. + + In all cases, the decoding algorithm for the actual data is as + follows: + + do + read block header from input stream. + if stored with no compression + skip any remaining bits in current partially + processed byte + read LEN and NLEN (see next section) + copy LEN bytes of data to output + otherwise + if compressed with dynamic Huffman codes + read representation of code trees (see + subsection below) + loop (until end of block code recognized) + decode literal/length value from input stream + if value < 256 + copy value (literal byte) to output stream + otherwise + if value = end of block (256) + break from loop + otherwise (value = 257..285) + decode distance from input stream + + move backwards distance bytes in the output + stream, and copy length bytes from this + position to the output stream. + end loop + while not last block + + Note that a duplicated string reference may refer to a string + in a previous block; i.e., the backward distance may cross one + or more block boundaries. However a distance cannot refer past + the beginning of the output stream. (An application using a + + + +Deutsch Informational [Page 10] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + preset dictionary might discard part of the output stream; a + distance can refer to that part of the output stream anyway) + Note also that the referenced string may overlap the current + position; for example, if the last 2 bytes decoded have values + X and Y, a string reference with + adds X,Y,X,Y,X to the output stream. + + We now specify each compression method in turn. + + 3.2.4. Non-compressed blocks (BTYPE=00) + + Any bits of input up to the next byte boundary are ignored. + The rest of the block consists of the following information: + + 0 1 2 3 4... + +---+---+---+---+================================+ + | LEN | NLEN |... LEN bytes of literal data...| + +---+---+---+---+================================+ + + LEN is the number of data bytes in the block. NLEN is the + one's complement of LEN. + + 3.2.5. Compressed blocks (length and distance codes) + + As noted above, encoded data blocks in the "deflate" format + consist of sequences of symbols drawn from three conceptually + distinct alphabets: either literal bytes, from the alphabet of + byte values (0..255), or pairs, + where the length is drawn from (3..258) and the distance is + drawn from (1..32,768). In fact, the literal and length + alphabets are merged into a single alphabet (0..285), where + values 0..255 represent literal bytes, the value 256 indicates + end-of-block, and values 257..285 represent length codes + (possibly in conjunction with extra bits following the symbol + code) as follows: + + + + + + + + + + + + + + + + +Deutsch Informational [Page 11] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + Extra Extra Extra + Code Bits Length(s) Code Bits Lengths Code Bits Length(s) + ---- ---- ------ ---- ---- ------- ---- ---- ------- + 257 0 3 267 1 15,16 277 4 67-82 + 258 0 4 268 1 17,18 278 4 83-98 + 259 0 5 269 2 19-22 279 4 99-114 + 260 0 6 270 2 23-26 280 4 115-130 + 261 0 7 271 2 27-30 281 5 131-162 + 262 0 8 272 2 31-34 282 5 163-194 + 263 0 9 273 3 35-42 283 5 195-226 + 264 0 10 274 3 43-50 284 5 227-257 + 265 1 11,12 275 3 51-58 285 0 258 + 266 1 13,14 276 3 59-66 + + The extra bits should be interpreted as a machine integer + stored with the most-significant bit first, e.g., bits 1110 + represent the value 14. + + Extra Extra Extra + Code Bits Dist Code Bits Dist Code Bits Distance + ---- ---- ---- ---- ---- ------ ---- ---- -------- + 0 0 1 10 4 33-48 20 9 1025-1536 + 1 0 2 11 4 49-64 21 9 1537-2048 + 2 0 3 12 5 65-96 22 10 2049-3072 + 3 0 4 13 5 97-128 23 10 3073-4096 + 4 1 5,6 14 6 129-192 24 11 4097-6144 + 5 1 7,8 15 6 193-256 25 11 6145-8192 + 6 2 9-12 16 7 257-384 26 12 8193-12288 + 7 2 13-16 17 7 385-512 27 12 12289-16384 + 8 3 17-24 18 8 513-768 28 13 16385-24576 + 9 3 25-32 19 8 769-1024 29 13 24577-32768 + + 3.2.6. Compression with fixed Huffman codes (BTYPE=01) + + The Huffman codes for the two alphabets are fixed, and are not + represented explicitly in the data. The Huffman code lengths + for the literal/length alphabet are: + + Lit Value Bits Codes + --------- ---- ----- + 0 - 143 8 00110000 through + 10111111 + 144 - 255 9 110010000 through + 111111111 + 256 - 279 7 0000000 through + 0010111 + 280 - 287 8 11000000 through + 11000111 + + + +Deutsch Informational [Page 12] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + The code lengths are sufficient to generate the actual codes, + as described above; we show the codes in the table for added + clarity. Literal/length values 286-287 will never actually + occur in the compressed data, but participate in the code + construction. + + Distance codes 0-31 are represented by (fixed-length) 5-bit + codes, with possible additional bits as shown in the table + shown in Paragraph 3.2.5, above. Note that distance codes 30- + 31 will never actually occur in the compressed data. + + 3.2.7. Compression with dynamic Huffman codes (BTYPE=10) + + The Huffman codes for the two alphabets appear in the block + immediately after the header bits and before the actual + compressed data, first the literal/length code and then the + distance code. Each code is defined by a sequence of code + lengths, as discussed in Paragraph 3.2.2, above. For even + greater compactness, the code length sequences themselves are + compressed using a Huffman code. The alphabet for code lengths + is as follows: + + 0 - 15: Represent code lengths of 0 - 15 + 16: Copy the previous code length 3 - 6 times. + The next 2 bits indicate repeat length + (0 = 3, ... , 3 = 6) + Example: Codes 8, 16 (+2 bits 11), + 16 (+2 bits 10) will expand to + 12 code lengths of 8 (1 + 6 + 5) + 17: Repeat a code length of 0 for 3 - 10 times. + (3 bits of length) + 18: Repeat a code length of 0 for 11 - 138 times + (7 bits of length) + + A code length of 0 indicates that the corresponding symbol in + the literal/length or distance alphabet will not occur in the + block, and should not participate in the Huffman code + construction algorithm given earlier. If only one distance + code is used, it is encoded using one bit, not zero bits; in + this case there is a single code length of one, with one unused + code. One distance code of zero bits means that there are no + distance codes used at all (the data is all literals). + + We can now define the format of the block: + + 5 Bits: HLIT, # of Literal/Length codes - 257 (257 - 286) + 5 Bits: HDIST, # of Distance codes - 1 (1 - 32) + 4 Bits: HCLEN, # of Code Length codes - 4 (4 - 19) + + + +Deutsch Informational [Page 13] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + (HCLEN + 4) x 3 bits: code lengths for the code length + alphabet given just above, in the order: 16, 17, 18, + 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 + + These code lengths are interpreted as 3-bit integers + (0-7); as above, a code length of 0 means the + corresponding symbol (literal/length or distance code + length) is not used. + + HLIT + 257 code lengths for the literal/length alphabet, + encoded using the code length Huffman code + + HDIST + 1 code lengths for the distance alphabet, + encoded using the code length Huffman code + + The actual compressed data of the block, + encoded using the literal/length and distance Huffman + codes + + The literal/length symbol 256 (end of data), + encoded using the literal/length Huffman code + + The code length repeat codes can cross from HLIT + 257 to the + HDIST + 1 code lengths. In other words, all code lengths form + a single sequence of HLIT + HDIST + 258 values. + + 3.3. Compliance + + A compressor may limit further the ranges of values specified in + the previous section and still be compliant; for example, it may + limit the range of backward pointers to some value smaller than + 32K. Similarly, a compressor may limit the size of blocks so that + a compressible block fits in memory. + + A compliant decompressor must accept the full range of possible + values defined in the previous section, and must accept blocks of + arbitrary size. + +4. Compression algorithm details + + While it is the intent of this document to define the "deflate" + compressed data format without reference to any particular + compression algorithm, the format is related to the compressed + formats produced by LZ77 (Lempel-Ziv 1977, see reference [2] below); + since many variations of LZ77 are patented, it is strongly + recommended that the implementor of a compressor follow the general + algorithm presented here, which is known not to be patented per se. + The material in this section is not part of the definition of the + + + +Deutsch Informational [Page 14] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + + specification per se, and a compressor need not follow it in order to + be compliant. + + The compressor terminates a block when it determines that starting a + new block with fresh trees would be useful, or when the block size + fills up the compressor's block buffer. + + The compressor uses a chained hash table to find duplicated strings, + using a hash function that operates on 3-byte sequences. At any + given point during compression, let XYZ be the next 3 input bytes to + be examined (not necessarily all different, of course). First, the + compressor examines the hash chain for XYZ. If the chain is empty, + the compressor simply writes out X as a literal byte and advances one + byte in the input. If the hash chain is not empty, indicating that + the sequence XYZ (or, if we are unlucky, some other 3 bytes with the + same hash function value) has occurred recently, the compressor + compares all strings on the XYZ hash chain with the actual input data + sequence starting at the current point, and selects the longest + match. + + The compressor searches the hash chains starting with the most recent + strings, to favor small distances and thus take advantage of the + Huffman encoding. The hash chains are singly linked. There are no + deletions from the hash chains; the algorithm simply discards matches + that are too old. To avoid a worst-case situation, very long hash + chains are arbitrarily truncated at a certain length, determined by a + run-time parameter. + + To improve overall compression, the compressor optionally defers the + selection of matches ("lazy matching"): after a match of length N has + been found, the compressor searches for a longer match starting at + the next input byte. If it finds a longer match, it truncates the + previous match to a length of one (thus producing a single literal + byte) and then emits the longer match. Otherwise, it emits the + original match, and, as described above, advances N bytes before + continuing. + + Run-time parameters also control this "lazy match" procedure. If + compression ratio is most important, the compressor attempts a + complete second search regardless of the length of the first match. + In the normal case, if the current match is "long enough", the + compressor reduces the search for a longer match, thus speeding up + the process. If speed is most important, the compressor inserts new + strings in the hash table only when no match was found, or when the + match is not "too long". This degrades the compression ratio but + saves time since there are both fewer insertions and fewer searches. + + + + + +Deutsch Informational [Page 15] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +5. References + + [1] Huffman, D. A., "A Method for the Construction of Minimum + Redundancy Codes", Proceedings of the Institute of Radio + Engineers, September 1952, Volume 40, Number 9, pp. 1098-1101. + + [2] Ziv J., Lempel A., "A Universal Algorithm for Sequential Data + Compression", IEEE Transactions on Information Theory, Vol. 23, + No. 3, pp. 337-343. + + [3] Gailly, J.-L., and Adler, M., ZLIB documentation and sources, + available in ftp://ftp.uu.net/pub/archiving/zip/doc/ + + [4] Gailly, J.-L., and Adler, M., GZIP documentation and sources, + available as gzip-*.tar in ftp://prep.ai.mit.edu/pub/gnu/ + + [5] Schwartz, E. S., and Kallick, B. "Generating a canonical prefix + encoding." Comm. ACM, 7,3 (Mar. 1964), pp. 166-169. + + [6] Hirschberg and Lelewer, "Efficient decoding of prefix codes," + Comm. ACM, 33,4, April 1990, pp. 449-459. + +6. Security Considerations + + Any data compression method involves the reduction of redundancy in + the data. Consequently, any corruption of the data is likely to have + severe effects and be difficult to correct. Uncompressed text, on + the other hand, will probably still be readable despite the presence + of some corrupted bytes. + + It is recommended that systems using this data format provide some + means of validating the integrity of the compressed data. See + reference [3], for example. + +7. Source code + + Source code for a C language implementation of a "deflate" compliant + compressor and decompressor is available within the zlib package at + ftp://ftp.uu.net/pub/archiving/zip/zlib/. + +8. Acknowledgements + + Trademarks cited in this document are the property of their + respective owners. + + Phil Katz designed the deflate format. Jean-Loup Gailly and Mark + Adler wrote the related software described in this specification. + Glenn Randers-Pehrson converted this document to RFC and HTML format. + + + +Deutsch Informational [Page 16] + +RFC 1951 DEFLATE Compressed Data Format Specification May 1996 + + +9. Author's Address + + L. Peter Deutsch + Aladdin Enterprises + 203 Santa Margarita Ave. + Menlo Park, CA 94025 + + Phone: (415) 322-0103 (AM only) + FAX: (415) 322-1734 + EMail: + + Questions about the technical content of this specification can be + sent by email to: + + Jean-Loup Gailly and + Mark Adler + + Editorial comments on this specification can be sent by email to: + + L. Peter Deutsch and + Glenn Randers-Pehrson + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Deutsch Informational [Page 17] + diff --git a/lib/std/compress/rfc1951.txt.fixed.z.9 b/lib/std/compress/rfc1951.txt.fixed.z.9 new file mode 100644 index 0000000000000000000000000000000000000000..8ea5904770052de696de797b4ef5f3b1a5535e5b GIT binary patch literal 12836 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 literal 0 HcmV?d00001 diff --git a/lib/std/compress/rfc1951.txt.z.0 b/lib/std/compress/rfc1951.txt.z.0 new file mode 100644 index 0000000000000000000000000000000000000000..3f50fb68f8da776fc6d6833b2cbe11cf822fd075 GIT binary patch literal 36960 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 OzyJIH{9pg?|Nei(V%6mU literal 0 HcmV?d00001 diff --git a/lib/std/compress/rfc1951.txt.z.9 b/lib/std/compress/rfc1951.txt.z.9 new file mode 100644 index 0000000000000000000000000000000000000000..84e7cbe5b715527cb3498c7261f5c525ff5d9426 GIT binary patch literal 11111 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 4); + const FCHECK = @truncate(u5, header[1]); + const FDICT = @truncate(u1, header[1] >> 5); + + if ((@as(u16, header[0]) << 8 | header[1]) % 31 != 0) + return error.BadHeader; + + // The CM field must be 8 to indicate the use of DEFLATE + if (CM != 8) return error.InvalidCompression; + // CINFO is the base-2 logarithm of the window size, minus 8. + // Values above 7 are unspecified and therefore rejected. + if (CINFO > 7) return error.InvalidWindowSize; + const window_size: u16 = @as(u16, 1) << (CINFO + 8); + + // TODO: Support this case + if (FDICT != 0) + return error.Unsupported; + + var window_slice = try allocator.alloc(u8, window_size); + + return Self{ + .allocator = allocator, + .inflater = deflate.inflateStream(source, window_slice), + .in_reader = source, + .hasher = std.hash.Adler32.init(), + .window_slice = window_slice, + }; + } + + fn deinit(self: *Self) void { + self.allocator.free(self.window_slice); + } + + // Implements the io.Reader interface + pub fn read(self: *Self, buffer: []u8) Error!usize { + if (buffer.len == 0) + return 0; + + // Read from the compressed stream and update the computed checksum + const r = try self.inflater.read(buffer); + if (r != 0) { + self.hasher.update(buffer[0..r]); + return r; + } + + // We've reached the end of stream, check if the checksum matches + const hash = try self.in_reader.readIntBig(u32); + if (hash != self.hasher.final()) + return error.WrongChecksum; + + return 0; + } + + pub fn reader(self: *Self) Reader { + return .{ .context = self }; + } + }; +} + +pub fn zlibStream(allocator: *mem.Allocator, reader: anytype) !ZlibStream(@TypeOf(reader)) { + return ZlibStream(@TypeOf(reader)).init(allocator, reader); +} + +fn testReader(data: []const u8, comptime expected: []const u8) !void { + var in_stream = io.fixedBufferStream(data); + + var zlib_stream = try zlibStream(testing.allocator, in_stream.reader()); + defer zlib_stream.deinit(); + + // Read and decompress the whole file + const buf = try zlib_stream.reader().readAllAlloc(testing.allocator, std.math.maxInt(usize)); + defer testing.allocator.free(buf); + // Calculate its SHA256 hash and check it against the reference + var hash: [32]u8 = undefined; + std.crypto.hash.sha2.Sha256.hash(buf, hash[0..], .{}); + + assertEqual(expected, &hash); +} + +// Assert `expected` == `input` where `input` is a bytestring. +pub fn assertEqual(comptime expected: []const u8, input: []const u8) void { + var expected_bytes: [expected.len / 2]u8 = undefined; + for (expected_bytes) |*r, i| { + r.* = std.fmt.parseInt(u8, expected[2 * i .. 2 * i + 2], 16) catch unreachable; + } + + testing.expectEqualSlices(u8, &expected_bytes, input); +} + +// All the test cases are obtained by compressing the RFC1950 text +// +// https://tools.ietf.org/rfc/rfc1950.txt length=36944 bytes +// SHA256=5ebf4b5b7fe1c3a0c0ab9aa3ac8c0f3853a7dc484905e76e03b0b0f301350009 +test "compressed data" { + // Compressed with compression level = 0 + try testReader( + @embedFile("rfc1951.txt.z.0"), + "5ebf4b5b7fe1c3a0c0ab9aa3ac8c0f3853a7dc484905e76e03b0b0f301350009", + ); + // Compressed with compression level = 9 + try testReader( + @embedFile("rfc1951.txt.z.9"), + "5ebf4b5b7fe1c3a0c0ab9aa3ac8c0f3853a7dc484905e76e03b0b0f301350009", + ); + // Compressed with compression level = 9 and fixed Huffman codes + try testReader( + @embedFile("rfc1951.txt.fixed.z.9"), + "5ebf4b5b7fe1c3a0c0ab9aa3ac8c0f3853a7dc484905e76e03b0b0f301350009", + ); +} + +test "sanity checks" { + // Truncated header + testing.expectError( + error.EndOfStream, + testReader(&[_]u8{0x78}, ""), + ); + // Failed FCHECK check + testing.expectError( + error.BadHeader, + testReader(&[_]u8{ 0x78, 0x9D }, ""), + ); + // Wrong CM + testing.expectError( + error.InvalidCompression, + testReader(&[_]u8{ 0x79, 0x94 }, ""), + ); + // Wrong CINFO + testing.expectError( + error.InvalidWindowSize, + testReader(&[_]u8{ 0x88, 0x98 }, ""), + ); + // Wrong checksum + testing.expectError( + error.WrongChecksum, + testReader(&[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }, ""), + ); + // Truncated checksum + testing.expectError( + error.EndOfStream, + testReader(&[_]u8{ 0x78, 0xda, 0x03, 0x00, 0x00 }, ""), + ); +} diff --git a/lib/std/std.zig b/lib/std/std.zig index 330f3c253b..4236b29298 100644 --- a/lib/std/std.zig +++ b/lib/std/std.zig @@ -50,6 +50,7 @@ pub const builtin = @import("builtin.zig"); pub const c = @import("c.zig"); pub const cache_hash = @import("cache_hash.zig"); pub const coff = @import("coff.zig"); +pub const compress = @import("compress.zig"); pub const crypto = @import("crypto.zig"); pub const cstr = @import("cstr.zig"); pub const debug = @import("debug.zig"); From c15f39212e32c612cf51f647868be2bdd024d0de Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 7 Sep 2020 15:15:48 -0700 Subject: [PATCH 2/2] build.zig: ignore the compression test files --- build.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build.zig b/build.zig index 8ac2d4f8ba..3f7f1a9038 100644 --- a/build.zig +++ b/build.zig @@ -123,7 +123,13 @@ pub fn build(b: *Builder) !void { .source_dir = "lib", .install_dir = .Lib, .install_subdir = "zig", - .exclude_extensions = &[_][]const u8{ "test.zig", "README.md" }, + .exclude_extensions = &[_][]const u8{ + "test.zig", + "README.md", + ".z.0", + ".z.9", + "rfc1951.txt", + }, }); const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");