1 module dud.pkgdescription.helper;
2 
3 import std.format;
4 import dud.pkgdescription : PackageDescription;
5 
6 @safe:
7 
8 template PreprocessKey(string key) {
9 	import std.algorithm.searching : endsWith;
10 	static if(key.endsWith("_")) {
11 		enum PreprocessKey = key[0 .. $ - 1];
12 	} else {
13 		enum PreprocessKey = key;
14 	}
15 }
16 
17 string pkgCompare(const PackageDescription a, const PackageDescription b)
18 		@trusted
19 {
20 	import std.typecons : Nullable;
21 	import std.array : appender;
22 	import std.traits : isArray, FieldNameTuple;
23 
24 	auto app = appender!string();
25 	formattedWrite(app, "PackageDescription difference {\n");
26 	static foreach(mem; FieldNameTuple!PackageDescription) {{
27 		auto aMem = __traits(getMember, a, mem);
28 		auto bMem = __traits(getMember, b, mem);
29 
30 		if(aMem != bMem) {
31 			static if(is(typeof(aMem) : Nullable!Args, Args...)) {
32 				if(aMem.isNull() != bMem.isNull()) {
33 					formattedWrite(app, "\ta.%1$s %s b.%1$s %s\n",
34 						mem,
35 						aMem.isNull() ? "null" : "notNull",
36 						bMem.isNull() ? "null" : "notNull"
37 					);
38 				} else {
39 					assert(false, "This can not happen");
40 				}
41 			} else static if(isArray!(typeof(aMem))) {
42 				if(aMem.length != bMem.length) {
43 					formattedWrite(app, "a.length(%s) != b.length(%s)\n",
44 						aMem.length, bMem.length);
45 				} else {
46 					formattedWrite(app, "\t%s {\n", mem);
47 					foreach(idx; 0 .. aMem.length) {
48 						if(aMem[idx] != bMem[idx]) {
49 							formattedWrite(app,
50 								"\t\ta[%s] = %s\n\t\tb[%s] = %s\n",
51 								idx, aMem[idx], idx, bMem[idx]);
52 						}
53 					}
54 					formattedWrite(app, "\t}\n");
55 				}
56 			} else {
57 				formattedWrite(app, "\ta.%s = %s\nb.%s = %s\n",
58 					mem, aMem, mem, bMem);
59 			}
60 		}
61 	}}
62 	formattedWrite(app, "}\n");
63 	return app.data;
64 }
65 
66 template isMem(string name) {
67 	static if(__traits(hasMember, PackageDescription, name)) {
68 		enum isMem = name;
69 	} else {
70 		static assert(false,
71 			format("'%s' is not a member of PackageDescription", name));
72 	}
73 }
74 
75 unittest {
76 	static assert(!__traits(compiles, isMem!"foo"));
77 	static assert( __traits(compiles, isMem!"name"));
78 }