Skip to content

Instantly share code, notes, and snippets.

@tapoton
Created May 15, 2025 14:27
Show Gist options
  • Select an option

  • Save tapoton/6664c35629923b6558635c7a1bd82a2f to your computer and use it in GitHub Desktop.

Select an option

Save tapoton/6664c35629923b6558635c7a1bd82a2f to your computer and use it in GitHub Desktop.
Resilient enum wrapper
public enum Resilient<T: RawRepresentable> {
case known(T)
case unknown(T.RawValue)
public var known: T? {
switch self {
case .known(let value): value
case .unknown: nil
}
}
}
extension Resilient: RawRepresentable {
public var rawValue: T.RawValue {
switch self {
case .known(let value): value.rawValue
case .unknown(let rawValue): rawValue
}
}
public init(rawValue: T.RawValue) {
self = if let value = T(rawValue: rawValue) {
.known(value)
} else {
.unknown(rawValue)
}
}
}
extension Resilient: Equatable where T.RawValue: Equatable {
public static func == (lhs: Resilient, rhs: Resilient) -> Bool {
lhs.rawValue == rhs.rawValue
}
public static func ~= (lhs: Resilient, rhs: T) -> Bool {
lhs.rawValue == rhs.rawValue
}
}
public func ~= <T>(lhs: T, rhs: Resilient<T>) -> Bool where T.RawValue: Equatable {
lhs.rawValue == rhs.rawValue
}
extension Resilient: Hashable where T.RawValue: Hashable {
public func hash(into hasher: inout Hasher) {
hasher.combine(rawValue)
}
}
extension Resilient: Decodable where T.RawValue: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let rawValue = try container.decode(T.RawValue.self)
self.init(rawValue: rawValue)
}
}
extension Resilient: Encodable where T.RawValue: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(rawValue)
}
}
extension Resilient: Sendable where T: Sendable, T.RawValue: Sendable {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment