apple_kit

Apple-native services for Radroots iOS and macOS apps
git clone https://radroots.dev/git/apple_kit.git
Log | Files | Refs | README | LICENSE

RadrootsBackgroundURLTaskDescriptor.swift (4105B)


      1 import Foundation
      2 
      3 enum RadrootsStagedBackgroundDownloadResult: Sendable, Equatable {
      4     case file(URL)
      5     case failure
      6 }
      7 
      8 struct RadrootsBackgroundHTTPResult: Sendable, Equatable {
      9     let statusCode: Int?
     10     let mediaType: String?
     11     let body: Data?
     12     let contentEncoding: String?
     13     let bodyExceeded: Bool
     14     let mediaTypeWasMalformed: Bool
     15     let destinationMismatch: Bool
     16     let headerFailure: RadrootsBackgroundTransferFailure?
     17 
     18     init(
     19         statusCode: Int?, mediaType: String?, body: Data?, contentEncoding: String? = nil,
     20         bodyExceeded: Bool,
     21         mediaTypeWasMalformed: Bool = false, destinationMismatch: Bool = false,
     22         headerFailure: RadrootsBackgroundTransferFailure? = nil
     23     ) {
     24         self.statusCode = statusCode
     25         self.mediaType = mediaType
     26         self.body = body
     27         self.contentEncoding = contentEncoding
     28         self.bodyExceeded = bodyExceeded
     29         self.mediaTypeWasMalformed = mediaTypeWasMalformed
     30         self.destinationMismatch = destinationMismatch
     31         self.headerFailure = headerFailure
     32     }
     33 }
     34 
     35 struct RadrootsBackgroundURLTaskDescriptor: Sendable, Equatable {
     36     private static let prefix = "radroots-transfer-v1"
     37 
     38     let identifier: RadrootsBackgroundTransferIdentifier
     39     let maximumTransferBytes: UInt64
     40     let maximumResponseBodyBytes: Int
     41     let executionID: UUID?
     42 
     43     init(request: RadrootsBackgroundTransferRequest, executionID: UUID? = nil) {
     44         identifier = request.identifier
     45         maximumTransferBytes = request.maximumTransferBytes
     46         maximumResponseBodyBytes = request.responsePolicy.maximumBodyBytes
     47         self.executionID = executionID
     48     }
     49 
     50     init?(taskDescription: String?) {
     51         guard let taskDescription else { return nil }
     52         let components = taskDescription.split(separator: "|", omittingEmptySubsequences: false)
     53         if components.count == 5, components[0] == "radroots-transfer-v2",
     54            let executionID = UUID(uuidString: String(components[4])),
     55            let previous = Self(taskDescription: ([Self.prefix] + components[1 ... 3].map(String.init))
     56                .joined(separator: "|")) {
     57             identifier = previous.identifier
     58             maximumTransferBytes = previous.maximumTransferBytes
     59             maximumResponseBodyBytes = previous.maximumResponseBodyBytes
     60             self.executionID = executionID
     61             return
     62         }
     63         if components.count == 4,
     64            components[0] == Substring(Self.prefix),
     65            let identifier = try? RadrootsBackgroundTransferIdentifier(String(components[1])),
     66            let maximumTransferBytes = UInt64(components[2]),
     67            let maximumResponseBodyBytes = Int(components[3]),
     68            maximumTransferBytes > 0,
     69            maximumTransferBytes <= RadrootsBackgroundTransferRequest.absoluteMaximumTransferBytes,
     70            (0 ... 65536).contains(maximumResponseBodyBytes) {
     71             self.identifier = identifier
     72             self.maximumTransferBytes = maximumTransferBytes
     73             self.maximumResponseBodyBytes = maximumResponseBodyBytes
     74             executionID = nil
     75             return
     76         }
     77         guard let legacyIdentifier = try? RadrootsBackgroundTransferIdentifier(taskDescription) else {
     78             return nil
     79         }
     80         identifier = legacyIdentifier
     81         maximumTransferBytes = RadrootsBackgroundTransferRequest.defaultMaximumTransferBytes
     82         maximumResponseBodyBytes = 65536
     83         executionID = nil
     84     }
     85 
     86     var taskDescription: String {
     87         if let executionID {
     88             return "radroots-transfer-v2|\(identifier.rawValue)|\(maximumTransferBytes)|"
     89                 + "\(maximumResponseBodyBytes)|\(executionID.uuidString.lowercased())"
     90         }
     91         return "\(Self.prefix)|\(identifier.rawValue)|\(maximumTransferBytes)|\(maximumResponseBodyBytes)"
     92     }
     93 }
     94 
     95 extension RadrootsBackgroundTransferRequest {
     96     var isUpload: Bool {
     97         if case .upload = operation {
     98             return true
     99         }
    100         return false
    101     }
    102 }
    103 
    104 struct RadrootsTransferResponseError: Error {
    105     let failure: RadrootsBackgroundTransferFailure
    106 }