// // Parameter.swift // Pachyderm // // Created by Shadowfacts on 9/8/18. // Copyright © 2018 Shadowfacts. All rights reserved. // import Foundation struct Parameter: Sendable { let name: String let value: String? } precedencegroup ParameterizationPrecedence { associativity: left higherThan: AdditionPrecedence } infix operator => : ParameterizationPrecedence extension String { static func =>(name: String, value: String?) -> Parameter { return Parameter(name: name, value: value) } static func =>(name: String, value: Bool?) -> Parameter { return Parameter(name: name, value: value?.description) } static func =>(name: String, value: Int?) -> Parameter { return Parameter(name: name, value: value?.description) } static func =>(name: String, value: Date?) -> Parameter { if let value = value { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] let string = formatter.string(from: value) return Parameter(name: name, value: string) } else { return Parameter(name: name, value: nil) } } static func =>(name: String, value: TimeInterval?) -> Parameter { return name => (value == nil ? nil : Int(value!)) } static func =>(name: String, focus: (Float, Float)?) -> Parameter { guard let focus = focus else { return Parameter(name: name, value: nil) } return Parameter(name: name, value: "\(focus.0),\(focus.1)") } static func =>(name: String, values: [String]?) -> [Parameter] { guard let values = values else { return [] } let name = "\(name)[]" return values.map { Parameter(name: name, value: $0) } } static func =>(name: String, values: [Int]) -> [Parameter] { return name => values.map { $0.description } } } extension Parameter: CustomStringConvertible { var description: String { if let value = value { return "\(name)=\(value)" } else { return name } } } extension Array where Element == Parameter { var urlEncoded: String { return compactMap { guard let value = $0.value, let escapedValue = value.addingPercentEncoding(withAllowedCharacters: .alphanumerics) else { return nil } return "\($0.name)=\(escapedValue)" }.joined(separator: "&") } var queryItems: [URLQueryItem] { return compactMap { guard let value = $0.value else { return nil } return URLQueryItem(name: $0.name, value: value) } } }