Skip to content

Instantly share code, notes, and snippets.

@erica
Last active February 19, 2019 23:10
Show Gist options
  • Save erica/dd1f6616b4124c588cf7 to your computer and use it in GitHub Desktop.
Save erica/dd1f6616b4124c588cf7 to your computer and use it in GitHub Desktop.
func EnumerationMemberCount<EnumType:Hashable>(eType : EnumType.Type) -> Int {
if sizeof(eType) == 0 {return 1} // throw up hands
if sizeof(eType) > 2 {fatalError("too many enumeration cases.")}
let singleByte = sizeof(eType) == 1
let min = singleByte ? 2 : 257
let max = singleByte ? 2 << 8 : 2 << 16
for hashIndex in min..<max {
switch singleByte {
case true:
if unsafeBitCast(UInt8(hashIndex), eType).hashValue == 0 {
return hashIndex
}
case false:
if unsafeBitCast(UInt16(hashIndex), eType).hashValue == 0 {
return hashIndex
}
}
}
return max
}
func EnumerationMembers<EnumType:Hashable>(eType:EnumType.Type) -> [EnumType] {
var enumMembers = [EnumType]()
let singleByte = sizeof(eType) == 1
for index in 0..<EnumerationMemberCount(EnumType) {
switch singleByte {
case true:
let member = unsafeBitCast(UInt8(index), EnumType.self)
enumMembers.append(member)
case false:
let member = unsafeBitCast(UInt16(index), EnumType.self)
enumMembers.append(member)
}
}
return enumMembers
}
public protocol EnumConvertible: Hashable {
init?(fromHash hash: Int)
static func countMembers() -> Int
static func members() -> [Self]
}
extension EnumConvertible where Self:Hashable {
internal static func fromHash(hashValue index: Int) -> Self {
let member = unsafeBitCast(UInt8(index), Self.self)
return member
}
static public func countMembers() -> Int {return EnumerationMemberCount(Self)}
static public func members() -> [Self] {return EnumerationMembers(Self)}
public init?(fromHash hash: Int) {
if hash >= Self.countMembers() {return nil}
self = Self.fromHash(hashValue: hash)
}
}
enum Planets : Int, EnumConvertible {case Mercury, Venus, Earth, Mars, Jupiter, Saturn, Neptune, Uranus, Pluto}
Planets.fromHash(hashValue: 0)
EnumerationMemberCount(Planets)
EnumerationMembers(Planets)
Planets.countMembers()
Planets.members()
enum Foo : Int, EnumConvertible {case i = 1, j = 5, k = 9}
enum Coin : EnumConvertible {case Heads, Tails}
enum Quark: String, EnumConvertible {case Up, Down, Top, Bottom, Strange, Charmed}
print(Planets.members())
print(Foo.members())
print(Coin.members())
print(Quark.members())
Quark.fromHash(hashValue: 2).rawValue
Foo.fromHash(hashValue: 0).rawValue
Foo(fromHash: 23)
Foo(fromHash: 0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment