diff --git a/Sources/Extensions.swift b/Sources/Extensions.swift index 0e644569..810f8f21 100644 --- a/Sources/Extensions.swift +++ b/Sources/Extensions.swift @@ -20,95 +20,20 @@ extension Data { } } - func bytes(from range: Range) -> [UInt8] { - return self.subdata(in: range).toArray(type: UInt8.self) - } - } extension UInt8 { - subscript(index: Int) -> UInt8 { - precondition(index >= 0 && index < 8, "Index must be between 0 and 7 (included).") - let uindex = index.toUInt8() - return (self & (0x1 << uindex)) >> uindex - } - - subscript(range: CountableRange) -> [UInt8] { - return range.map { - let uindex = $0.toUInt8() - return (self & (0x1 << uindex)) >> uindex - } - } - func toInt() -> Int { return Int(bitPattern: UInt(self)) } - func toUintArray() -> [UInt8] { - return self[0..<8] - } - - func reversedBitOrder() -> UInt8 { - var c = (self & 0xF0) >> 4 | (self & 0x0F) << 4 - c = (c & 0xCC) >> 2 | (c & 0x33) << 2 - c = (c & 0xAA) >> 1 | (c & 0x55) << 1 - return c - } - -} - -extension UInt16 { - - subscript(range: CountableRange) -> [UInt8] { - return range.map { - let uindex = UInt16(truncatingBitPattern: UInt($0)) - return ((self & (0x1 << uindex)) >> uindex).toUInt8() - } - } - - func toInt() -> Int { - return Int(bitPattern: UInt(self)) - } - - func toUInt8() -> UInt8 { - return UInt8(truncatingBitPattern: self) - } - } extension Int { - func toUInt16() -> UInt16 { - return UInt16(truncatingBitPattern: UInt(self)) - } - func toUInt8() -> UInt8 { return UInt8(truncatingBitPattern: UInt(self)) } } - -func convertToInt(uint8Array array: [UInt8], bitOrder: BitOrder = .reversed) -> Int { - var result = 0 - for i in 0.. UInt8 { - precondition(array.count <= 8, "Array must contain no more than 8 bits.") - var result: UInt8 = 0 - for i in 0.. ServiceInfo { - // First byte is compression method and window size - let cmf = pointerData.alignedByte() - // First four bits are compression method. // Only compression method = 8 (DEFLATE) is supported. - let compressionMethod = convertToUInt8(uint8Array: cmf[0..<4]) + let compressionMethod = pointerData.intFromBits(count: 4) guard compressionMethod == 8 else { throw ZlibError.WrongCompressionMethod } // Remaining four bits indicate window size // For DEFLATE it must not be more than 7 - let compressionInfo = convertToUInt8(uint8Array: cmf[4..<8]) + let compressionInfo = pointerData.intFromBits(count: 4) guard compressionInfo <= 7 else { throw ZlibError.WrongCompressionInfo } let windowSize = Int(pow(Double(2), Double(compressionInfo + 8))) - // Second byte is flags - let flags = pointerData.alignedByte() + // compressionMethod and compressionInfo combined are needed later for integrity check + let cmf = compressionInfo << 4 + compressionMethod - // Flags contain fcheck bits which are supposed to be integrity check - guard (UInt(cmf) * 256 + UInt(flags)) % 31 == 0 else { throw ZlibError.WrongFcheck } + // Next five bits are fcheck bits which are supposed to be integrity check + let fcheck = pointerData.intFromBits(count: 5) - // Fifth bit indicate if archive contain Adler-32 checksum of preset dictionary - let fdict = flags[5] + // Sixth bit indicate if archive contain Adler-32 checksum of preset dictionary + let fdict = pointerData.intFromBits(count: 1) // Remaining bits indicate compression level guard let compressionLevel = CompressionLevel(rawValue: - convertToInt(uint8Array: flags[6..<8])) else { throw ZlibError.WrongCompressionLevel } + pointerData.intFromBits(count: 2)) else { throw ZlibError.WrongCompressionLevel } + + // fcheck, fdict and compresionLevel together make flags byte which is used in integrity check + let flags = compressionLevel.rawValue << 6 + fdict << 5 + fcheck + guard (UInt(cmf) * 256 + UInt(flags)) % 31 == 0 else { throw ZlibError.WrongFcheck } let info = ServiceInfo(compressionMethod: compressionMethod, windowSize: windowSize,