diff --git a/Snippets/GzipCompression.swift b/Snippets/GzipCompression.swift index 129198cb..4fd131f5 100644 --- a/Snippets/GzipCompression.swift +++ b/Snippets/GzipCompression.swift @@ -4,7 +4,7 @@ import PNG let path:String = "Snippets/GzipCompression/example" guard -let gzipped:[UInt8] = (System.File.Source.open(path: "\(path).gz") +let original:[UInt8] = (System.File.Source.open(path: "\(path).gz") { (source:inout System.File.Source) -> [UInt8]? in @@ -21,8 +21,20 @@ else } var inflator:Gzip.Inflator = .init() -try inflator.push(gzipped[...]) +try inflator.push(original[...]) -let text:String = .init(decoding: inflator.pull(), as: Unicode.UTF8.self) +let utf8:[UInt8] = inflator.pull() +let text:String = .init(decoding: utf8, as: Unicode.UTF8.self) print(text) + +var deflator:Gzip.Deflator = .init(level: 13, exponent: 15, hint: 128 << 10) + deflator.push(utf8[...], last: true) + +let _:Void? = System.File.Destination.open(path: "\(path).txt.gz") +{ + while let part:[UInt8] = deflator.pull() + { + $0.write(part) + } +} diff --git a/Snippets/GzipCompression/example.txt.gz b/Snippets/GzipCompression/example.txt.gz new file mode 100644 index 00000000..e6113b3e Binary files /dev/null and b/Snippets/GzipCompression/example.txt.gz differ diff --git a/Sources/LZ77/Gzip/Gzip.Deflator.swift b/Sources/LZ77/Gzip/Gzip.Deflator.swift index 74f7a6bd..77fef54c 100644 --- a/Sources/LZ77/Gzip/Gzip.Deflator.swift +++ b/Sources/LZ77/Gzip/Gzip.Deflator.swift @@ -15,7 +15,7 @@ extension Gzip } extension Gzip.Deflator { - mutating + public mutating func push(_ data:ArraySlice, last:Bool = false) { self.buffers.push(data, last: last) diff --git a/Sources/LZ77/Gzip/Gzip.StreamHeader.swift b/Sources/LZ77/Gzip/Gzip.StreamHeader.swift index 7e0d896b..7447822a 100644 --- a/Sources/LZ77/Gzip/Gzip.StreamHeader.swift +++ b/Sources/LZ77/Gzip/Gzip.StreamHeader.swift @@ -25,7 +25,7 @@ extension Gzip.StreamHeader } guard - case 0x1f_8b = input[bit, count: 16, as: UInt16.self] + case 0x8b_1f = input[bit] else { throw Gzip.StreamHeaderError.invalidSigil @@ -69,7 +69,7 @@ extension Gzip.StreamHeader } // This is little-endian! - let xlen:UInt16 = input[bit + 80, count: 16, as: UInt16.self].byteSwapped + let xlen:UInt16 = .init(littleEndian: input[bit + 80]) bit += 96 @@ -85,13 +85,13 @@ extension Gzip.StreamHeader // TODO: this is discarding all the metadata! func write(_ output:inout LZ77.DeflatorOut) { - output.append(0x1f_8b, count: 16) - output.append(0x08_00, count: 16) + output.append(0x8b_1f, count: 16) + output.append(0x00_08, count: 16) // TODO: support MTIME output.append(0x00_00, count: 16) output.append(0x00_00, count: 16) - output.append(0x00_ff, count: 16) + output.append(0xff_00, count: 16) } } diff --git a/Sources/LZ77/Inflator/LZ77.InflatorIn.swift b/Sources/LZ77/Inflator/LZ77.InflatorIn.swift index f3b4140c..c33ba537 100644 --- a/Sources/LZ77/Inflator/LZ77.InflatorIn.swift +++ b/Sources/LZ77/Inflator/LZ77.InflatorIn.swift @@ -137,7 +137,13 @@ extension LZ77.InflatorIn } } - /// Returns bits in the low end of the returned integer. + /// Returns bits in the low end of the returned integer. The maximum meaningful bit `count` + /// is 16. + /// + /// The best way to think about the bit order is to imagine the bitstream as a single, + /// arbitrarily-precision integer. This means if you load a slice of the integer into a + /// ``UInt16``, the most-significant bits in the result will correspond to the bits that + /// appear later in the bitstream. /// /// ```text /// { b.15, b.14, b.13, b.12, b.11, b.10, b.9, b.8, b.7, b.6, b.5, b.4, b.3, b.2, b.1, b.0 }