Skip to content

Instantly share code, notes, and snippets.

@shadone
Created March 1, 2021 21:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shadone/bdf39631baabe6e6ebe7f5c0cb91cd10 to your computer and use it in GitHub Desktop.
Save shadone/bdf39631baabe6e6ebe7f5c0cb91cd10 to your computer and use it in GitHub Desktop.
/// 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