diff --git a/Sources/Postie/Query/QueryItem.swift b/Sources/Postie/Query/QueryItem.swift index 574cdfd..2e56dbb 100644 --- a/Sources/Postie/Query/QueryItem.swift +++ b/Sources/Postie/Query/QueryItem.swift @@ -5,7 +5,6 @@ internal protocol QueryItemProtocol { /// Path parameter value which should be serialized and appended to the URL var untypedValue: QueryItemValue { get } - } @propertyWrapper @@ -18,67 +17,95 @@ public struct QueryItem where T: QueryItemValue { self.wrappedValue = wrappedValue } - public init(defaultValue: T) { - self.wrappedValue = defaultValue - } - - public init(name: String?, defaultValue: T) { + public init(name: String? = nil, defaultValue: T) { self.name = name - self.wrappedValue = defaultValue + wrappedValue = defaultValue } } +// MARK: - Encodable + +extension QueryItem: Encodable where T: Encodable {} + +// MARK: - QueryItemProtocol + extension QueryItem: QueryItemProtocol { var untypedValue: QueryItemValue { - self.wrappedValue + wrappedValue } } -extension QueryItem where T == String { +public extension QueryItem where T == Bool { - public init(name: String?) { + init(name: String?) { self.name = name - self.wrappedValue = "" + wrappedValue = false } } -extension QueryItem where T == String? { +public extension QueryItem where T == Bool? { - public init(name: String?) { + init(name: String?) { self.name = name - self.wrappedValue = nil + wrappedValue = nil } } -extension QueryItem where T == Int? { +public extension QueryItem where T == Double { - public init(name: String?) { + init(name: String?) { self.name = name - self.wrappedValue = nil + wrappedValue = .zero } } -extension QueryItem where T == Bool? { +public extension QueryItem where T == Double? { - public init(name: String?) { + init(name: String?) { self.name = name - self.wrappedValue = nil + wrappedValue = nil } } -extension QueryItem: Encodable where T: Encodable {} +public extension QueryItem where T == Int? { + + init(name: String?) { + self.name = name + wrappedValue = nil + } +} + +public extension QueryItem where T == String { + + init(name: String?) { + self.name = name + wrappedValue = "" + } +} + +public extension QueryItem where T == String? { + + init(name: String?) { + self.name = name + wrappedValue = nil + } +} + +// MARK: - OptionalType public protocol OptionalType { associatedtype Wrapped static var none: Self { get } } +// MARK: - Optional + OptionalType + extension Optional: OptionalType {} -extension QueryItem where T: OptionalType, T.Wrapped: RawRepresentable { +public extension QueryItem where T: OptionalType, T.Wrapped: RawRepresentable { - public init(name: String?) { + init(name: String?) { self.init(defaultValue: .none) self.name = name } diff --git a/Sources/Postie/Query/QueryItemValue.swift b/Sources/Postie/Query/QueryItemValue.swift index 14d956b..afa453b 100644 --- a/Sources/Postie/Query/QueryItemValue.swift +++ b/Sources/Postie/Query/QueryItemValue.swift @@ -7,10 +7,29 @@ public protocol QueryItemValue { func iterateCollection(_ iterator: (QueryItemValue) -> Void) } -extension String: QueryItemValue { +// MARK: - Array + QueryItemValue + +extension Array: QueryItemValue where Element: QueryItemValue { public var serializedQueryItem: String? { - self + fatalError("This method should not be called. Multiple query items should be added to the query individually") + } + + public var isCollection: Bool { + return true + } + + public func iterateCollection(_ iterator: (QueryItemValue) -> Void) { + forEach(iterator) + } +} + +// MARK: - Bool + QueryItemValue + +extension Bool: QueryItemValue { + + public var serializedQueryItem: String? { + self ? "true" : "false" } public var isCollection: Bool { false } @@ -20,10 +39,12 @@ extension String: QueryItemValue { } } -extension Int: QueryItemValue { +// MARK: - Double + QueryItemValue + +extension Double: QueryItemValue { public var serializedQueryItem: String? { - self.description + description } public var isCollection: Bool { false } @@ -33,10 +54,12 @@ extension Int: QueryItemValue { } } -extension Bool: QueryItemValue { +// MARK: - Int + QueryItemValue + +extension Int: QueryItemValue { public var serializedQueryItem: String? { - self ? "true" : "false" + description } public var isCollection: Bool { false } @@ -46,39 +69,49 @@ extension Bool: QueryItemValue { } } -extension Optional: QueryItemValue where Wrapped: QueryItemValue { +// MARK: - String + QueryItemValue + +extension String: QueryItemValue { public var serializedQueryItem: String? { - guard let value = self else { return nil } - return value.serializedQueryItem + self } - public var isCollection: Bool { - guard let value = self else { return false } - return value.isCollection - } + public var isCollection: Bool { false } public func iterateCollection(_ iterator: (QueryItemValue) -> Void) { - guard let value = self else { return } - return value.iterateCollection(iterator) + fatalError("Not supported") } } -extension Array: QueryItemValue where Element: QueryItemValue { +// MARK: - Optional + QueryItemValue + +extension Optional: QueryItemValue where Wrapped: QueryItemValue { public var serializedQueryItem: String? { - fatalError("This method should not be called. Multiple query items should be added to the query individually") + guard let value = self else { + return nil + } + return value.serializedQueryItem } public var isCollection: Bool { - return true + guard let value = self else { + return false + } + return value.isCollection } public func iterateCollection(_ iterator: (QueryItemValue) -> Void) { - forEach(iterator) + guard let value = self else { + return + } + return value.iterateCollection(iterator) } } +// MARK: - Set + QueryItemValue + extension Set: QueryItemValue where Element: QueryItemValue { public var serializedQueryItem: String? { @@ -94,17 +127,17 @@ extension Set: QueryItemValue where Element: QueryItemValue { } } -extension QueryItemValue where Self: RawRepresentable, RawValue: QueryItemValue { +public extension QueryItemValue where Self: RawRepresentable, RawValue: QueryItemValue { - public var serializedQueryItem: String? { - self.rawValue.serializedQueryItem + var serializedQueryItem: String? { + rawValue.serializedQueryItem } - public var isCollection: Bool { - self.rawValue.isCollection + var isCollection: Bool { + rawValue.isCollection } - public func iterateCollection(_ iterator: (QueryItemValue) -> Void) { - self.rawValue.iterateCollection(iterator) + func iterateCollection(_ iterator: (QueryItemValue) -> Void) { + rawValue.iterateCollection(iterator) } } diff --git a/Sources/Postie/Strategies/Headers/DefaultHeaderStrategy.swift b/Sources/Postie/Strategies/Headers/DefaultHeaderStrategy.swift index 9a0898b..7ed0f04 100644 --- a/Sources/Postie/Strategies/Headers/DefaultHeaderStrategy.swift +++ b/Sources/Postie/Strategies/Headers/DefaultHeaderStrategy.swift @@ -2,23 +2,23 @@ import Foundation public struct DefaultHeaderStrategy: ResponseHeaderDecodingStrategy { - public typealias RawValue = String + public typealias RawValue = String - public static func decode(decoder: Decoder) throws -> RawValue { - guard let key = decoder.codingPath.last?.stringValue else { - throw ResponseHeaderDecodingError.missingCodingKey - } - // Check if the decoder is response decoder, otherwise fall back to default decoding logic - guard let responseDecoding = decoder as? ResponseDecoding else { - return try RawValue(from: decoder) - } - // Transform dash separator to camelCase - guard let value = responseDecoding.valueForHeaderCaseInsensitive(key) else { - throw DecodingError.valueNotFound(RawValue.self, DecodingError.Context( - codingPath: decoder.codingPath, - debugDescription: "Missing value for case-insensitive header key: \(key)" - )) - } - return value + public static func decode(decoder: Decoder) throws -> RawValue { + guard let key = decoder.codingPath.last?.stringValue else { + throw ResponseHeaderDecodingError.missingCodingKey } + // Check if the decoder is response decoder, otherwise fall back to default decoding logic + guard let responseDecoding = decoder as? ResponseDecoding else { + return try RawValue(from: decoder) + } + // Transform dash separator to camelCase + guard let value: RawValue = responseDecoding.valueForHeaderCaseInsensitive(key) else { + throw DecodingError.valueNotFound(RawValue.self, DecodingError.Context( + codingPath: decoder.codingPath, + debugDescription: "Missing value for case-insensitive header key: \(key)" + )) + } + return value + } }