module pind.samples.ja.uda.uda_3; import std.stdio; import std.string; import std.algorithm; import std.conv; import std.traits; /* 割り当てられたシンボルを暗号化することを指定する。 * */ struct Encrypted { } enum Color { black, blue, red } /* 割り当てられたシンボルの色を指定する。 * デフォルトの色はColor.blackだ。 */ struct Colored { Color color; } struct Person { /* このメンバーは、暗号化されて青色で表示されるように指定されている。 * */ @Encrypted @Colored(Color.blue) string name; /* このメンバーには、ユーザー定義の属性はない。 * */ string lastName; /* このメンバーは、赤色で表示されるように指定されている。 */ @Colored(Color.red) string address; } /* 指定したメンバーにColored属性がある場合はその値を返し、 * ない場合はColor.blackを返す。 */ Color colorAttributeOf(T, string memberName)() { auto result = Color.black; foreach (attr; __traits(getAttributes, __traits(getMember, T, memberName))) { static if (is (typeof(attr) == Colored)) { result = attr.color; } } return result; } /* 指定された文字列のシーザー暗号化されたバージョンを返す。 * (注意: シーザー暗号は、非常に弱い暗号化方法だ。) * */ auto encrypted(string value) { return value.map!(a => dchar(a + 1)); } unittest { assert("abcdefghij".encrypted.equal("bcdefghijk")); } /* 指定されたオブジェクトを、そのメンバーの属性に従って * XML形式で表示する。 */ void printAsXML(T)(T object) { writefln("<%s>", T.stringof); scope(exit) writefln("", T.stringof); foreach (member; __traits(allMembers, T)) { string value = __traits(getMember, object, member).to!string; static if (hasUDA!(__traits(getMember, T, member), Encrypted)) { value = value.encrypted.to!string; } writefln(` <%1$s color="%2$s">%3$s`, member, colorAttributeOf!(T, member), value); } } void main() { auto people = [ Person("Alice", "Davignon", "Avignon"), Person("Ben", "de Bordeaux", "Bordeaux") ]; foreach (person; people) { printAsXML(person); } }