Skip to content

Commit

Permalink
fix byte order bug in gzip header parser, add gzip compression example
Browse files Browse the repository at this point in the history
  • Loading branch information
tayloraswift committed Feb 1, 2024
1 parent a34a366 commit 93ad782
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 10 deletions.
18 changes: 15 additions & 3 deletions Snippets/GzipCompression.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
}
}
Binary file added Snippets/GzipCompression/example.txt.gz
Binary file not shown.
2 changes: 1 addition & 1 deletion Sources/LZ77/Gzip/Gzip.Deflator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension Gzip
}
extension Gzip.Deflator
{
mutating
public mutating
func push(_ data:ArraySlice<UInt8>, last:Bool = false)
{
self.buffers.push(data, last: last)
Expand Down
10 changes: 5 additions & 5 deletions Sources/LZ77/Gzip/Gzip.StreamHeader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand All @@ -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)
}
}
8 changes: 7 additions & 1 deletion Sources/LZ77/Inflator/LZ77.InflatorIn.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down

0 comments on commit 93ad782

Please sign in to comment.