| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973 | ////  URLEncodedFormEncoder.swift////  Copyright (c) 2019 Alamofire Software Foundation (http://alamofire.org/)////  Permission is hereby granted, free of charge, to any person obtaining a copy//  of this software and associated documentation files (the "Software"), to deal//  in the Software without restriction, including without limitation the rights//  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell//  copies of the Software, and to permit persons to whom the Software is//  furnished to do so, subject to the following conditions:////  The above copyright notice and this permission notice shall be included in//  all copies or substantial portions of the Software.////  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR//  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,//  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE//  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER//  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,//  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN//  THE SOFTWARE.//import Foundation/// An object that encodes instances into URL-encoded query strings.////// There is no published specification for how to encode collection types. By default, the convention of appending/// `[]` to the key for array values (`foo[]=1&foo[]=2`), and appending the key surrounded by square brackets for/// nested dictionary values (`foo[bar]=baz`) is used. Optionally, `ArrayEncoding` can be used to omit the/// square brackets appended to array keys.////// `BoolEncoding` can be used to configure how `Bool` values are encoded. The default behavior is to encode/// `true` as 1 and `false` as 0.////// `DateEncoding` can be used to configure how `Date` values are encoded. By default, the `.deferredToDate`/// strategy is used, which formats dates from their structure.////// `SpaceEncoding` can be used to configure how spaces are encoded. Modern encodings use percent replacement (`%20`),/// while older encodings may expect spaces to be replaced with `+`.////// This type is largely based on Vapor's [`url-encoded-form`](https://github.com/vapor/url-encoded-form) project.public final class URLEncodedFormEncoder {    /// Encoding to use for `Array` values.    public enum ArrayEncoding {        /// An empty set of square brackets ("[]") are appended to the key for every value. This is the default encoding.        case brackets        /// No brackets are appended to the key and the key is encoded as is.        case noBrackets        /// Encodes the key according to the encoding.        ///        /// - Parameter key: The `key` to encode.        /// - Returns:       The encoded key.        func encode(_ key: String) -> String {            switch self {            case .brackets: return "\(key)[]"            case .noBrackets: return key            }        }    }    /// Encoding to use for `Bool` values.    public enum BoolEncoding {        /// Encodes `true` as `1`, `false` as `0`.        case numeric        /// Encodes `true` as "true", `false` as "false". This is the default encoding.        case literal        /// Encodes the given `Bool` as a `String`.        ///        /// - Parameter value: The `Bool` to encode.        ///        /// - Returns:         The encoded `String`.        func encode(_ value: Bool) -> String {            switch self {            case .numeric: return value ? "1" : "0"            case .literal: return value ? "true" : "false"            }        }    }    /// Encoding to use for `Data` values.    public enum DataEncoding {        /// Defers encoding to the `Data` type.        case deferredToData        /// Encodes `Data` as a Base64-encoded string. This is the default encoding.        case base64        /// Encode the `Data` as a custom value encoded by the given closure.        case custom((Data) throws -> String)        /// Encodes `Data` according to the encoding.        ///        /// - Parameter data: The `Data` to encode.        ///        /// - Returns:        The encoded `String`, or `nil` if the `Data` should be encoded according to its        ///                   `Encodable` implementation.        func encode(_ data: Data) throws -> String? {            switch self {            case .deferredToData: return nil            case .base64: return data.base64EncodedString()            case let .custom(encoding): return try encoding(data)            }        }    }    /// Encoding to use for `Date` values.    public enum DateEncoding {        /// ISO8601 and RFC3339 formatter.        private static let iso8601Formatter: ISO8601DateFormatter = {            let formatter = ISO8601DateFormatter()            formatter.formatOptions = .withInternetDateTime            return formatter        }()        /// Defers encoding to the `Date` type. This is the default encoding.        case deferredToDate        /// Encodes `Date`s as seconds since midnight UTC on January 1, 1970.        case secondsSince1970        /// Encodes `Date`s as milliseconds since midnight UTC on January 1, 1970.        case millisecondsSince1970        /// Encodes `Date`s according to the ISO8601 and RFC3339 standards.        case iso8601        /// Encodes `Date`s using the given `DateFormatter`.        case formatted(DateFormatter)        /// Encodes `Date`s using the given closure.        case custom((Date) throws -> String)        /// Encodes the date according to the encoding.        ///        /// - Parameter date: The `Date` to encode.        ///        /// - Returns:        The encoded `String`, or `nil` if the `Date` should be encoded according to its        ///                   `Encodable` implementation.        func encode(_ date: Date) throws -> String? {            switch self {            case .deferredToDate:                return nil            case .secondsSince1970:                return String(date.timeIntervalSince1970)            case .millisecondsSince1970:                return String(date.timeIntervalSince1970 * 1000.0)            case .iso8601:                return DateEncoding.iso8601Formatter.string(from: date)            case let .formatted(formatter):                return formatter.string(from: date)            case let .custom(closure):                return try closure(date)            }        }    }    /// Encoding to use for keys.    ///    /// This type is derived from [`JSONEncoder`'s `KeyEncodingStrategy`](https://github.com/apple/swift/blob/6aa313b8dd5f05135f7f878eccc1db6f9fbe34ff/stdlib/public/Darwin/Foundation/JSONEncoder.swift#L128)    /// and [`XMLEncoder`s `KeyEncodingStrategy`](https://github.com/MaxDesiatov/XMLCoder/blob/master/Sources/XMLCoder/Encoder/XMLEncoder.swift#L102).    public enum KeyEncoding {        /// Use the keys specified by each type. This is the default encoding.        case useDefaultKeys        /// Convert from "camelCaseKeys" to "snake_case_keys" before writing a key.        ///        /// Capital characters are determined by testing membership in        /// `CharacterSet.uppercaseLetters` and `CharacterSet.lowercaseLetters`        /// (Unicode General Categories Lu and Lt).        /// The conversion to lower case uses `Locale.system`, also known as        /// the ICU "root" locale. This means the result is consistent        /// regardless of the current user's locale and language preferences.        ///        /// Converting from camel case to snake case:        /// 1. Splits words at the boundary of lower-case to upper-case        /// 2. Inserts `_` between words        /// 3. Lowercases the entire string        /// 4. Preserves starting and ending `_`.        ///        /// For example, `oneTwoThree` becomes `one_two_three`. `_oneTwoThree_` becomes `_one_two_three_`.        ///        /// - Note: Using a key encoding strategy has a nominal performance cost, as each string key has to be converted.        case convertToSnakeCase        /// Same as convertToSnakeCase, but using `-` instead of `_`.        /// For example `oneTwoThree` becomes `one-two-three`.        case convertToKebabCase        /// Capitalize the first letter only.        /// For example `oneTwoThree` becomes  `OneTwoThree`.        case capitalized        /// Uppercase all letters.        /// For example `oneTwoThree` becomes  `ONETWOTHREE`.        case uppercased        /// Lowercase all letters.        /// For example `oneTwoThree` becomes  `onetwothree`.        case lowercased        /// A custom encoding using the provided closure.        case custom((String) -> String)        func encode(_ key: String) -> String {            switch self {            case .useDefaultKeys: return key            case .convertToSnakeCase: return convertToSnakeCase(key)            case .convertToKebabCase: return convertToKebabCase(key)            case .capitalized: return String(key.prefix(1).uppercased() + key.dropFirst())            case .uppercased: return key.uppercased()            case .lowercased: return key.lowercased()            case let .custom(encoding): return encoding(key)            }        }        private func convertToSnakeCase(_ key: String) -> String {            convert(key, usingSeparator: "_")        }        private func convertToKebabCase(_ key: String) -> String {            convert(key, usingSeparator: "-")        }        private func convert(_ key: String, usingSeparator separator: String) -> String {            guard !key.isEmpty else { return key }            var words: [Range<String.Index>] = []            // The general idea of this algorithm is to split words on            // transition from lower to upper case, then on transition of >1            // upper case characters to lowercase            //            // myProperty -> my_property            // myURLProperty -> my_url_property            //            // It is assumed, per Swift naming conventions, that the first character of the key is lowercase.            var wordStart = key.startIndex            var searchRange = key.index(after: wordStart)..<key.endIndex            // Find next uppercase character            while let upperCaseRange = key.rangeOfCharacter(from: CharacterSet.uppercaseLetters, options: [], range: searchRange) {                let untilUpperCase = wordStart..<upperCaseRange.lowerBound                words.append(untilUpperCase)                // Find next lowercase character                searchRange = upperCaseRange.lowerBound..<searchRange.upperBound                guard let lowerCaseRange = key.rangeOfCharacter(from: CharacterSet.lowercaseLetters, options: [], range: searchRange) else {                    // There are no more lower case letters. Just end here.                    wordStart = searchRange.lowerBound                    break                }                // Is the next lowercase letter more than 1 after the uppercase?                // If so, we encountered a group of uppercase letters that we                // should treat as its own word                let nextCharacterAfterCapital = key.index(after: upperCaseRange.lowerBound)                if lowerCaseRange.lowerBound == nextCharacterAfterCapital {                    // The next character after capital is a lower case character and therefore not a word boundary.                    // Continue searching for the next upper case for the boundary.                    wordStart = upperCaseRange.lowerBound                } else {                    // There was a range of >1 capital letters. Turn those into a word, stopping at the capital before the lower case character.                    let beforeLowerIndex = key.index(before: lowerCaseRange.lowerBound)                    words.append(upperCaseRange.lowerBound..<beforeLowerIndex)                    // Next word starts at the capital before the lowercase we just found                    wordStart = beforeLowerIndex                }                searchRange = lowerCaseRange.upperBound..<searchRange.upperBound            }            words.append(wordStart..<searchRange.upperBound)            let result = words.map { range in                key[range].lowercased()            }.joined(separator: separator)            return result        }    }    /// Encoding to use for spaces.    public enum SpaceEncoding {        /// Encodes spaces according to normal percent escaping rules (%20).        case percentEscaped        /// Encodes spaces as `+`,        case plusReplaced        /// Encodes the string according to the encoding.        ///        /// - Parameter string: The `String` to encode.        ///        /// - Returns:          The encoded `String`.        func encode(_ string: String) -> String {            switch self {            case .percentEscaped: return string.replacingOccurrences(of: " ", with: "%20")            case .plusReplaced: return string.replacingOccurrences(of: " ", with: "+")            }        }    }    /// `URLEncodedFormEncoder` error.    public enum Error: Swift.Error {        /// An invalid root object was created by the encoder. Only keyed values are valid.        case invalidRootObject(String)        var localizedDescription: String {            switch self {            case let .invalidRootObject(object):                return "URLEncodedFormEncoder requires keyed root object. Received \(object) instead."            }        }    }    /// Whether or not to sort the encoded key value pairs.    ///    /// - Note: This setting ensures a consistent ordering for all encodings of the same parameters. When set to `false`,    ///         encoded `Dictionary` values may have a different encoded order each time they're encoded due to    ///       ` Dictionary`'s random storage order, but `Encodable` types will maintain their encoded order.    public let alphabetizeKeyValuePairs: Bool    /// The `ArrayEncoding` to use.    public let arrayEncoding: ArrayEncoding    /// The `BoolEncoding` to use.    public let boolEncoding: BoolEncoding    /// THe `DataEncoding` to use.    public let dataEncoding: DataEncoding    /// The `DateEncoding` to use.    public let dateEncoding: DateEncoding    /// The `KeyEncoding` to use.    public let keyEncoding: KeyEncoding    /// The `SpaceEncoding` to use.    public let spaceEncoding: SpaceEncoding    /// The `CharacterSet` of allowed (non-escaped) characters.    public var allowedCharacters: CharacterSet    /// Creates an instance from the supplied parameters.    ///    /// - Parameters:    ///   - alphabetizeKeyValuePairs: Whether or not to sort the encoded key value pairs. `true` by default.    ///   - arrayEncoding:            The `ArrayEncoding` to use. `.brackets` by default.    ///   - boolEncoding:             The `BoolEncoding` to use. `.numeric` by default.    ///   - dataEncoding:             The `DataEncoding` to use. `.base64` by default.    ///   - dateEncoding:             The `DateEncoding` to use. `.deferredToDate` by default.    ///   - keyEncoding:              The `KeyEncoding` to use. `.useDefaultKeys` by default.    ///   - spaceEncoding:            The `SpaceEncoding` to use. `.percentEscaped` by default.    ///   - allowedCharacters:        The `CharacterSet` of allowed (non-escaped) characters. `.afURLQueryAllowed` by    ///                               default.    public init(alphabetizeKeyValuePairs: Bool = true,                arrayEncoding: ArrayEncoding = .brackets,                boolEncoding: BoolEncoding = .numeric,                dataEncoding: DataEncoding = .base64,                dateEncoding: DateEncoding = .deferredToDate,                keyEncoding: KeyEncoding = .useDefaultKeys,                spaceEncoding: SpaceEncoding = .percentEscaped,                allowedCharacters: CharacterSet = .afURLQueryAllowed) {        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs        self.arrayEncoding = arrayEncoding        self.boolEncoding = boolEncoding        self.dataEncoding = dataEncoding        self.dateEncoding = dateEncoding        self.keyEncoding = keyEncoding        self.spaceEncoding = spaceEncoding        self.allowedCharacters = allowedCharacters    }    func encode(_ value: Encodable) throws -> URLEncodedFormComponent {        let context = URLEncodedFormContext(.object([]))        let encoder = _URLEncodedFormEncoder(context: context,                                             boolEncoding: boolEncoding,                                             dataEncoding: dataEncoding,                                             dateEncoding: dateEncoding)        try value.encode(to: encoder)        return context.component    }    /// Encodes the `value` as a URL form encoded `String`.    ///    /// - Parameter value: The `Encodable` value.`    ///    /// - Returns:         The encoded `String`.    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.    public func encode(_ value: Encodable) throws -> String {        let component: URLEncodedFormComponent = try encode(value)        guard case let .object(object) = component else {            throw Error.invalidRootObject("\(component)")        }        let serializer = URLEncodedFormSerializer(alphabetizeKeyValuePairs: alphabetizeKeyValuePairs,                                                  arrayEncoding: arrayEncoding,                                                  keyEncoding: keyEncoding,                                                  spaceEncoding: spaceEncoding,                                                  allowedCharacters: allowedCharacters)        let query = serializer.serialize(object)        return query    }    /// Encodes the value as `Data`. This is performed by first creating an encoded `String` and then returning the    /// `.utf8` data.    ///    /// - Parameter value: The `Encodable` value.    ///    /// - Returns:         The encoded `Data`.    ///    /// - Throws:          An `Error` or `EncodingError` instance if encoding fails.    public func encode(_ value: Encodable) throws -> Data {        let string: String = try encode(value)        return Data(string.utf8)    }}final class _URLEncodedFormEncoder {    var codingPath: [CodingKey]    // Returns an empty dictionary, as this encoder doesn't support userInfo.    var userInfo: [CodingUserInfoKey: Any] { [:] }    let context: URLEncodedFormContext    private let boolEncoding: URLEncodedFormEncoder.BoolEncoding    private let dataEncoding: URLEncodedFormEncoder.DataEncoding    private let dateEncoding: URLEncodedFormEncoder.DateEncoding    init(context: URLEncodedFormContext,         codingPath: [CodingKey] = [],         boolEncoding: URLEncodedFormEncoder.BoolEncoding,         dataEncoding: URLEncodedFormEncoder.DataEncoding,         dateEncoding: URLEncodedFormEncoder.DateEncoding) {        self.context = context        self.codingPath = codingPath        self.boolEncoding = boolEncoding        self.dataEncoding = dataEncoding        self.dateEncoding = dateEncoding    }}extension _URLEncodedFormEncoder: Encoder {    func container<Key>(keyedBy type: Key.Type) -> KeyedEncodingContainer<Key> where Key: CodingKey {        let container = _URLEncodedFormEncoder.KeyedContainer<Key>(context: context,                                                                   codingPath: codingPath,                                                                   boolEncoding: boolEncoding,                                                                   dataEncoding: dataEncoding,                                                                   dateEncoding: dateEncoding)        return KeyedEncodingContainer(container)    }    func unkeyedContainer() -> UnkeyedEncodingContainer {        _URLEncodedFormEncoder.UnkeyedContainer(context: context,                                                codingPath: codingPath,                                                boolEncoding: boolEncoding,                                                dataEncoding: dataEncoding,                                                dateEncoding: dateEncoding)    }    func singleValueContainer() -> SingleValueEncodingContainer {        _URLEncodedFormEncoder.SingleValueContainer(context: context,                                                    codingPath: codingPath,                                                    boolEncoding: boolEncoding,                                                    dataEncoding: dataEncoding,                                                    dateEncoding: dateEncoding)    }}final class URLEncodedFormContext {    var component: URLEncodedFormComponent    init(_ component: URLEncodedFormComponent) {        self.component = component    }}enum URLEncodedFormComponent {    typealias Object = [(key: String, value: URLEncodedFormComponent)]    case string(String)    case array([URLEncodedFormComponent])    case object(Object)    /// Converts self to an `[URLEncodedFormData]` or returns `nil` if not convertible.    var array: [URLEncodedFormComponent]? {        switch self {        case let .array(array): return array        default: return nil        }    }    /// Converts self to an `Object` or returns `nil` if not convertible.    var object: Object? {        switch self {        case let .object(object): return object        default: return nil        }    }    /// Sets self to the supplied value at a given path.    ///    ///     data.set(to: "hello", at: ["path", "to", "value"])    ///    /// - parameters:    ///     - value: Value of `Self` to set at the supplied path.    ///     - path: `CodingKey` path to update with the supplied value.    public mutating func set(to value: URLEncodedFormComponent, at path: [CodingKey]) {        set(&self, to: value, at: path)    }    /// Recursive backing method to `set(to:at:)`.    private func set(_ context: inout URLEncodedFormComponent, to value: URLEncodedFormComponent, at path: [CodingKey]) {        guard path.count >= 1 else {            context = value            return        }        let end = path[0]        var child: URLEncodedFormComponent        switch path.count {        case 1:            child = value        case 2...:            if let index = end.intValue {                let array = context.array ?? []                if array.count > index {                    child = array[index]                } else {                    child = .array([])                }                set(&child, to: value, at: Array(path[1...]))            } else {                child = context.object?.first { $0.key == end.stringValue }?.value ?? .object(.init())                set(&child, to: value, at: Array(path[1...]))            }        default: fatalError("Unreachable")        }        if let index = end.intValue {            if var array = context.array {                if array.count > index {                    array[index] = child                } else {                    array.append(child)                }                context = .array(array)            } else {                context = .array([child])            }        } else {            if var object = context.object {                if let index = object.firstIndex(where: { $0.key == end.stringValue }) {                    object[index] = (key: end.stringValue, value: child)                } else {                    object.append((key: end.stringValue, value: child))                }                context = .object(object)            } else {                context = .object([(key: end.stringValue, value: child)])            }        }    }}struct AnyCodingKey: CodingKey, Hashable {    let stringValue: String    let intValue: Int?    init?(stringValue: String) {        self.stringValue = stringValue        intValue = nil    }    init?(intValue: Int) {        stringValue = "\(intValue)"        self.intValue = intValue    }    init<Key>(_ base: Key) where Key: CodingKey {        if let intValue = base.intValue {            self.init(intValue: intValue)!        } else {            self.init(stringValue: base.stringValue)!        }    }}extension _URLEncodedFormEncoder {    final class KeyedContainer<Key> where Key: CodingKey {        var codingPath: [CodingKey]        private let context: URLEncodedFormContext        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding        private let dataEncoding: URLEncodedFormEncoder.DataEncoding        private let dateEncoding: URLEncodedFormEncoder.DateEncoding        init(context: URLEncodedFormContext,             codingPath: [CodingKey],             boolEncoding: URLEncodedFormEncoder.BoolEncoding,             dataEncoding: URLEncodedFormEncoder.DataEncoding,             dateEncoding: URLEncodedFormEncoder.DateEncoding) {            self.context = context            self.codingPath = codingPath            self.boolEncoding = boolEncoding            self.dataEncoding = dataEncoding            self.dateEncoding = dateEncoding        }        private func nestedCodingPath(for key: CodingKey) -> [CodingKey] {            codingPath + [key]        }    }}extension _URLEncodedFormEncoder.KeyedContainer: KeyedEncodingContainerProtocol {    func encodeNil(forKey key: Key) throws {        let context = EncodingError.Context(codingPath: codingPath,                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")        throw EncodingError.invalidValue("\(key): nil", context)    }    func encode<T>(_ value: T, forKey key: Key) throws where T: Encodable {        var container = nestedSingleValueEncoder(for: key)        try container.encode(value)    }    func nestedSingleValueEncoder(for key: Key) -> SingleValueEncodingContainer {        let container = _URLEncodedFormEncoder.SingleValueContainer(context: context,                                                                    codingPath: nestedCodingPath(for: key),                                                                    boolEncoding: boolEncoding,                                                                    dataEncoding: dataEncoding,                                                                    dateEncoding: dateEncoding)        return container    }    func nestedUnkeyedContainer(forKey key: Key) -> UnkeyedEncodingContainer {        let container = _URLEncodedFormEncoder.UnkeyedContainer(context: context,                                                                codingPath: nestedCodingPath(for: key),                                                                boolEncoding: boolEncoding,                                                                dataEncoding: dataEncoding,                                                                dateEncoding: dateEncoding)        return container    }    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type, forKey key: Key) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,                                                                         codingPath: nestedCodingPath(for: key),                                                                         boolEncoding: boolEncoding,                                                                         dataEncoding: dataEncoding,                                                                         dateEncoding: dateEncoding)        return KeyedEncodingContainer(container)    }    func superEncoder() -> Encoder {        _URLEncodedFormEncoder(context: context,                               codingPath: codingPath,                               boolEncoding: boolEncoding,                               dataEncoding: dataEncoding,                               dateEncoding: dateEncoding)    }    func superEncoder(forKey key: Key) -> Encoder {        _URLEncodedFormEncoder(context: context,                               codingPath: nestedCodingPath(for: key),                               boolEncoding: boolEncoding,                               dataEncoding: dataEncoding,                               dateEncoding: dateEncoding)    }}extension _URLEncodedFormEncoder {    final class SingleValueContainer {        var codingPath: [CodingKey]        private var canEncodeNewValue = true        private let context: URLEncodedFormContext        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding        private let dataEncoding: URLEncodedFormEncoder.DataEncoding        private let dateEncoding: URLEncodedFormEncoder.DateEncoding        init(context: URLEncodedFormContext,             codingPath: [CodingKey],             boolEncoding: URLEncodedFormEncoder.BoolEncoding,             dataEncoding: URLEncodedFormEncoder.DataEncoding,             dateEncoding: URLEncodedFormEncoder.DateEncoding) {            self.context = context            self.codingPath = codingPath            self.boolEncoding = boolEncoding            self.dataEncoding = dataEncoding            self.dateEncoding = dateEncoding        }        private func checkCanEncode(value: Any?) throws {            guard canEncodeNewValue else {                let context = EncodingError.Context(codingPath: codingPath,                                                    debugDescription: "Attempt to encode value through single value container when previously value already encoded.")                throw EncodingError.invalidValue(value as Any, context)            }        }    }}extension _URLEncodedFormEncoder.SingleValueContainer: SingleValueEncodingContainer {    func encodeNil() throws {        try checkCanEncode(value: nil)        defer { canEncodeNewValue = false }        let context = EncodingError.Context(codingPath: codingPath,                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")        throw EncodingError.invalidValue("nil", context)    }    func encode(_ value: Bool) throws {        try encode(value, as: String(boolEncoding.encode(value)))    }    func encode(_ value: String) throws {        try encode(value, as: value)    }    func encode(_ value: Double) throws {        try encode(value, as: String(value))    }    func encode(_ value: Float) throws {        try encode(value, as: String(value))    }    func encode(_ value: Int) throws {        try encode(value, as: String(value))    }    func encode(_ value: Int8) throws {        try encode(value, as: String(value))    }    func encode(_ value: Int16) throws {        try encode(value, as: String(value))    }    func encode(_ value: Int32) throws {        try encode(value, as: String(value))    }    func encode(_ value: Int64) throws {        try encode(value, as: String(value))    }    func encode(_ value: UInt) throws {        try encode(value, as: String(value))    }    func encode(_ value: UInt8) throws {        try encode(value, as: String(value))    }    func encode(_ value: UInt16) throws {        try encode(value, as: String(value))    }    func encode(_ value: UInt32) throws {        try encode(value, as: String(value))    }    func encode(_ value: UInt64) throws {        try encode(value, as: String(value))    }    private func encode<T>(_ value: T, as string: String) throws where T: Encodable {        try checkCanEncode(value: value)        defer { canEncodeNewValue = false }        context.component.set(to: .string(string), at: codingPath)    }    func encode<T>(_ value: T) throws where T: Encodable {        switch value {        case let date as Date:            guard let string = try dateEncoding.encode(date) else {                try attemptToEncode(value)                return            }            try encode(value, as: string)        case let data as Data:            guard let string = try dataEncoding.encode(data) else {                try attemptToEncode(value)                return            }            try encode(value, as: string)        default:            try attemptToEncode(value)        }    }    private func attemptToEncode<T>(_ value: T) throws where T: Encodable {        try checkCanEncode(value: value)        defer { canEncodeNewValue = false }        let encoder = _URLEncodedFormEncoder(context: context,                                             codingPath: codingPath,                                             boolEncoding: boolEncoding,                                             dataEncoding: dataEncoding,                                             dateEncoding: dateEncoding)        try value.encode(to: encoder)    }}extension _URLEncodedFormEncoder {    final class UnkeyedContainer {        var codingPath: [CodingKey]        var count = 0        var nestedCodingPath: [CodingKey] {            codingPath + [AnyCodingKey(intValue: count)!]        }        private let context: URLEncodedFormContext        private let boolEncoding: URLEncodedFormEncoder.BoolEncoding        private let dataEncoding: URLEncodedFormEncoder.DataEncoding        private let dateEncoding: URLEncodedFormEncoder.DateEncoding        init(context: URLEncodedFormContext,             codingPath: [CodingKey],             boolEncoding: URLEncodedFormEncoder.BoolEncoding,             dataEncoding: URLEncodedFormEncoder.DataEncoding,             dateEncoding: URLEncodedFormEncoder.DateEncoding) {            self.context = context            self.codingPath = codingPath            self.boolEncoding = boolEncoding            self.dataEncoding = dataEncoding            self.dateEncoding = dateEncoding        }    }}extension _URLEncodedFormEncoder.UnkeyedContainer: UnkeyedEncodingContainer {    func encodeNil() throws {        let context = EncodingError.Context(codingPath: codingPath,                                            debugDescription: "URLEncodedFormEncoder cannot encode nil values.")        throw EncodingError.invalidValue("nil", context)    }    func encode<T>(_ value: T) throws where T: Encodable {        var container = nestedSingleValueContainer()        try container.encode(value)    }    func nestedSingleValueContainer() -> SingleValueEncodingContainer {        defer { count += 1 }        return _URLEncodedFormEncoder.SingleValueContainer(context: context,                                                           codingPath: nestedCodingPath,                                                           boolEncoding: boolEncoding,                                                           dataEncoding: dataEncoding,                                                           dateEncoding: dateEncoding)    }    func nestedContainer<NestedKey>(keyedBy keyType: NestedKey.Type) -> KeyedEncodingContainer<NestedKey> where NestedKey: CodingKey {        defer { count += 1 }        let container = _URLEncodedFormEncoder.KeyedContainer<NestedKey>(context: context,                                                                         codingPath: nestedCodingPath,                                                                         boolEncoding: boolEncoding,                                                                         dataEncoding: dataEncoding,                                                                         dateEncoding: dateEncoding)        return KeyedEncodingContainer(container)    }    func nestedUnkeyedContainer() -> UnkeyedEncodingContainer {        defer { count += 1 }        return _URLEncodedFormEncoder.UnkeyedContainer(context: context,                                                       codingPath: nestedCodingPath,                                                       boolEncoding: boolEncoding,                                                       dataEncoding: dataEncoding,                                                       dateEncoding: dateEncoding)    }    func superEncoder() -> Encoder {        defer { count += 1 }        return _URLEncodedFormEncoder(context: context,                                      codingPath: codingPath,                                      boolEncoding: boolEncoding,                                      dataEncoding: dataEncoding,                                      dateEncoding: dateEncoding)    }}final class URLEncodedFormSerializer {    private let alphabetizeKeyValuePairs: Bool    private let arrayEncoding: URLEncodedFormEncoder.ArrayEncoding    private let keyEncoding: URLEncodedFormEncoder.KeyEncoding    private let spaceEncoding: URLEncodedFormEncoder.SpaceEncoding    private let allowedCharacters: CharacterSet    init(alphabetizeKeyValuePairs: Bool,         arrayEncoding: URLEncodedFormEncoder.ArrayEncoding,         keyEncoding: URLEncodedFormEncoder.KeyEncoding,         spaceEncoding: URLEncodedFormEncoder.SpaceEncoding,         allowedCharacters: CharacterSet) {        self.alphabetizeKeyValuePairs = alphabetizeKeyValuePairs        self.arrayEncoding = arrayEncoding        self.keyEncoding = keyEncoding        self.spaceEncoding = spaceEncoding        self.allowedCharacters = allowedCharacters    }    func serialize(_ object: URLEncodedFormComponent.Object) -> String {        var output: [String] = []        for (key, component) in object {            let value = serialize(component, forKey: key)            output.append(value)        }        output = alphabetizeKeyValuePairs ? output.sorted() : output        return output.joinedWithAmpersands()    }    func serialize(_ component: URLEncodedFormComponent, forKey key: String) -> String {        switch component {        case let .string(string): return "\(escape(keyEncoding.encode(key)))=\(escape(string))"        case let .array(array): return serialize(array, forKey: key)        case let .object(object): return serialize(object, forKey: key)        }    }    func serialize(_ object: URLEncodedFormComponent.Object, forKey key: String) -> String {        var segments: [String] = object.map { subKey, value in            let keyPath = "[\(subKey)]"            return serialize(value, forKey: key + keyPath)        }        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments        return segments.joinedWithAmpersands()    }    func serialize(_ array: [URLEncodedFormComponent], forKey key: String) -> String {        var segments: [String] = array.map { component in            let keyPath = arrayEncoding.encode(key)            return serialize(component, forKey: keyPath)        }        segments = alphabetizeKeyValuePairs ? segments.sorted() : segments        return segments.joinedWithAmpersands()    }    func escape(_ query: String) -> String {        var allowedCharactersWithSpace = allowedCharacters        allowedCharactersWithSpace.insert(charactersIn: " ")        let escapedQuery = query.addingPercentEncoding(withAllowedCharacters: allowedCharactersWithSpace) ?? query        let spaceEncodedQuery = spaceEncoding.encode(escapedQuery)        return spaceEncodedQuery    }}extension Array where Element == String {    func joinedWithAmpersands() -> String {        joined(separator: "&")    }}public extension CharacterSet {    /// Creates a CharacterSet from RFC 3986 allowed characters.    ///    /// RFC 3986 states that the following characters are "reserved" characters.    ///    /// - General Delimiters: ":", "#", "[", "]", "@", "?", "/"    /// - Sub-Delimiters: "!", "$", "&", "'", "(", ")", "*", "+", ",", ";", "="    ///    /// In RFC 3986 - Section 3.4, it states that the "?" and "/" characters should not be escaped to allow    /// query strings to include a URL. Therefore, all "reserved" characters with the exception of "?" and "/"    /// should be percent-escaped in the query string.    static let afURLQueryAllowed: CharacterSet = {        let generalDelimitersToEncode = ":#[]@" // does not include "?" or "/" due to RFC 3986 - Section 3.4        let subDelimitersToEncode = "!$&'()*+,;="        let encodableDelimiters = CharacterSet(charactersIn: "\(generalDelimitersToEncode)\(subDelimitersToEncode)")        return CharacterSet.urlQueryAllowed.subtracting(encodableDelimiters)    }()}
 |