🔧
Haxeでabstract enumに値が存在するかを判定するマクロ
Get all values of an @:enum abstract - Macros - Haxe programming language cookbook の改編版。
例えばこんな感じのabstract enumにsha1
が存在するかを判定するのに使う。
// hxnodejsから拝借
// https://github.com/HaxeFoundation/hxnodejs/blob/c9450595b2337587bcdaeacf159019531925f25d/src/js/node/Crypto.hx#L39C1-L45C1
enum abstract CryptoAlgorithm(String) from String to String {
var SHA1 = "sha1";
var MD5 = "md5";
var SHA256 = "sha256";
var SHA512 = "sha512";
}
#if macro
import haxe.macro.Context;
import haxe.macro.Expr;
using haxe.macro.Tools;
#end
/**
`enum abstract` 型に指定した値が存在するかを判定する switch 式を生成します。
**/
macro function containsAbstractEnumValue(typePath:Expr, value:Expr):ExprOf<Bool> {
final type = Context.getType(typePath.toString());
switch (type.follow()) {
case TAbstract(_.get() => ab, _) if (ab.meta.has(":enum")):
final cases:Array<Case> = [];
for (field in ab.impl.get().statics.get()) {
if (field.meta.has(":enum") && field.meta.has(":impl")) {
final fieldName = field.name;
cases.push({ values: [macro $typePath.$fieldName], expr: macro true });
}
}
return {
pos: Context.currentPos(),
expr: ESwitch(value, cases, macro false)
};
default:
throw new Error(type.toString() + " should be enum abstract", typePath.pos);
}
}
使用側
final result = containsAbstractEnumValue(CryptoAlgorithm, "sha1");
trace(result); //true
マクロとしては、abstract enumの型定義からtrueを返すswitch式を作ってるだけ。
try haxeで動作確認したので、こちらも貼っておきます。
Discussion