// SPDX-License-Identifier: Apache-2.0 import Foundation struct ApkIndexPackage: Hashable { let indexChecksum: String //TODO: Decode cus why not let name: String let version: String let architecture: String? let packageSize: UInt64 let installedSize: UInt64 let packageDescription: String let url: String let license: String let origin: String? let maintainer: String? let buildTime: Date? let commit: String? let providerPriority: UInt16? let dependencies: [ApkIndexDependency] let provides: [ApkIndexProvides] let installIf: [ApkIndexInstallIf] var downloadFilename: String { "\(self.name)-\(version).apk" } //TODO: Implementation //lazy var semanticVersion: (Int, Int, Int) = (0, 0, 0) } extension ApkIndexPackage { init(raw rawEntry: ApkRawIndexEntry) throws(Self.ParseError) { // Required fields var indexChecksum: String? = nil var name: String? = nil var version: String? = nil var description: String? = nil var url: String? = nil var license: String? = nil var packageSize: UInt64? = nil var installedSize: UInt64? = nil var dependencies = [ApkIndexDependency]() var provides = [ApkIndexProvides]() var installIf = [ApkIndexInstallIf]() // Optional fields var architecture: String? = nil var origin: String? = nil var maintainer: String? = nil var buildTime: Date? = nil var commit: String? = nil var providerPriority: UInt16? = nil // Read all the raw records for this entry for record in rawEntry.fields { switch record.key { case "P": name = record.value case "V": version = record.value case "T": description = record.value case "U": url = record.value case "L": license = record.value case "A": architecture = record.value case "D": do { dependencies = try ApkIndexDependency.extract(record.value) } catch { throw .badValue(key: record.key) } case "C": indexChecksum = record.value // base64-encoded SHA1 hash prefixed with "Q1" case "S": guard let value = UInt64(record.value, radix: 10) else { throw .badValue(key: record.key) } packageSize = value case "I": guard let value = UInt64(record.value, radix: 10) else { throw .badValue(key: record.key) } installedSize = value case "p": do { provides = try ApkIndexProvides.extract(record.value) } catch { throw .badValue(key: record.key) } case "i": do { installIf = try ApkIndexInstallIf.extract(record.value) } catch { throw .badValue(key: record.key) } case "o": origin = record.value case "m": maintainer = record.value case "t": guard let timet = UInt64(record.value, radix: 10), let timetInterval = TimeInterval(exactly: timet) else { throw .badValue(key: record.key) } buildTime = Date(timeIntervalSince1970: timetInterval) case "c": commit = record.value case "k": guard let value = UInt64(record.value, radix: 10), (0..(or error: @autoclosure () -> E) throws(E) -> Wrapped { switch self { case .some(let v): return v case .none: throw error() } } }