Skip to content
This repository was archived by the owner on Nov 16, 2020. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion Sources/URLEncodedForm/Codable/URLEncodedFormEncoder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,22 @@
/// See [Mozilla's](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/POST) docs for more information about
/// url-encoded forms.
public final class URLEncodedFormEncoder: DataEncoder {
/// The formatting of the output data.
public struct OutputFormatting : OptionSet {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON coder calls it "writing options". We should probably follow suit.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we're looking at different things? This code is copied from https://github.com/apple/swift/blob/master/stdlib/public/SDK/Foundation/JSONEncoder.swift where it is called:

/// The output format to produce. Defaults to `[]`.
open var outputFormatting: OutputFormatting = []

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small change here:

- OutputFormatting : OptionSet
+ OutputFormatting: OptionSet

/// The format's default value.
public let rawValue: UInt

/// Creates an OutputFormatting value with the given raw value.
public init(rawValue: UInt) {
self.rawValue = rawValue
}

/// Produce output with dictionary keys sorted in lexicographic order.
public static let sortedKeys = OutputFormatting(rawValue: 1 << 1)
}

public var outputFormatting: OutputFormatting = []
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Vapor style is to set all properties in the init method. We try to avoid default properties on members since they can be easy to miss when refactoring.


/// Create a new `URLEncodedFormEncoder`.
public init() {}

Expand All @@ -28,7 +44,7 @@ public final class URLEncodedFormEncoder: DataEncoder {
let context = URLEncodedFormDataContext(.dict([:]))
let encoder = _URLEncodedFormEncoder(context: context, codingPath: [])
try encodable.encode(to: encoder)
let serializer = URLEncodedFormSerializer()
let serializer = URLEncodedFormSerializer(sortedKeys: self.outputFormatting.contains(.sortedKeys))
guard case .dict(let dict) = context.data else {
throw URLEncodedFormError(
identifier: "invalidTopLevel",
Expand Down
30 changes: 24 additions & 6 deletions Sources/URLEncodedForm/Data/URLEncodedFormSerializer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,37 @@ import Bits
/// Converts `[String: URLEncodedFormData]` structs to `Data`.
final class URLEncodedFormSerializer {
/// Default form url encoded serializer.
static let `default` = URLEncodedFormSerializer()
static let `default` = URLEncodedFormSerializer(sortedKeys: false)

private var sortedKeys: Bool
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing comment


/// Create a new form-urlencoded data serializer.
init() {}
init(sortedKeys: Bool) {
self.sortedKeys = sortedKeys
}

/// Serializes the data.
func serialize(_ URLEncodedFormEncoded: [String: URLEncodedFormData]) throws -> Data {
var data: [Data] = []
for (key, val) in URLEncodedFormEncoded {
let key = try key.urlEncodedFormEncoded()
let subdata = try serialize(val, forKey: key)
data.append(subdata)

if self.sortedKeys {
let elements = URLEncodedFormEncoded.sorted { (left, right) -> Bool in
return left.key.compare(right.key, options: [.numeric, .caseInsensitive, .forcedOrdering]) == .orderedAscending
}

for (key, val) in elements {
let key = try key.urlEncodedFormEncoded()
let subdata = try serialize(val, forKey: key)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way we can reduce code dupe here?

data.append(subdata)
}
} else {
for (key, val) in URLEncodedFormEncoded {
let key = try key.urlEncodedFormEncoded()
let subdata = try serialize(val, forKey: key)
data.append(subdata)
}
}

return data.joinedWithAmpersands()
}

Expand Down