mirror of
https://github.com/LukeHagar/plexswift.git
synced 2025-12-09 12:47:44 +00:00
Regeneration
This commit is contained in:
58
Sources/Plexswift/internal/serialization/Form.swift
Normal file
58
Sources/Plexswift/internal/serialization/Form.swift
Normal file
@@ -0,0 +1,58 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
func multipartContentType(with boundary: String) -> String {
|
||||
return "multipart/form-data; boundary=\(boundary)"
|
||||
}
|
||||
|
||||
func serializeMultipartFormData(with multipartFormBodySerializable: MultipartFormBodySerializable) throws -> (boundary: String, data: Data) {
|
||||
let boundary = UUID().uuidString
|
||||
|
||||
var data = Data()
|
||||
let parameters = try multipartFormBodySerializable.serializedMultipartFormParameters(formatOverride: nil)
|
||||
parameters.forEach { parameter in
|
||||
switch parameter {
|
||||
case .value(name: let name, serialized: let serialized):
|
||||
guard let serialized else { return }
|
||||
|
||||
data.append(utf8String: "--\(boundary)\r\n")
|
||||
data.append(utf8String: "Content-Disposition: multipart/form-data; name=\"\(name)\"\r\n")
|
||||
data.append(utf8String: "Content-Type: text/plain\r\n\r\n")
|
||||
data.append(utf8String: "\(serialized)\r\n")
|
||||
case .file(name: let name, filename: let filename, data: let content):
|
||||
guard let filename, let content, let contentString = String(data: content, encoding: .ascii) else { return }
|
||||
|
||||
data.append(utf8String: "--\(boundary)\r\n")
|
||||
data.append(utf8String: "Content-Disposition: multipart/form-data; name=\"\(name)\"; filename=\"\(filename)\"\r\n")
|
||||
data.append(utf8String: "Content-Type: text/plain\r\n\r\n")
|
||||
data.append(utf8String: "\(contentString)\r\n")
|
||||
}
|
||||
}
|
||||
|
||||
data.append(utf8String: "--\(boundary)--")
|
||||
|
||||
return (boundary: boundary, data: data)
|
||||
}
|
||||
|
||||
func serializeFormData(with formBodySerializable: FormBodySerializable) throws -> Data? {
|
||||
let encoded = (try formBodySerializable.serializedFormParameters(formatOverride: nil))
|
||||
.compactMap { parameter -> (String, String)? in
|
||||
guard let serialized = parameter.serialized else { return nil }
|
||||
return (parameter.name, serialized)
|
||||
}
|
||||
.map { (name, serialized) in
|
||||
return "\(name)=\(serialized)"
|
||||
}
|
||||
.joined(separator: "&")
|
||||
|
||||
return encoded.data(using: .utf8)
|
||||
}
|
||||
|
||||
fileprivate extension Data {
|
||||
mutating func append(utf8String: String) {
|
||||
if let data = utf8String.data(using: .utf8) {
|
||||
append(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
17
Sources/Plexswift/internal/serialization/JSON.swift
Normal file
17
Sources/Plexswift/internal/serialization/JSON.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
func jsonEncoder() -> JSONEncoder {
|
||||
let jsonEncoder = JSONEncoder()
|
||||
// Sort keys to make this easier to test resulting JSON.
|
||||
jsonEncoder.outputFormatting = [.sortedKeys]
|
||||
return jsonEncoder
|
||||
}
|
||||
|
||||
func serializeEncodable(_ encodable: Encodable?) throws -> String? {
|
||||
guard let encodable else { return nil }
|
||||
|
||||
let data = try jsonEncoder().encode(encodable)
|
||||
return String(data: data, encoding: .utf8)
|
||||
}
|
||||
7
Sources/Plexswift/internal/serialization/Maps.swift
Normal file
7
Sources/Plexswift/internal/serialization/Maps.swift
Normal file
@@ -0,0 +1,7 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
func namedQueryParameters(from serializable: Serializable, name: String, format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return try serializable.serializeQueryParameters(with: format).mapKeys { _ in [name] }
|
||||
}
|
||||
102
Sources/Plexswift/internal/serialization/Parameters.swift
Normal file
102
Sources/Plexswift/internal/serialization/Parameters.swift
Normal file
@@ -0,0 +1,102 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
struct SerializedParameter {
|
||||
let name: String
|
||||
let serialized: String?
|
||||
}
|
||||
|
||||
protocol ParameterDefaults {
|
||||
func defaultSerializedPathParameter(for key: String) throws -> String?
|
||||
func defaultQueryParameter(for key: String) -> AnyValue?
|
||||
}
|
||||
|
||||
// MARK: - Serialization Types
|
||||
|
||||
protocol PathParameterSerializable {
|
||||
func serializedPathParameters(formatOverride: SerializableFormat?) throws -> [String: String]
|
||||
}
|
||||
|
||||
protocol QueryParameterSerializable {
|
||||
func serializedQueryParameters(with parameterDefaults: ParameterDefaults?, formatOverride: SerializableFormat?) throws -> [QueryParameter]
|
||||
}
|
||||
|
||||
protocol HeaderParameterSerializable {
|
||||
func serializedHeaderParameters() throws -> [SerializedParameter]
|
||||
}
|
||||
|
||||
enum MultipartFormParameter {
|
||||
case value(name: String, serialized: String?)
|
||||
case file(name: String, filename: String?, data: Data?)
|
||||
}
|
||||
|
||||
protocol MultipartFormBodySerializable {
|
||||
func serializedMultipartFormParameters(formatOverride: SerializableFormat?) throws -> [MultipartFormParameter]
|
||||
}
|
||||
|
||||
protocol FormBodySerializable {
|
||||
func serializedFormParameters(formatOverride: SerializableFormat?) throws -> [SerializedParameter]
|
||||
}
|
||||
|
||||
// MARK: - Models
|
||||
|
||||
func serializePathParameterSerializable(
|
||||
_ pathParameterSerializable: PathParameterSerializable,
|
||||
with format: SerializableFormat
|
||||
) throws -> String {
|
||||
let fields = try pathParameterSerializable
|
||||
.serializedPathParameters(formatOverride: format)
|
||||
.map { (key, value) in
|
||||
SerializedParameter(name: key, serialized: value)
|
||||
}
|
||||
.sorted { a, b in
|
||||
a.name < b.name
|
||||
}
|
||||
return serializeModel(with: fields, format: format)
|
||||
}
|
||||
|
||||
func serializeQueryParameterSerializable(
|
||||
_ queryParameterSerializable: QueryParameterSerializable,
|
||||
with format: SerializableFormat
|
||||
) throws -> String {
|
||||
let fields = try queryParameterSerializable
|
||||
.serializedQueryParameters(with: nil, formatOverride: format)
|
||||
.compactMap { queryParameter -> SerializedParameter? in
|
||||
guard let key = queryParameter.key.last else { return nil }
|
||||
return SerializedParameter(name: key, serialized: queryParameter.serialized)
|
||||
}
|
||||
return serializeModel(with: fields, format: format)
|
||||
}
|
||||
|
||||
func serializeModel(
|
||||
with fields: [SerializedParameter],
|
||||
format: SerializableFormat
|
||||
) -> String {
|
||||
return fields.map { field in
|
||||
guard let serialized = field.serialized else { return nil }
|
||||
if format.explode {
|
||||
return "\(field.name)=\(serialized)"
|
||||
} else {
|
||||
return "\(field.name)\(format.separator)\(serialized)"
|
||||
}
|
||||
}.compactMap { $0 }.joined(separator: format.separator)
|
||||
}
|
||||
|
||||
// MARK: - Maps
|
||||
|
||||
extension Dictionary: MultipartFormBodySerializable where Key == String, Value: Serializable {
|
||||
func serializedMultipartFormParameters(formatOverride: SerializableFormat?) throws -> [MultipartFormParameter] {
|
||||
return try map { key, value in
|
||||
return .value(name: key, serialized: try value.serialize(with: formatOverride ?? .multipart))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: FormBodySerializable where Key == String, Value: Serializable {
|
||||
func serializedFormParameters(formatOverride: SerializableFormat?) throws -> [SerializedParameter] {
|
||||
return try map { key, value in
|
||||
return SerializedParameter(name: key, serialized: try value.serialize(with: formatOverride ?? .form(explode: false)))
|
||||
}
|
||||
}
|
||||
}
|
||||
232
Sources/Plexswift/internal/serialization/PropertyWrappers.swift
Normal file
232
Sources/Plexswift/internal/serialization/PropertyWrappers.swift
Normal file
@@ -0,0 +1,232 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Wrappers
|
||||
|
||||
/// An internal type used to aid in serializing request data and deserializing response data.
|
||||
///
|
||||
/// > Important: This type should not be used directly.
|
||||
@propertyWrapper public struct DecimalSerialized<Value>: Codable, Serializable where Value: DoubleConvertible {
|
||||
// This property wrapper ensures that we (de)serialize values as Decimals to avoid floating-point rounding errors.
|
||||
|
||||
public var wrappedValue: Value
|
||||
|
||||
public init(wrappedValue: Value) {
|
||||
self.wrappedValue = wrappedValue
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
wrappedValue = try Value.decodeValue(with: container)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
if let double = wrappedValue.toDouble() {
|
||||
try container.encode(Decimal(double))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Serializable
|
||||
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return wrappedValue.toDouble().map { String($0) } ?? ""
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension DecimalSerialized: CustomStringConvertible where Value: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return wrappedValue.description
|
||||
}
|
||||
}
|
||||
|
||||
/// An internal type used to aid in serializing request data and deserializing response data.
|
||||
///
|
||||
/// > Important: This type should not be used directly.
|
||||
@propertyWrapper public struct DateTime<Value>: Codable, Serializable where Value: DateConvertible {
|
||||
// This property wrapper ensures that we (de)serialize Swift Dates in the correct datetime format.
|
||||
|
||||
public var wrappedValue: Value
|
||||
|
||||
public init(wrappedValue: Value) {
|
||||
self.wrappedValue = wrappedValue
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
wrappedValue = try Value.decodeValue(with: container, formatter: dateTimeFormatter)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
if let formatted = wrappedValue.formattedString(with: dateTimeFormatter) {
|
||||
try container.encode(formatted)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Serializable
|
||||
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return wrappedValue.formattedString(with: dateTimeFormatter) ?? ""
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension DateTime: CustomStringConvertible where Value: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return wrappedValue.description
|
||||
}
|
||||
}
|
||||
|
||||
/// An internal type used to aid in serializing request data and deserializing response data.
|
||||
///
|
||||
/// > Important: This type should not be used directly.
|
||||
@propertyWrapper public struct DateOnly<Value>: Codable, Serializable where Value: DateConvertible {
|
||||
// This property wrapper ensures that we (de)serialize dates in the date-only format, as Date doesn't distinguish between these types.
|
||||
|
||||
public var wrappedValue: Value
|
||||
|
||||
public init(wrappedValue: Value) {
|
||||
self.wrappedValue = wrappedValue
|
||||
}
|
||||
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
wrappedValue = try Value.decodeValue(with: container, formatter: dateOnlyFormatter)
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
if let formatted = wrappedValue.formattedString(with: dateOnlyFormatter) {
|
||||
try container.encode(formatted)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Serializable
|
||||
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return wrappedValue.formattedString(with: dateOnlyFormatter) ?? ""
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension DateOnly: CustomStringConvertible where Value: CustomStringConvertible {
|
||||
public var description: String {
|
||||
return wrappedValue.description
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Formatters
|
||||
|
||||
private let dateTimeFormatter = {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
|
||||
return dateFormatter
|
||||
}()
|
||||
|
||||
private let dateOnlyFormatter = {
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.dateFormat = "yyyy-MM-dd"
|
||||
return dateFormatter
|
||||
}()
|
||||
|
||||
// MARK: - Helpers
|
||||
|
||||
/// An internal type used to aid in serializing request data.
|
||||
///
|
||||
/// > Important: This type should not be used directly.
|
||||
public protocol DoubleConvertible {
|
||||
func toDouble() -> Double?
|
||||
static func decodeValue(with container: SingleValueDecodingContainer) throws -> Self
|
||||
}
|
||||
|
||||
extension Double: DoubleConvertible {
|
||||
public static func decodeValue(with container: SingleValueDecodingContainer) throws -> Double {
|
||||
return try container.decode(Double.self)
|
||||
}
|
||||
|
||||
public func toDouble() -> Double? {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
extension Optional: DoubleConvertible where Wrapped == Double {
|
||||
public static func decodeValue(with container: SingleValueDecodingContainer) throws -> Optional<Double> {
|
||||
if container.decodeNil() {
|
||||
return nil
|
||||
} else {
|
||||
return try container.decode(Double.self)
|
||||
}
|
||||
}
|
||||
|
||||
public func toDouble() -> Double? {
|
||||
return self
|
||||
}
|
||||
}
|
||||
|
||||
/// An internal type used to aid in serializing request data.
|
||||
///
|
||||
/// > Important: This type should not be used directly.
|
||||
public protocol DateConvertible {
|
||||
func toDate() -> Date?
|
||||
func formattedString(with formatter: DateFormatter) -> String?
|
||||
|
||||
static func decodeValue(with container: SingleValueDecodingContainer, formatter: DateFormatter) throws -> Self
|
||||
}
|
||||
|
||||
extension Date: DateConvertible {
|
||||
public static func decodeValue(with container: SingleValueDecodingContainer, formatter: DateFormatter) throws -> Date {
|
||||
let string = try container.decode(String.self)
|
||||
guard let date = formatter.date(from: string) else {
|
||||
throw DecodingError.dataCorruptedError(
|
||||
in: container,
|
||||
debugDescription: "Invalid date string value '\(string)'"
|
||||
)
|
||||
}
|
||||
return date
|
||||
}
|
||||
|
||||
public func toDate() -> Date? {
|
||||
return self
|
||||
}
|
||||
|
||||
public func formattedString(with formatter: DateFormatter) -> String? {
|
||||
return formatter.string(from: self)
|
||||
}
|
||||
}
|
||||
|
||||
extension Optional: DateConvertible where Wrapped == Date {
|
||||
public static func decodeValue(with container: SingleValueDecodingContainer, formatter: DateFormatter) throws -> Optional<Date> {
|
||||
if container.decodeNil() {
|
||||
return nil
|
||||
} else {
|
||||
let string = try container.decode(String.self)
|
||||
guard let date = formatter.date(from: string) else {
|
||||
throw DecodingError.dataCorruptedError(
|
||||
in: container,
|
||||
debugDescription: "Invalid date string value '\(string)'"
|
||||
)
|
||||
}
|
||||
return date
|
||||
}
|
||||
}
|
||||
|
||||
public func toDate() -> Date? {
|
||||
return self
|
||||
}
|
||||
|
||||
public func formattedString(with formatter: DateFormatter) -> String? {
|
||||
return self.map { formatter.string(from: $0) }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
func queryString(from queryParameters: [QueryParameter]) -> String {
|
||||
return queryParameters
|
||||
.sorted { qp1, qp2 in
|
||||
if qp1.key == qp2.key {
|
||||
return qp1.index < qp2.index
|
||||
}
|
||||
|
||||
// Lexicographically sort components.
|
||||
for (c1, c2) in zip(qp1.key, qp2.key) {
|
||||
if c1 < c2 { return true }
|
||||
else if c1 > c2 { return false }
|
||||
}
|
||||
return true
|
||||
}.compactMap { queryParam in
|
||||
guard
|
||||
let encodedName = percentEncode(string: queryParameterName(from: queryParam.key)),
|
||||
let encodedValue = percentEncode(string: queryParam.serialized)
|
||||
else { return nil }
|
||||
return "\(encodedName)=\(encodedValue)"
|
||||
}.joined(separator: "&")
|
||||
}
|
||||
|
||||
// Helps build nested and exploded query parameters.
|
||||
class QueryParameterBuilder {
|
||||
private var queryParameters: [QueryParameter] = []
|
||||
|
||||
func addQueryParameters(from serializable: Serializable?, named name: String, format: SerializableFormat, parameterDefaults: ParameterDefaults?) throws {
|
||||
guard let serializable = serializable ?? parameterDefaults?.defaultQueryParameter(for: name) else { return }
|
||||
if format.explode {
|
||||
queryParameters.append(
|
||||
contentsOf: try serializable
|
||||
.serializeQueryParameters(with: format)
|
||||
.mapKeys { parameterKey(from: $0, nameOverride: name, with: format) }
|
||||
)
|
||||
} else {
|
||||
queryParameters.append(QueryParameter(key: [name], serialized: try serializable.serialize(with: format)))
|
||||
}
|
||||
}
|
||||
|
||||
func addJSONQueryParameter(named name: String, with encodable: Encodable?) throws {
|
||||
guard let encodable, let encoded = try serializeEncodable(encodable) else { return }
|
||||
queryParameters.append(QueryParameter(key: [name], serialized: encoded))
|
||||
}
|
||||
|
||||
func build() -> [QueryParameter] {
|
||||
return queryParameters
|
||||
}
|
||||
}
|
||||
|
||||
extension Array where Element == QueryParameter {
|
||||
func mapKeys(_ f: ([String]) -> [String]) -> [QueryParameter] {
|
||||
return map { QueryParameter(key: f($0.key), serialized: $0.serialized, index: $0.index) }
|
||||
}
|
||||
}
|
||||
|
||||
private func parameterKey(from key: [String], nameOverride: String, with format: SerializableFormat) -> [String] {
|
||||
if format.isDeep {
|
||||
return [nameOverride] + key
|
||||
} else {
|
||||
return key.isEmpty ? [nameOverride] : key
|
||||
}
|
||||
}
|
||||
|
||||
private let allowedPercentEncodingCharacters = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "-."))
|
||||
|
||||
private func percentEncode(string: String) -> String? {
|
||||
return string.addingPercentEncoding(withAllowedCharacters: allowedPercentEncodingCharacters)
|
||||
}
|
||||
|
||||
private func queryParameterName(from key: [String]) -> String {
|
||||
guard let first = key.first else { return "" }
|
||||
let rest = key.dropFirst()
|
||||
return "\(first)\(rest.map { "[\($0)]" }.joined())"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
enum SecurityParameter {
|
||||
case httpBasic(username: String?, password: String?)
|
||||
case httpBearer(value: String?)
|
||||
case apiKey(name: String, value: String?)
|
||||
case oauth2(name: String, value: String?)
|
||||
case openIdConnect(name: String, value: String?)
|
||||
}
|
||||
|
||||
protocol SecurityParameterProviding {
|
||||
func securityParameters() -> [SecurityParameter]
|
||||
}
|
||||
213
Sources/Plexswift/internal/serialization/Serializable.swift
Normal file
213
Sources/Plexswift/internal/serialization/Serializable.swift
Normal file
@@ -0,0 +1,213 @@
|
||||
// Code generated by Speakeasy (https://speakeasyapi.dev). DO NOT EDIT.
|
||||
|
||||
import Foundation
|
||||
|
||||
enum QueryParameterSerializableStyle {
|
||||
case form
|
||||
case pipeDelimited
|
||||
case deepObject
|
||||
}
|
||||
|
||||
enum SerializableFormat {
|
||||
case path(explode: Bool)
|
||||
case query(style: QueryParameterSerializableStyle, explode: Bool)
|
||||
case header(explode: Bool)
|
||||
case multipart
|
||||
case form(explode: Bool)
|
||||
|
||||
var explode: Bool {
|
||||
switch self {
|
||||
case .path(let explode), .query(_, let explode), .header(let explode), .form(let explode):
|
||||
return explode
|
||||
case .multipart:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var isDeep: Bool {
|
||||
switch self {
|
||||
case .path, .header, .multipart, .form:
|
||||
return false
|
||||
case .query(let style, _):
|
||||
switch style {
|
||||
case .form, .pipeDelimited:
|
||||
return false
|
||||
case .deepObject:
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct QueryParameter {
|
||||
let key: [String]
|
||||
let serialized: String
|
||||
let index: Int
|
||||
|
||||
init(key: [String], serialized: String) {
|
||||
self.key = key
|
||||
self.serialized = serialized
|
||||
self.index = 0
|
||||
}
|
||||
|
||||
init(key: [String], serialized: String, index: Int) {
|
||||
self.key = key
|
||||
self.serialized = serialized
|
||||
self.index = index
|
||||
}
|
||||
}
|
||||
|
||||
enum SerializationError: Swift.Error {
|
||||
case failedToSerializeData
|
||||
case missingRequiredRequestBody
|
||||
case invalidSerializationParameter(type: String, format: String)
|
||||
}
|
||||
|
||||
protocol Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter]
|
||||
}
|
||||
|
||||
extension Serializable {
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Primitives
|
||||
|
||||
extension NSNull: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return "null"
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension String: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return self
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension Int: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return String(self)
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension Double: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return String(self)
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension Bool: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return String(self)
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension Data: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
guard let string = String(data: self, encoding: .ascii) else {
|
||||
throw SerializationError.failedToSerializeData
|
||||
}
|
||||
return string
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
|
||||
extension Optional: Serializable where Wrapped: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return try self?.serialize(with: format) ?? ""
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
return try self?.serializeQueryParameters(with: format) ?? []
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Collections
|
||||
|
||||
extension Array: Serializable where Element: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
return try map { try $0.serialize(with: format) }.joined(separator: format.separator)
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
if format.explode {
|
||||
return try enumerated().map { index, value in
|
||||
QueryParameter(key: [], serialized: try value.serialize(with: format), index: index)
|
||||
}
|
||||
} else {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Dictionary: Serializable where Key == String, Value: Serializable {
|
||||
func serialize(with format: SerializableFormat) throws -> String {
|
||||
// Sort by keys first to make serialization deterministic.
|
||||
return try map { key, value in
|
||||
(key, value)
|
||||
}.sorted {
|
||||
$0.0 < $1.0
|
||||
}.map { (key, value) in
|
||||
if format.explode {
|
||||
return "\(key)=\(try value.serialize(with: format))"
|
||||
} else {
|
||||
return "\(key)\(format.separator)\(try value.serialize(with: format))"
|
||||
}
|
||||
}.joined(separator: format.separator)
|
||||
}
|
||||
|
||||
func serializeQueryParameters(with format: SerializableFormat) throws -> [QueryParameter] {
|
||||
if format.explode {
|
||||
return try flatMap { key, value in
|
||||
try value.serializeQueryParameters(with: format).mapKeys { _ in [key] }
|
||||
}
|
||||
} else {
|
||||
return [QueryParameter(key: [], serialized: try serialize(with: format))]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Extensions
|
||||
|
||||
extension SerializableFormat {
|
||||
var separator: String {
|
||||
switch self {
|
||||
case .path, .header, .multipart, .form:
|
||||
return ","
|
||||
case .query(let style, _):
|
||||
switch style {
|
||||
case .form, .deepObject:
|
||||
return ","
|
||||
case .pipeDelimited:
|
||||
return "|"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user