Skip to content

Instantly share code, notes, and snippets.

@farzadshbfn
Last active May 4, 2020 12:56
Show Gist options
  • Save farzadshbfn/22664e4ea226b942c4a9de6a37c0c119 to your computer and use it in GitHub Desktop.
Save farzadshbfn/22664e4ea226b942c4a9de6a37c0c119 to your computer and use it in GitHub Desktop.
struct User: Codable {
typealias Id = String
let id: Id
let cellNumber: CellNumber
let status: Status
enum Status {
case notRegistered
case registered(profile: Profile)
}
struct Profile: Codable {
let name: String
let lastName: String
let email: Email?
let isEmailVerified: Bool
private enum CodingKeys: String, CodingKey {
case name
case lastName = "last_name"
case email
case isEmailVerified = "is_email_verified"
}
}
private enum CodingKeys: String, CodingKey {
case id
case cellNumber = "cell_number"
case isRegistered = "is_registered"
case profile
}
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
id = try container.decode(Id.self, forKey: .id)
cellNumber = try container.decode(CellNumber.self, forKey: .cellNumber)
let isRegistered = try container.decode(Bool.self, forKey: .isRegistered)
status = isRegistered ? try .registered(profile: container.decode(Profile.self, forKey: .profile)) : .notRegistered
}
func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(id, forKey: .id)
try container.encode(cellNumber, forKey: .cellNumber)
switch status {
case .notRegistered:
try container.encode(false, forKey: .isRegistered)
case .registered(let profile):
try container.encode(true, forKey: .isRegistered)
try container.encode(profile, forKey: .profile)
}
}
}
struct CellNumber: Codable {
let digits: String
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawDigits = try container.decode(String.self)
// validate rawDigits by some Regex maybe? and throw appropriate errors?
// or extract CountryCode and AreaCode and save them in another way?
self.digits = rawDigits
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(digits)
}
}
struct Email: Codable {
let address: String
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawAddress = try container.decode(String.self)
// validate rawAddress by some Regex maybe? and throw appropriate errors?
self.address = rawAddress
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(address)
}
}
// MARK:- User Helper methods
extension User {
var isRegistered: Bool {
return status.isRegistered
}
var profile: Profile? {
return status.profile
}
}
// MARK:- User.Status helper methods
extension User.Status {
fileprivate var isRegistered: Bool {
switch self {
case .registered: return true
case .notRegistered: return false
}
}
fileprivate var profile: User.Profile? {
switch self {
case .registered(let profile): return profile
case .notRegistered: return nil
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment