diff --git a/Sources/BZip2.swift b/Sources/BZip2.swift index f5059029..3ce23d1b 100644 --- a/Sources/BZip2.swift +++ b/Sources/BZip2.swift @@ -142,7 +142,9 @@ public class BZip2: DecompressionAlgorithm { while bitReader.bit() > 0 { length -= (Int(bitReader.bit() * 2) - 1) } - lengths.append(HuffmanLength(symbol: i, codeLength: length)) + if length > 0 { + lengths.append(HuffmanLength(symbol: i, codeLength: length)) + } } let table = DecodingHuffmanTree(lengths: lengths, bitReader) tables.append(table) diff --git a/Sources/DecodingHuffmanTree.swift b/Sources/DecodingHuffmanTree.swift index 5bc1e4e0..7d569d39 100644 --- a/Sources/DecodingHuffmanTree.swift +++ b/Sources/DecodingHuffmanTree.swift @@ -12,12 +12,12 @@ class DecodingHuffmanTree { private var tree: [Int] private let leafCount: Int - /// `lengths` don't have to be properly sorted. + /// `lengths` don't have to be properly sorted, but there must not be any 0 code lengths. init(lengths: [HuffmanLength], _ bitReader: BitReader) { self.bitReader = bitReader // Sort `lengths` array to calculate canonical Huffman code. - let sortedLengths = lengths.filter { $0.codeLength > 0 }.sorted { (left: HuffmanLength, right: HuffmanLength) -> Bool in + let sortedLengths = lengths.sorted { (left: HuffmanLength, right: HuffmanLength) -> Bool in if left.codeLength == right.codeLength { return left.symbol < right.symbol } else { @@ -47,6 +47,7 @@ class DecodingHuffmanTree { var loopBits = -1 var symbol = -1 for length in sortedLengths { + precondition(length.codeLength > 0, "Code length must not be 0 during HuffmanTree construction.") symbol += 1 // We sometimes need to make symbol to have length.bits bit length. let bits = length.codeLength diff --git a/Sources/EncodingHuffmanTree.swift b/Sources/EncodingHuffmanTree.swift index 0ad2e4df..4774369a 100644 --- a/Sources/EncodingHuffmanTree.swift +++ b/Sources/EncodingHuffmanTree.swift @@ -11,12 +11,12 @@ class EncodingHuffmanTree { private var codingIndices: [[Int]] - /// `lengths` don't have to be properly sorted. + /// `lengths` don't have to be properly sorted, but there must not be any 0 code lengths. init(lengths: [HuffmanLength], _ bitWriter: BitWriter) { self.bitWriter = bitWriter // Sort `lengths` array to calculate canonical Huffman code. - let sortedLengths = lengths.filter { $0.codeLength > 0 }.sorted { (left: HuffmanLength, right: HuffmanLength) -> Bool in + let sortedLengths = lengths.sorted { (left: HuffmanLength, right: HuffmanLength) -> Bool in if left.codeLength == right.codeLength { return left.symbol < right.symbol } else { @@ -44,6 +44,7 @@ class EncodingHuffmanTree { var loopBits = -1 var symbol = -1 for length in sortedLengths { + precondition(length.codeLength > 0, "Code length must not be 0 during HuffmanTree construction.") symbol += 1 // We sometimes need to make symbol to have length.bits bit length. let bits = length.codeLength diff --git a/Sources/HuffmanLength.swift b/Sources/HuffmanLength.swift index d7085388..516d3fb6 100644 --- a/Sources/HuffmanLength.swift +++ b/Sources/HuffmanLength.swift @@ -29,10 +29,11 @@ struct HuffmanLength { return lengths } + /// - Note: Skips zero codeLengths. static func lengths(from orderedCodeLengths: [Int]) -> [HuffmanLength] { var lengths = [HuffmanLength]() - for i in 0.. 0 { + lengths.append(HuffmanLength(symbol: i, codeLength: codeLength)) } return lengths }