// // XCallbackURL.swift // Tusker // // Created by Shadowfacts on 9/23/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import Foundation struct XCallbackURLSpec { let path: String let arguments: [String: Bool] let handle: (XCallbackURL) -> Bool init(path: String, arguments: [String: Bool], handle: @escaping (XCallbackURL) -> Bool) { self.path = path self.arguments = arguments self.handle = handle } } struct XCallbackURL { let path: String let arguments: [String: String] let success: URL? let error: URL? let cancel: URL? init(spec: XCallbackURLSpec, components: URLComponents) { self.path = spec.path let queryItems = components.queryItems! self.arguments = spec.arguments.reduce(into: [String: String](), { (result, el) in if let value = queryItems.first(where: { $0.name == el.key })?.value { result[el.key] = value } }) success = queryItems.first(where: { $0.name == "x-success" }).flatMap { $0.value }.flatMap { URL(string: $0) } error = queryItems.first(where: { $0.name == "x-error" }).flatMap { $0.value }.flatMap { URL(string: $0) } cancel = queryItems.first(where: { $0.name == "x-cancel" }).flatMap { $0.value }.flatMap { URL(string: $0) } } } extension XCallbackURLSpec { func matches(_ components: URLComponents) -> Bool { return path == components.path && arguments.matches(components) } } extension Dictionary where Key == String, Value == Bool { func matches(_ components: URLComponents) -> Bool { for (name, optional) in self { if (!optional && components.queryItems?.first(where: { $0.name == name }) == nil) { return false } } return true } }