// Written by Christopher E. Miller // Placed into public domain. /// Mixin for boolean bit flags. /// Params: /// IntType = the type of the bits. /// bits = the variable of the _bits. /// BIT_FLAG = which _bits to use in bits. template BitFlag(IntType, alias bits, ulong BIT_FLAG) // IntType BIT_FLAG { bool flag() { return (bits & cast(IntType)BIT_FLAG) == cast(IntType)BIT_FLAG; } void flag(bool opt) { bits = opt ? (bits | cast(IntType)BIT_FLAG) : (bits & ~cast(IntType)BIT_FLAG); } } /// Mixin for masking bits. /// Params: /// IntType = the type of the bits. /// bits = the variable of the _bits. /// BIT_MASK = which _bits to use in bits, subject to shifting by SHIFT_BY. /// SHIFT_BY = number of bits to shift the mask value. template BitMask(IntType, alias bits, ulong BIT_MASK, ulong SHIFT_BY = 0) // IntType BIT_MASK, IntType SHIFT_BY = 0 { IntType mask() { return (bits >> cast(IntType)SHIFT_BY) & cast(IntType)BIT_MASK; } void mask(IntType opt) { bits |= (opt & cast(IntType)BIT_MASK) << cast(IntType)SHIFT_BY; } } unittest { struct FlagTest { uint bits; mixin .BitFlag!(uint, bits, 0x1) foo; mixin .BitFlag!(uint, bits, 0x2) bar; mixin .BitFlag!(uint, bits, 0x4) baz; } FlagTest ftest; ftest.foo.flag = true; ftest.bar.flag = false; ftest.baz.flag = true; assert(ftest.bits == 0b101); assert(ftest.foo.flag == true); assert(ftest.bar.flag == false); assert(ftest.baz.flag == true); struct MaskTest { uint bits; mixin .BitMask!(uint, bits, 0b11, 0) foo; mixin .BitMask!(uint, bits, 0b1, 2) bar; mixin .BitMask!(uint, bits, 0b11, 3) baz; } MaskTest mtest; mtest.foo.mask = 0b101; // Becomes 0b01 in mtest.bits mtest.bar.mask = 0b1; // Becomes 0b100 in mtest.bits mtest.baz.mask = 0b1110; // Becomes 0b10000 in mtest.bits assert(mtest.bits == 0b10101); assert(mtest.foo.mask == 0b01); assert(mtest.bar.mask == 0b1); assert(mtest.baz.mask == 0b10); }