1 module nxt.enum_ex; 2 3 @safe: 4 5 /** Enumeration wrapper that uses optimized conversion to string (via `toString` 6 * member). 7 * 8 * See_Also: https://forum.dlang.org/thread/ppndhxvzayedgpbjculm@forum.dlang.org?page=1 9 * 10 * TODO: Move logic to `std.conv.to`. 11 */ 12 struct Enum(E) 13 if (is(E == enum)) 14 { 15 @property string toString() @safe pure nothrow @nogc 16 { 17 return toStringFaster(_enum); 18 } 19 E _enum; // the wrapped enum 20 alias _enum this; 21 } 22 23 /// 24 @safe pure unittest 25 { 26 enum X { a, 27 b, 28 _b = b // enumerator alias 29 } 30 alias EnumX = Enum!X; 31 assert(EnumX(X.a).toString == "a"); 32 assert(EnumX(X.b).toString == "b"); 33 assert(EnumX(X._b).toString == "b"); // alias encodes to original 34 } 35 36 /** Fast and more generic implementation of `std.conv.to` for enumerations. 37 */ 38 string toStringFaster(T)(const scope T value) @safe pure nothrow @nogc 39 if (is(T == enum)) 40 { 41 import std.meta : AliasSeq; 42 /* TODO: skip wrapping in `AliasSeq` when `allMembers` can be iterated 43 * directly when a bug in compiler has been fixed */ 44 alias members = AliasSeq!(__traits(allMembers, T)); 45 final switch (value) 46 { 47 static foreach (index, member; members) 48 { 49 static if (index == 0 || 50 (__traits(getMember, T, members[index - 1]) != 51 __traits(getMember, T, member))) 52 { 53 case __traits(getMember, T, member): 54 return member; 55 } 56 } 57 } 58 } 59 60 /// 61 @safe pure nothrow @nogc unittest 62 { 63 enum E { unknown, x, y, z, } 64 assert(E.x.toStringFaster == "x"); 65 assert(E.y.toStringFaster == "y"); 66 assert(E.z.toStringFaster == "z"); 67 } 68 69 /** Faster implementation of `std.conv.to` for enumerations with no aliases. 70 */ 71 string toStringNonAliases(T)(const scope T value) @safe pure nothrow @nogc 72 if (is(T == enum)) // TODO: check for no aliases 73 { 74 final switch (value) 75 { 76 static foreach (member; __traits(allMembers, T)) 77 { 78 case __traits(getMember, T, member): 79 return member; 80 } 81 } 82 } 83 84 /// 85 @safe pure nothrow @nogc unittest 86 { 87 enum E { unknown, x, y, z, } 88 assert(E.x.toStringNonAliases == "x"); 89 assert(E.y.toStringNonAliases == "y"); 90 assert(E.z.toStringNonAliases == "z"); 91 }