Created
October 17, 2021 20:27
-
-
Save samrayner/d383bf2392b97227c1702c8c4eacd1e1 to your computer and use it in GitHub Desktop.
This file contains 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
/* | |
Why? | |
- Lots of RawRepresentable boilerplate for every enum that needs a .other() case | |
- The model is polluted with an invalid case which we can't define behaviour for other than logging | |
- New method lets us handle the invalid case (e.g. log it) but then only pass on valid cases to the rest of the app | |
*/ | |
import Foundation | |
enum RawExpectation<Expected: RawRepresentable> { | |
case expected(Expected) | |
case unexpected(Expected.RawValue) | |
func expected() -> Expected? { | |
switch self { | |
case .expected(let expected): | |
return expected | |
case .unexpected: | |
return nil | |
} | |
} | |
func expected(else fallback: Expected) -> Expected { | |
expected() ?? fallback | |
} | |
} | |
extension RawExpectation: RawRepresentable { | |
init(nonOptionalWithRawValue rawValue: Expected.RawValue) { | |
if let expected = Expected(rawValue: rawValue) { | |
self = .expected(expected) | |
} else { | |
self = .unexpected(rawValue) | |
} | |
} | |
init?(rawValue: Expected.RawValue) { | |
self.init(nonOptionalWithRawValue: rawValue) | |
} | |
var rawValue: Expected.RawValue { | |
switch self { | |
case .expected(let expected): | |
return expected.rawValue | |
case .unexpected(let rawValue): | |
return rawValue | |
} | |
} | |
} | |
extension RawExpectation: Decodable where Expected.RawValue: Decodable { | |
init(from decoder: Decoder) throws { | |
self.init(nonOptionalWithRawValue: try Expected.RawValue(from: decoder)) | |
} | |
} | |
extension RawExpectation: Encodable where Expected.RawValue: Encodable { | |
func encode(to encoder: Encoder) throws { | |
try rawValue.encode(to: encoder) | |
} | |
} | |
// ------------------------ | |
enum DocumentTypeOld: RawRepresentable, Codable { | |
private enum Keys { | |
static let photoId = "PHOTO_ID" | |
static let selfie = "SELFIE_PHOTO_ID" | |
static let bankStatement = "BANK_STATEMENT" | |
} | |
case photoId | |
case selfie | |
case bankStatement | |
case other(String) | |
init?(rawValue: String) { | |
switch rawValue { | |
case Keys.photoId: | |
self = .photoId | |
case Keys.selfie: | |
self = .selfie | |
case Keys.bankStatement: | |
self = .bankStatement | |
default: | |
self = .other(rawValue) | |
} | |
} | |
var rawValue: String { | |
switch self { | |
case .photoId: | |
return Keys.photoId | |
case .selfie: | |
return Keys.selfie | |
case .bankStatement: | |
return Keys.bankStatement | |
case .other(let string): | |
return string | |
} | |
} | |
} | |
enum DocumentTypeNew: String, Codable, CaseIterable { | |
case photoId = "PHOTO_ID" | |
case selfie = "SELFIE_PHOTO_ID" | |
case bankStatement = "BANK_STATEMENT" | |
} | |
struct Response: Codable { | |
let documentTypeOld: DocumentTypeOld | |
let documentTypeNew: RawExpectation<DocumentTypeNew> | |
} | |
let response = try JSONDecoder().decode( | |
Response.self, | |
from: """ | |
{ | |
"documentTypeOld": "PHOTO_ID", | |
"documentTypeNew": "BANK_STATEMENT" | |
} | |
""".data(using: .utf8)! | |
) | |
switch response.documentTypeOld { | |
case .selfie, .bankStatement, .photoId: | |
print("Expected doctype: \(response.documentTypeOld.rawValue)") | |
case .other(let rawValue): | |
print("Unexpected doctype: \(rawValue)") | |
} | |
switch response.documentTypeNew { | |
case .expected(let docType): | |
print("Expected doctype: \(docType.rawValue)") | |
case .unexpected(let rawValue): | |
print("Unexpected doctype: \(rawValue)") | |
} | |
func docTypeOldOrNil() -> DocumentTypeOld? { | |
switch response.documentTypeOld { | |
case .selfie, .bankStatement, .photoId: | |
return response.documentTypeOld | |
case .other(_): | |
return nil | |
} | |
} | |
func docTypeNewOrNil() -> DocumentTypeNew? { | |
response.documentTypeNew.expected() | |
} | |
print(docTypeOldOrNil()) | |
print(docTypeNewOrNil()) | |
print(String(data: try JSONEncoder().encode(response), encoding: .utf8)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment