OrOther is a macro that adds a "blank" .other(_:) case to any enum. All that's needed is to create an empty enum, add a private nested enum called Options with an explicit raw value type, add the explicit cases you want, then tack @OrOther onto the primary enum.
OrOther will automatically synthesize the any enum cases you add to Options, then add an extra .other(_:) case. The .other(_:) case has an associated value of the same type as the Options enum's raw value.
It also automatically synthesizes conformace to RawRepresentable for the attached enum, by adding a synthesized computed rawValue property and init(rawValue:) initializer:
rawValuereturns therawValueof the matching case from the nestedOptionsenum, unless it's.other, in which case, the associated value is returned.init(rawValue:)is non-failable, as it first tries to match therawValueto that of theOptionsenum and return the matching case. If there isn't a matching case inOptions, it returnsrawValueas the associated value of an.othercase.
You can then add other protocols to your primary enum as you'd like (e.g. adding Codable to EnumTest in the example below).
Additionally, due to macros not being able to add an extension for a private type, you cannot make the primary enum private. The only workaround as of now is to explictly conform the primary enum to RawRepresentable.
@OrOther
enum EnumTest: Codable {
private enum Options: String {
case a
case b
case c, d, e, f
}
}enum EnumTest {
private enum Options: String { ... }
typealias RawValue = String
case a, b, c, d, e, f, other(String)
var rawValue: RawValue {
switch self {
case .a:
return Options.a.rawValue
case .b:
return Options.b.rawValue
case .c:
return Options.c.rawValue
case .d:
return Options.d.rawValue
case .e:
return Options.e.rawValue
case .f:
return Options.f.rawValue
case .other(let string):
return string
}
}
init(rawValue: RawValue) {
if let this = Options(rawValue: rawValue) {
switch this {
case .a:
self = .a
case .b:
self = .b
case .c:
self = .c
case .d:
self = .d
case .e:
self = .e
case .f:
self = .f
}
} else {
self = .other(rawValue)
}
}
}The following protocols can be explicitly added to the primary enum, and @OrOther its conformance will be automatically synthesized:
EquatableHashableEncodable/Decodable/CodableCaseIterable