Whether or not to build assert statements or assignment statements.
Output buffer to write to.
Original struct object.
Changed struct object.
The number of tabs to indent the lines with.
The string name of a recursing symbol, if applicable.
struct Foo { string s; int i; bool b; } Foo altered; altered.s = "some string"; altered.i = 42; altered.b = true; Appender!(char[]) sink; sink.formatDeltaInto!(No.asserts)(Foo.init, altered);
1 import lu.uda : Hidden; 2 import std.array : Appender; 3 4 Appender!(char[]) sink; 5 sink.reserve(1024); 6 7 struct Server 8 { 9 string address; 10 ushort port; 11 bool connected; 12 } 13 14 struct Connection 15 { 16 enum State 17 { 18 unset, 19 disconnected, 20 connected, 21 } 22 23 State state; 24 string nickname; 25 @Hidden string user; 26 @Hidden string password; 27 Server server; 28 } 29 30 Connection conn; 31 32 with (conn) 33 { 34 state = Connection.State.connected; 35 nickname = "NICKNAME"; 36 user = "USER"; 37 password = "hunter2"; 38 server.address = "address.tld"; 39 server.port = 1337; 40 } 41 42 sink.formatDeltaInto!(No.asserts)(Connection.init, conn, 0, "conn"); 43 44 assert(sink.data == 45 `conn.state = Connection.State.connected; 46 conn.nickname = "NICKNAME"; 47 conn.server.address = "address.tld"; 48 conn.server.port = 1337; 49 `, '\n' ~ sink.data); 50 51 sink = typeof(sink).init; 52 53 sink.formatDeltaInto!(Yes.asserts)(Connection.init, conn, 0, "conn"); 54 55 assert(sink.data == 56 `assert((conn.state == Connection.State.connected), Enum!(Connection.State).toString(conn.state)); 57 assert((conn.nickname == "NICKNAME"), conn.nickname); 58 assert((conn.server.address == "address.tld"), conn.server.address); 59 assert((conn.server.port == 1337), conn.server.port.to!string); 60 `, '\n' ~ sink.data); 61 62 struct Foo 63 { 64 string s; 65 int i; 66 bool b; 67 char c; 68 } 69 70 Foo f1; 71 f1.s = "string"; 72 f1.i = 42; 73 f1.b = true; 74 f1.c = '$'; 75 76 Foo f2 = f1; 77 f2.s = "yarn"; 78 f2.b = false; 79 f2.c = '#'; 80 81 sink = typeof(sink).init; 82 83 sink.formatDeltaInto!(No.asserts)(f1, f2); 84 assert(sink.data == 85 `s = "yarn"; 86 b = false; 87 c = '#'; 88 `, '\n' ~ sink.data); 89 90 sink = typeof(sink).init; 91 92 sink.formatDeltaInto!(Yes.asserts)(f1, f2); 93 assert(sink.data == 94 `assert((s == "yarn"), s); 95 assert(!b); 96 assert((c == '#'), c.to!string); 97 `, '\n' ~ sink.data); 98 99 sink = typeof(sink).init; 100 101 { 102 struct S 103 { 104 int i; 105 } 106 107 class C 108 { 109 string s; 110 bool b; 111 S child; 112 } 113 114 C c1 = new C; 115 C c2 = new C; 116 117 c2.s = "harbl"; 118 c2.b = true; 119 c2.child.i = 42; 120 121 sink.formatDeltaInto!(No.asserts)(c1, c2); 122 assert(sink.data == 123 `s = "harbl"; 124 b = true; 125 child.i = 42; 126 `, '\n' ~ sink.data); 127 128 sink = typeof(sink).init; 129 130 sink.formatDeltaInto!(Yes.asserts)(c1, c2); 131 assert(sink.data == 132 `assert((s == "harbl"), s); 133 assert(b); 134 assert((child.i == 42), child.i.to!string); 135 `, '\n' ~ sink.data); 136 } 137 { 138 struct Blah 139 { 140 int[5] arr; 141 string[3] sarr; 142 char[2] carr; 143 } 144 145 Blah b1; 146 Blah b2; 147 b2.arr = [ 1, 0, 3, 0, 5 ]; 148 b2.sarr = [ "hello", string.init, "world" ]; 149 b2.carr = [ 'a', char.init ]; 150 151 sink = typeof(sink).init; 152 153 sink.formatDeltaInto(b1, b2); 154 assert(sink.data == 155 `arr[0] = 1; 156 arr[2] = 3; 157 arr[4] = 5; 158 sarr[0] = "hello"; 159 sarr[2] = "world"; 160 carr[0] = 'a'; 161 `); 162 163 sink = typeof(sink).init; 164 165 sink.formatDeltaInto!(Yes.asserts)(b1, b2); 166 assert(sink.data == 167 `assert((arr[0] == 1), arr[0].to!string); 168 assert((arr[2] == 3), arr[2].to!string); 169 assert((arr[4] == 5), arr[4].to!string); 170 assert((sarr[0] == "hello"), sarr[0]); 171 assert((sarr[2] == "world"), sarr[2]); 172 assert((carr[0] == 'a'), carr[0].to!string); 173 `); 174 }
Constructs statement lines for each changed field (or the delta) between two instances of a struct and stores them into a passed output sink.