mirror of
https://github.com/tsolomko/SWCompression.git
synced 2026-06-23 14:56:41 +00:00
61 lines
2.4 KiB
Swift
61 lines
2.4 KiB
Swift
// Copyright (c) 2021 Timofey Solomko
|
|
// Licensed under MIT License
|
|
//
|
|
// See LICENSE for license information
|
|
|
|
import Foundation
|
|
import BitByteData
|
|
|
|
// While it is tempting to make Provider conform to `IteratorProtocol` and `Sequence` protocols, it is in fact
|
|
// impossible to do so, since `TarEntryInfo.init(...)` is throwing and `IteratorProtocol.next()` cannot be throwing.
|
|
struct TarEntryInfoProvider {
|
|
|
|
private let byteReader: LittleEndianByteReader
|
|
private var lastGlobalExtendedHeader: TarExtendedHeader?
|
|
private var lastLocalExtendedHeader: TarExtendedHeader?
|
|
private var longLinkName: String?
|
|
private var longName: String?
|
|
|
|
init(_ data: Data) {
|
|
self.byteReader = LittleEndianByteReader(data: data)
|
|
}
|
|
|
|
mutating func next() throws -> TarEntryInfo? {
|
|
guard byteReader.bytesLeft >= 1024,
|
|
byteReader.data[byteReader.offset..<byteReader.offset + 1024] != Data(count: 1024)
|
|
else { return nil }
|
|
|
|
let info = try TarEntryInfo(byteReader, lastGlobalExtendedHeader, lastLocalExtendedHeader,
|
|
longName, longLinkName)
|
|
let dataStartIndex = info.blockStartIndex + 512
|
|
|
|
if let specialEntryType = info.specialEntryType {
|
|
switch specialEntryType {
|
|
case .globalExtendedHeader:
|
|
let dataEndIndex = dataStartIndex + info.size!
|
|
lastGlobalExtendedHeader = try TarExtendedHeader(byteReader.data[dataStartIndex..<dataEndIndex])
|
|
case .sunExtendedHeader:
|
|
fallthrough
|
|
case .localExtendedHeader:
|
|
let dataEndIndex = dataStartIndex + info.size!
|
|
lastLocalExtendedHeader = try TarExtendedHeader(byteReader.data[dataStartIndex..<dataEndIndex])
|
|
case .longLinkName:
|
|
byteReader.offset = dataStartIndex
|
|
longLinkName = byteReader.tarCString(maxLength: info.size!)
|
|
case .longName:
|
|
byteReader.offset = dataStartIndex
|
|
longName = byteReader.tarCString(maxLength: info.size!)
|
|
}
|
|
byteReader.offset = dataStartIndex + info.size!.roundTo512()
|
|
} else {
|
|
// Skip file data.
|
|
byteReader.offset = dataStartIndex + info.size!.roundTo512()
|
|
lastLocalExtendedHeader = nil
|
|
longName = nil
|
|
longLinkName = nil
|
|
}
|
|
return info
|
|
}
|
|
|
|
}
|