module websocketd.checkpoint; struct Checkpoint { string name; string condition; string code; string toDCode(string datasource, string source, string valuename) { import std.format : format; return format(` case "%s": if (%s) { %s __prevState = "__prev_%s"; goto case; } else { __dataBySource[%s] = %s; __frames[%s] = %s; break; } case "__prev_%s": `, name, condition, code, name, source, datasource, source, valuename, name); } } string CheckpointSetup(T)(string datasource, string valuename, string source, Checkpoint[] checkpoints...) { import std.array : join; import std.algorithm : map; import std.format : format; string f = format(` static string __prevState = "start"; static ubyte[][string] __dataBySource; static %s[string] __frames; if (%s !in __frames) __frames[%s] = %s.init; %s %s = __frames[%s]; if (%s !in __dataBySource) __dataBySource[%s] = []; string changeState(string state) { return "{ __prevState = \"" ~ state ~ "\"; goto case \"" ~ state ~ "\"; }"; } %s = __dataBySource[%s] ~ %s; switch (__prevState) { case "__prev_start": case "start": %s default: __prevState = "start"; __dataBySource[%s] = %s; } `, T.stringof, source, source, T.stringof, T.stringof, valuename, source, source, source, datasource, source, datasource, checkpoints.map!(c => c.toDCode(datasource, source, valuename)).join, source, datasource); return f; }