Repository: vapor/vapor
File: Sources/Vapor/URLEncodedForm/URLEncodedFormDecoder.swift (Swift)

Code before:
///     print(data) // "name=Vapor&age=3"
///     let user = try URLEncodedFormDecoder().decode(User.self, from: data)
///     print(user) // User
///
/// URL-encoded forms are commonly used by websites to send form data via POST requests. This encoding is relatively
/// efficient for small amounts of data but must be percent-encoded.  `multipart/form-data` is more efficient for sending
/// large data blobs like files.
///
/// See [Mozilla's](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) docs for more information about
/// url-encoded forms.
public struct URLEncodedFormDecoder: ContentDecoder, URLQueryDecoder {
    /// Used to capture URLForm Coding Configuration used for decoding
    public struct Configuration {
        /// Supported date formats
        public enum DateFormat {
            /// Seconds since 1 January 1970 00:00:00 UTC
            case unixTimestamp
            /// ISO 8601 formatted date
            case iso8601
            /// Using custom callback
            case custom((Decoder) throws -> Date)
        }

        let boolFlags: Bool
        let arraySeparators: [Character]
        let dateFormats: [DateFormat]
        /// Creates a new `URLEncodedFormCodingConfiguration`.
        /// - parameters:
        ///     - boolFlags: Set to `true` allows you to parse `flag1&flag2` as boolean variables
        ///                  where object with variable `flag1` and `flag2` would decode to `true`
        ///                  or `false` depending on if the value was present or not. If this flag is set to
        ///                  true, it will always resolve for an optional `Bool`.
        ///     - arraySeparators: Uses these characters to decode arrays. If set to `,`, `arr=v1,v2` would
        ///                        populate a key named `arr` of type `Array` to be decoded as `["v1", "v2"]`
        ///     - dateFormats: Date formats used to decode a date. Date formats are tried in the order provided.
        ///                    Defaults to `[.timeIntervalSince1970, .iso8601]`
        public init(
            boolFlags: Bool = true,
            arraySeparators: [Character] = [",", "|"],
            dateFormats: [DateFormat] = [.unixTimestamp, .iso8601]
        ) {
            self.boolFlags = boolFlags
            self.arraySeparators = arraySeparators
            self.dateFormats = dateFormats
        }
    }


    /// The underlying `URLEncodedFormEncodedParser`
    private let parser: URLEncodedFormParser


Review comment (suggestion):
I think we should try and copy JSONDecoder here as much as possible: https://developer.apple.com/documentation/foundation/jsondecoder/datedecodingstrategy

Code after:
///     print(data) // "name=Vapor&age=3"
///     let user = try URLEncodedFormDecoder().decode(User.self, from: data)
///     print(user) // User
///
/// URL-encoded forms are commonly used by websites to send form data via POST requests. This encoding is relatively
/// efficient for small amounts of data but must be percent-encoded.  `multipart/form-data` is more efficient for sending
/// large data blobs like files.
///
/// See [Mozilla's](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) docs for more information about
/// url-encoded forms.
public struct URLEncodedFormDecoder: ContentDecoder, URLQueryDecoder {
    /// Used to capture URLForm Coding Configuration used for decoding
    public struct Configuration {
        /// Supported date formats
        public enum DateDecodingStrategy {
            /// Seconds since 1 January 1970 00:00:00 UTC (Unix Timestamp)
            case secondsSince1970
            /// ISO 8601 formatted date
            case iso8601
            /// Using custom callback
            case custom((Decoder) throws -> Date)
        }

        let boolFlags: Bool
        let arraySeparators: [Character]
        let dateDecodingStrategy: DateDecodingStrategy
        /// Creates a new `URLEncodedFormCodingConfiguration`.
        /// - parameters:
        ///     - boolFlags: Set to `true` allows you to parse `flag1&flag2` as boolean variables
        ///                  where object with variable `flag1` and `flag2` would decode to `true`
        ///                  or `false` depending on if the value was present or not. If this flag is set to
        ///                  true, it will always resolve for an optional `Bool`.
        ///     - arraySeparators: Uses these characters to decode arrays. If set to `,`, `arr=v1,v2` would
        ///                        populate a key named `arr` of type `Array` to be decoded as `["v1", "v2"]`
        ///     - dateDecodingStrategy: Date format used to decode a date. Date formats are tried in the order provided
        public init(
            boolFlags: Bool = true,
            arraySeparators: [Character] = [",", "|"],
            dateDecodingStrategy: DateDecodingStrategy = .secondsSince1970
        ) {
            self.boolFlags = boolFlags
            self.arraySeparators = arraySeparators
            self.dateDecodingStrategy = dateDecodingStrategy
        }
    }


    /// The underlying `URLEncodedFormEncodedParser`
    private let parser: URLEncodedFormParser

    private let configuration: Configuration