module universal.extras.enums;

import std.typetuple;
import std.traits;
import universal.core.product;
import universal.core.coproduct;

/*
	for working with enums
*/

/*
	turn an enum instance into a union, whose field names follow the enum identifiers.
*/
template enumUnion(N) if(is(N == enum))
{
	alias Ns = EnumMembers!N; 
	alias U = Union!(enumDecls!N);

	U enumUnion(N a) 
	{
		foreach(i, b; Ns)
			if(a == b)
				return U().inject!i(a);

		assert(0);
	}
}

/*
	interleaves the names of enums with the type of the enum, repeated
*/
template enumDecls(N)
{
  import std.range: iota;
  import std.meta: aliasSeqOf;

  alias enumDecls = staticMap!(enumDecl, aliasSeqOf!(Ns.length.iota));

  alias Ns = EnumMembers!N; 
  alias enumDecl(uint i) = TypeTuple!(__traits(identifier, Ns[i]), N);
}