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