Json Value with styles
1 enum Style { block, flow } 2 3 static struct SomeMetadata { 4 int a; 5 @safe pure nothrow @nogc scope 6 int opCmp(scope const SomeMetadata rhs) const { return a - rhs.a; } 7 } 8 9 static struct ParsePosition 10 { 11 string file, line, column; 12 13 void toString()(scope ref W w) scope const 14 { 15 w.put(file); 16 if (line) { 17 w.put("("); w.put(line); 18 if (column) { w.put(","); w.put(column); } 19 w.put(")"); 20 } 21 } 22 } 23 24 static union Json_ 25 { 26 typeof(null) null_; 27 bool boolean; 28 long integer; 29 double floating; 30 // Not, that `string` is't builtin type but an alias in `object.d` 31 // So we can use `string` as a name of the string field 32 immutable(char)[] string; 33 This[] array; 34 // commented out to test `opCmp` primitive 35 // This[immutable(char)[]] object; 36 37 @algMeta: 38 bool active; 39 SomeMetadata metadata; 40 @algTransp: 41 Style style; 42 @algVerbose ParsePosition position; 43 } 44 45 alias JsonAlgebraic = Algebraic!Json_; 46 47 // typeof(null) has priority 48 static assert(JsonAlgebraic.Kind.init == JsonAlgebraic.Kind.null_); 49 static assert(JsonAlgebraic.Kind.null_ == 0); 50 51 // Kind and AllowedTypes has the same order 52 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.array] == JsonAlgebraic[])); 53 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.boolean] == bool)); 54 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.floating] == double)); 55 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.integer] == long)); 56 static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.null_] == typeof(null))); 57 // static assert (is(JsonAlgebraic.AllowedTypes[JsonAlgebraic.Kind.object] == JsonAlgebraic[string])); 58 59 JsonAlgebraic v; 60 assert(v.kind == JsonAlgebraic.Kind.null_); 61 62 v = 1; 63 assert(v.kind == JsonAlgebraic.Kind.integer); 64 assert(v == 1); 65 v = JsonAlgebraic(1); 66 assert(v == 1); 67 v = v.get!(long, double); 68 69 v = "Tagged!"; 70 // member-based access. Simple! 71 assert(v.string == "Tagged!"); 72 // type-based access 73 assert(v.get!string == "Tagged!"); 74 assert(v.trustedGet!string == "Tagged!"); 75 76 assert(v.kind == JsonAlgebraic.Kind.string); 77 78 assert(v.get!"string" == "Tagged!"); // string-based get 79 assert(v.trustedGet!"string" == "Tagged!"); // string-based trustedGet 80 81 assert(v.get!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based get 82 assert(v.trustedGet!(JsonAlgebraic.Kind.string) == "Tagged!"); // Kind-based trustedGet 83 84 // checks 85 assert(v._is!string); // type based 86 assert(v._is!"string"); // string based 87 assert(v._is!(JsonAlgebraic.Kind.string)); // 88 89 v = null; 90 assert(v.kind == JsonAlgebraic.Kind.null_); 91 92 v = [JsonAlgebraic("str"), JsonAlgebraic(4.3)]; 93 94 assert(v.kind == JsonAlgebraic.Kind.array); 95 assert(v.trustedGet!(JsonAlgebraic[])[1].kind == JsonAlgebraic.Kind.floating); 96 97 JsonAlgebraic w = v; 98 w.style = Style.flow; 99 assert(v.style != w.style); 100 assert(v == w); 101 assert(v <= w); 102 assert(v >= w); 103 assert(v.toHash == w.toHash); 104 w.active = true; 105 assert(v != w); 106 assert(v.toHash != w.toHash); 107 assert(v.get!"array" == w.get!"array"); 108 assert(v < w); 109 110 // test equality with self-referencing allowed type 111 auto arr = [JsonAlgebraic("str"), JsonAlgebraic(120)]; 112 v = arr; 113 assert(v == arr); 114 assert(v == [JsonAlgebraic("str"), JsonAlgebraic(120)]);
Wrapped algebraic with propogated primitives
static struct Response { private union Response_ { double float_; immutable(char)[] string; Response[] array; Response[immutable(char)[]] table; } alias ResponseAlgebraic = Algebraic!Response_; ResponseAlgebraic data; alias Tag = ResponseAlgebraic.Kind; // propogates opEquals, opAssign, and other primitives alias data this; static foreach (T; ResponseAlgebraic.AllowedTypes) this(T v) @safe pure nothrow @nogc { data = v; } } Response v = 3.0; assert(v.kind == Response.Tag.float_); v = "str"; assert(v == "str");
Tagged Variant Type (aka Tagged Algebraic Type).
Compatible with BetterC mode.
Template has two declarations: