swift - How to enumerate an enum with String type? -
enum suit: string { case spades = "♠" case hearts = "♥" case diamonds = "♦" case clubs = "♣" }
for example, how can like:
for suit in suit { // suit print(suit.rawvalue) }
resulting example:
♠ ♥ ♦ ♣
i made utility function iterateenum()
iterating cases arbitrary enum
types.
here example usage:
enum suit:string { case spades = "♠" case hearts = "♥" case diamonds = "♦" case clubs = "♣" } f in iterateenum(suit) { println(f.rawvalue) }
outputs:
♠ ♥ ♦ ♣
but, only debug or test purpose: relies on several undocumented current(swift1.1) compiler behaviors. so, use @ own risk :)
here code:
func iterateenum<t: hashable>(_: t.type) -> generatorof<t> { var cast: (int -> t)! switch sizeof(t) { case 0: return generatorof(generatorofone(unsafebitcast((), t.self))) case 1: cast = { unsafebitcast(uint8(truncatingbitpattern: $0), t.self) } case 2: cast = { unsafebitcast(uint16(truncatingbitpattern: $0), t.self) } case 4: cast = { unsafebitcast(uint32(truncatingbitpattern: $0), t.self) } case 8: cast = { unsafebitcast(uint64($0), t.self) } default: fatalerror("cannot here") } var = 0 return generatorof { let next = cast(i) return next.hashvalue == i++ ? next : nil } }
the underlying idea is:
- memory representation of
enum
- excludingenum
s associated types - index of cases, when count of cases2...256
, it's identicaluint8
, when257...65536
, it'suint16
, on. so, canunsafebitcast
corresponding unsigned integer types. .hashvalue
of enum values same index of case..hashvalue
of enum values bitcasted invalid index0
added:
revised swift2 , implemented casting ideas @kametrixom's answer
func iterateenum<t: hashable>(_: t.type) -> anygenerator<t> { var = 0 return anygenerator { let next = withunsafepointer(&i) { unsafepointer<t>($0).memory } return next.hashvalue == i++ ? next : nil } }
added: revised swift3
func iterateenum<t: hashable>(_: t.type) -> anyiterator<t> { var = 0 return anyiterator { let next = withunsafepointer(to: &i) { $0.withmemoryrebound(to: t.self, capacity: 1) { $0.pointee } } if next.hashvalue != { return nil } += 1 return next } }
added: revised swift3.0.1
func iterateenum<t: hashable>(_: t.type) -> anyiterator<t> { var = 0 return anyiterator { let next = withunsafebytes(of: &i) { $0.load(as: t.self) } if next.hashvalue != { return nil } += 1 return next } }
Comments
Post a Comment