Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import std.stdio : writeln;
- public enum Optional;
- public enum Ignore;
- public enum Producing;
- public final class SafeBuilder(UnsafeBuilder, string[] MethodsToCall, string BuildingFinalizationFunctionName)
- {
- private UnsafeBuilder builder;
- this()
- {
- builder = new UnsafeBuilder;
- }
- this(UnsafeBuilder builder)
- {
- this.builder = builder;
- }
- private static auto findBuildFinalizationFunction(BuilderType)() pure nothrow
- {
- import std.traits;
- import std.meta;
- string[] buildChainFinalizationCandidates = [];
- foreach(member; __traits(allMembers, BuilderType))
- {
- alias is_method = AliasSeq!(MemberFunctionsTuple!(BuilderType, member));
- alias is_system = AliasSeq!(MemberFunctionsTuple!(Object, member));
- static if (0 < is_method.length && 0 == is_system.length)
- {
- bool take = false;
- alias attributes =
- AliasSeq!(__traits(getAttributes, mixin(BuilderType.stringof ~ "." ~ member)));
- foreach(attribute; attributes)
- {
- static if (__traits(isSame, attribute, Producing))
- {
- take = true;
- }
- }
- if (take)
- {
- buildChainFinalizationCandidates ~= member;
- }
- }
- }
- return buildChainFinalizationCandidates;
- }
- private static auto listRequiredToCallFunctions(BuilderType, string BuildingFinalizationFunctionName)() pure nothrow
- {
- import std.traits;
- import std.meta;
- string[] requiredToCallFunctions = [];
- foreach(member; __traits(allMembers, BuilderType))
- {
- alias is_method = AliasSeq!(MemberFunctionsTuple!(BuilderType, member));
- alias is_system = AliasSeq!(MemberFunctionsTuple!(Object, member));
- static if (BuildingFinalizationFunctionName != member && 0 < is_method.length && 0 == is_system.length)
- {
- alias attributes =
- AliasSeq!(__traits(getAttributes, mixin(BuilderType.stringof ~ "." ~ member)));
- bool take = true;
- foreach(attribute; attributes)
- {
- static if (__traits(isSame, attribute, Optional) || __traits(isSame, attribute, Ignore))
- {
- take = false;
- }
- }
- if (take)
- {
- requiredToCallFunctions ~= member;
- }
- }
- }
- return requiredToCallFunctions;
- }
- static if (0 < MethodsToCall.length)
- {
- auto opDispatch(string methodName, Arguments...)(Arguments arguments)
- {
- static if (methodName == BuildingFinalizationFunctionName)
- {
- pragma(msg, "error: can't call build while this methods are not called: ", MethodsToCall);
- static assert (0);
- }
- mixin(builder.stringof ~ "." ~ methodName)(arguments);
- import std.algorithm : remove;
- return new SafeBuilder!(UnsafeBuilder,
- remove!(m => m == methodName)(MethodsToCall), BuildingFinalizationFunctionName)(builder);
- }
- }
- else
- {
- alias builder this;
- }
- }
- public static auto prepare(UnsafeBuilder)(UnsafeBuilder builder)
- {
- alias EmptyBuilder = SafeBuilder!(UnsafeBuilder, [], null);
- static if (0 == EmptyBuilder.findBuildFinalizationFunction!(UnsafeBuilder)().length)
- {
- pragma(msg, "error: no functions marked as " ~ Producing.stringof);
- static assert(0);
- }
- static if (1 < EmptyBuilder.findBuildFinalizationFunction!(UnsafeBuilder)().length)
- {
- pragma(msg, "error: more than one function marked as " ~ Producing.stringof);
- static assert(0);
- }
- const auto buildFinalizer = EmptyBuilder.findBuildFinalizationFunction!(UnsafeBuilder)()[0];
- const auto functionsToCall = EmptyBuilder.listRequiredToCallFunctions!(UnsafeBuilder, buildFinalizer)();
- alias Wrapper = SafeBuilder!(UnsafeBuilder, functionsToCall, buildFinalizer);
- return builder is null ? new Wrapper() : new Wrapper(builder);
- }
- public static auto prepare(UnsafeBuilder)()
- {
- return prepare!(UnsafeBuilder)(null);
- }
- class Ware
- {
- void say()
- {
- writeln("hello!");
- }
- }
- class WareBuilder
- {
- public auto stepOne()
- {
- writeln("step 1 (required)");
- return this;
- }
- public auto stepTwo()
- {
- writeln("step 2 (required)");
- return this;
- }
- @Ignore
- public void someWiredStuff()
- {
- writeln("some function");
- }
- @Optional
- public auto stepThreeOptional()
- {
- writeln("step 3 (optional)");
- return this;
- }
- @Producing
- public Ware build()
- {
- writeln("build()");
- return new Ware();
- }
- }
- int main(string[] argv)
- {
- writeln("Hello D-World!");
- auto builder = prepare!(WareBuilder)();
- auto ware = builder
- .stepTwo()
- .stepOne()
- .build();
- ware.say();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement