Created
March 1, 2021 21:01
-
-
Save shadone/bdf39631baabe6e6ebe7f5c0cb91cd10 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A convenience wrapper allowing to define Decodable properties of type enum that can contain yet unknown values. | |
/// | |
/// e.g. | |
/// ``` | |
/// enum Color: String, Decodable, RawRepresentable { | |
/// case red | |
/// case cherryRed = "#dd0000" | |
/// case green | |
/// } | |
/// | |
/// struct MyNetworkModel: Decodable { | |
/// // can be decoded from JSON: | |
/// // { | |
/// // "color": "pink" | |
/// // } | |
/// var color: ValueOrUnknown<Color> | |
/// } | |
/// ``` | |
public enum ValueOrUnknown<Value: Decodable & RawRepresentable>: Decodable, RawRepresentable | |
where Value.RawValue: Decodable | |
{ | |
public typealias RawValue = Value.RawValue | |
case value(Value) | |
case unknown(RawValue) | |
/// Return a known value if present. | |
public var value: Value? { | |
switch self { | |
case let .value(value): | |
return value | |
case .unknown: | |
return nil | |
} | |
} | |
public init?(rawValue: Value.RawValue) { | |
if let value = Value(rawValue: rawValue) { | |
self = .value(value) | |
} else { | |
self = .unknown(rawValue) | |
} | |
} | |
public var rawValue: Value.RawValue { | |
switch self { | |
case let .value(value): | |
return value.rawValue | |
case let .unknown(rawValue): | |
return rawValue | |
} | |
} | |
public init(from decoder: Decoder) throws { | |
let container = try decoder.singleValueContainer() | |
if let value = try? container.decode(Value.self) { | |
self = .value(value) | |
} else { | |
let value = try container.decode(RawValue.self) | |
self = .unknown(value) | |
} | |
} | |
} | |
/// Optional conformance to Encodable. | |
extension ValueOrUnknown: Encodable where Value: Codable & RawRepresentable, Value.RawValue: Encodable { | |
public func encode(to encoder: Encoder) throws { | |
var container = encoder.singleValueContainer() | |
switch self { | |
case let .value(value): | |
try container.encode(value) | |
case let .unknown(rawValue): | |
try container.encode(rawValue) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment