When using standard enums, it’s easy to create an enum value from a string using the createByName() method:
enum MyEnum {
Alt1;
}
var alt1 = MyEnum.createByName('Alt1');
How can I do the same using enum abstracts?
Let’s say I have following…
enum abstract MyAbstractEnum(Int) {
var Alt1 = 1;
}
…where I would like to create the MyAbstractEnum.Alt1 from the string “Alt1”?
Has to be done the macro way because abstracts don’t exist at runtime, right? This code.haxe.org snippet helps me getting the underlying values, and by modifying that snippet I can also get the field names… But I haven’t figured out the rest.
Thanks, Alexander, but I want to avoid a string switch like that - If there is twenty or a hundred values in the enum abstract, the problems become obvious.
class AbstractEnumTools
{
public static macro function getValueMap(typePath: Expr): Expr
{
var type = Context.getType(typePath.toString());
switch (type.follow())
{
case TAbstract(_.get() => ab, _) if (ab.meta.has(":enum")):
var map : Array<Expr> = [];
for (field in ab.impl.get().statics.get())
{
if (field.meta.has(":enum") && field.meta.has(":impl"))
{
var fieldName = field.name;
var value = macro $typePath.$fieldName;
map.push(macro $v{fieldName} => $value);
}
}
return macro $a{map};
default:
throw new Error(type.toString() + " should be @:enum abstract", typePath.pos);
}
}
}
enum abstract MyAbstractEnum(Int)
{
var Alt1 = 1;
public static function fromStr(str: String): MyAbstractEnum
{
var valueMap = AbstractEnumTools.getValueMap(MyAbstractEnum);
return valueMap[str];
}
}