1 module dud.pkgdescription.duplicate;
2 
3 import std.array : empty;
4 import std.algorithm.iteration : each;
5 import std.traits : FieldNameTuple;
6 import std.typecons : nullable;
7 import std.format : format;
8 
9 import dud.semver.semver;
10 import dud.semver.versionrange;
11 import dud.pkgdescription;
12 
13 @safe pure:
14 
15 PackageDescription dup(const ref PackageDescription pkg) {
16 	PackageDescription ret;
17 
18 	static foreach(mem; FieldNameTuple!(PackageDescription)) {{
19 		alias MemType = typeof(__traits(getMember, PackageDescription, mem));
20 		static if(is(MemType == string)
21 				|| is(MemType == SemVer)
22 				|| is(MemType == Path)
23 				|| is(MemType == UnprocessedPath)
24 				|| is(MemType == Paths)
25 				|| is(MemType == BuildOptions)
26 				|| is(MemType == Dependency[])
27 				|| is(MemType == Platform[][])
28 				|| is(MemType == SubPackage[])
29 				|| is(MemType == BuildType[string])
30 				|| is(MemType == ToolchainRequirement[Toolchain])
31 				|| is(MemType == SubConfigs)
32 				|| is(MemType == BuildRequirements)
33 				|| is(MemType == PackageDescription[string])
34 				|| is(MemType == String)
35 				|| is(MemType == Strings)
36 				|| is(MemType == string[]))
37 		{
38 			__traits(getMember, ret, mem) = __traits(getMember, pkg, mem).dup();
39 		} else static if(is(MemType == TargetType)
40 				|| is(MemType == string)
41 				)
42 		{
43 			__traits(getMember, ret, mem) = __traits(getMember, pkg, mem);
44 		} else {
45 			static assert(false, format(
46 				"Type '%s' of member '%s' is not handled in dup",
47 				MemType.stringof, mem));
48 		}
49 	}}
50 
51 	return ret;
52 }
53 
54 VersionRange dup(const ref VersionRange old) {
55 	return old.dup();
56 }
57 
58 unittest {
59 	import dud.pkgdescription.compare;
60 	import dud.semver.versionrange;
61 	auto old = parseVersionRange(">=1.15.0");
62 	assert(!old.isNull());
63 
64 	VersionRange d = dup(old.get());
65 	assert(areEqual(old.get(), d));
66 }
67 
68 //
69 // ToolchainRequirement
70 //
71 
72 ToolchainRequirement dup(const ref ToolchainRequirement old) pure {
73 	ToolchainRequirement ret;
74 	ret.no = old.no;
75 	ret.version_ = old.version_.dup();
76 	return ret;
77 }
78 
79 ToolchainRequirement[Toolchain] dup(
80 		ref const(ToolchainRequirement[Toolchain]) old)
81 {
82 	ToolchainRequirement[Toolchain] ret;
83 	old.byKeyValue().each!(it => ret[it.key] = it.value.dup());
84 	return ret;
85 }
86 
87 //
88 // TargetType
89 //
90 
91 TargetType dup(const(TargetType) old) {
92 	TargetType ret = old;
93 	return ret;
94 }
95 
96 //
97 // SemVer
98 //
99 
100 SemVer dup(ref const(SemVer) old) {
101 	return old.dup();
102 }
103 
104 SemVer[] dup(const(SemVer[]) old) {
105 	SemVer[] ret;
106 	old.each!(it => ret ~= it.dup());
107 	return ret;
108 }
109 
110 //
111 // BuildOption
112 //
113 
114 BuildOption[] dup(const(BuildOption[]) old) {
115 	BuildOption[] ret;
116 	old.each!(it => ret ~= it);
117 	return ret;
118 }
119 
120 BuildOptions dup(ref const(BuildOptions) old) {
121 	BuildOptions ret;
122 	ret.unspecifiedPlatform = old.unspecifiedPlatform.dup();
123 	foreach(key, value; old.platforms) {
124 		ret.platforms[key] = value.dup();
125 	}
126 	return ret;
127 }
128 
129 //
130 // SubConfig
131 //
132 
133 SubConfigs dup(ref const(SubConfigs) old) {
134 	SubConfigs ret;
135 	old.unspecifiedPlatform
136 		.byKeyValue
137 		.each!(it => ret.unspecifiedPlatform[it.key] = it.value);
138 
139 	foreach(key, value; old.configs) {
140 		string[string] tmp;
141 		foreach(key2, value2; value) {
142 			tmp[key2] = value2;
143 		}
144 		ret.configs[key] = tmp;
145 	}
146 	return ret;
147 }
148 
149 Platform[] dup(const(Platform[]) old) {
150 	Platform[] ret;
151 	old.each!(it => ret ~= it);
152 	return ret;
153 }
154 
155 Platform[][] dup(const(Platform[][]) old) {
156 	Platform[][] ret;
157 	old.each!(it => ret ~= it.dup);
158 	return ret;
159 }
160 
161 BuildType dup(const(BuildType) old) {
162 	BuildType ret;
163 	ret.pkg = old.pkg.dup();
164 	ret.name = old.name;
165 	return ret;
166 }
167 
168 BuildType[string] dup(const(BuildType[string]) old) {
169 	BuildType[string] ret;
170 	old.byKeyValue().each!(it => ret[it.key] = it.value.dup());
171 	return ret;
172 }
173 
174 BuildRequirement[] dup(const(BuildRequirement[]) old) {
175 	BuildRequirement[] ret;
176 	old.each!(it => ret ~= it);
177 	return ret;
178 }
179 
180 BuildRequirementPlatform dup(const(BuildRequirementPlatform) old) {
181 	return BuildRequirementPlatform(
182 			old.requirements.dup(),
183 			old.platforms.dup());
184 }
185 
186 BuildRequirements dup(const(BuildRequirements) old) {
187 	BuildRequirements ret;
188 	old.platforms.each!(it => ret.platforms ~= it.dup());
189 	return ret;
190 }
191 
192 PackageDescription[string] dup(const(PackageDescription[string]) old) {
193 	PackageDescription[string] ret;
194 	old.byKeyValue().each!(it => ret[it.key] = it.value.dup());
195 	return ret;
196 }
197 
198 SubPackage dup(ref const(SubPackage) old) {
199 	SubPackage ret;
200 	ret.path = old.path.dup();
201 	if(!old.inlinePkg.isNull()) {
202 		ret.inlinePkg = nullable(old.inlinePkg.get().dup());
203 	}
204 	return ret;
205 }
206 
207 SubPackage[] dup(const(SubPackage[]) old) {
208 	SubPackage[] ret;
209 	old.each!(it => ret ~= it.dup());
210 	return ret;
211 }
212 
213 //
214 // Dependency
215 //
216 
217 Dependency dup(ref const(Dependency) old) {
218 	Dependency ret;
219 	ret.name = old.name;
220 	ret.platforms = old.platforms.dup();
221 	ret.path = old.path.dup();
222 	if(!old.default_.isNull()) {
223 		const bool o = old.default_.get();
224 		ret.default_ = o;
225 	}
226 
227 	if(!old.optional.isNull()) {
228 		const bool o = old.optional.get();
229 		ret.optional = o;
230 	}
231 
232 	if(!old.version_.isNull()) {
233 		VersionRange o = old.version_.get().dup;
234 		ret.version_ = o;
235 	}
236 	return ret;
237 }
238 
239 Dependency[] dup(const(Dependency[]) old) {
240 	Dependency[] ret;
241 	old.each!(it => ret ~= it.dup());
242 	return ret;
243 }
244 
245 //
246 // String
247 //
248 
249 StringsPlatform dup(ref const(StringsPlatform) old) {
250 	StringsPlatform ret;
251 	ret.strs = old.strs.dup();
252 	ret.platforms = old.platforms.dup();
253 	return ret;
254 }
255 
256 Strings dup(ref const(Strings) old) {
257 	Strings ret;
258 	old.platforms.each!(p => ret.platforms ~= p.dup());
259 	return ret;
260 }
261 
262 //
263 // String
264 //
265 
266 StringPlatform dup(ref const(StringPlatform) old) {
267 	StringPlatform ret;
268 	ret.str = old.str.dup();
269 	ret.platforms = old.platforms.dup();
270 	return ret;
271 }
272 
273 String dup(ref const(String) old) {
274 	String ret;
275 	old.platforms.each!(p => ret.platforms ~= p.dup());
276 	return ret;
277 }
278 
279 //
280 // Paths
281 //
282 
283 Paths dup(ref const(Paths) old) {
284 	Paths ret;
285 	old.platforms.each!(p => ret.platforms ~= p.dup());
286 	return ret;
287 }
288 
289 //
290 // Path
291 //
292 
293 PathPlatform dup(ref const(PathPlatform) old) {
294 	PathPlatform ret;
295 	ret.path = UnprocessedPath(old.path.path);
296 	ret.platforms = old.platforms.dup();
297 	return ret;
298 }
299 
300 PathPlatform[] dup(const(PathPlatform[]) old) {
301 	PathPlatform[] ret;
302 	old.each!(it => ret ~= it.dup());
303 	return ret;
304 }
305 
306 UnprocessedPath dup(ref const(UnprocessedPath) old) {
307 	return UnprocessedPath(old.path.dup());
308 }
309 
310 PathsPlatform dup(ref const(PathsPlatform) old) {
311 	PathsPlatform ret;
312 	old.paths.each!(it => ret.paths ~= it.dup());
313 	ret.platforms = old.platforms.dup();
314 	return ret;
315 }
316 
317 PathsPlatform[] dup(const(PathsPlatform[]) old) {
318 	PathsPlatform[] ret;
319 	old.each!(it => ret ~= it.dup());
320 	return ret;
321 }
322 
323 Path dup(ref const(Path) old) {
324 	Path ret;
325 	old.platforms.each!(p => ret.platforms ~= p.dup());
326 	return ret;
327 }
328 
329 //
330 // string
331 //
332 
333 string dup(const(string) old) {
334 	return old;
335 }
336 
337 string[] dup(const(string[]) old) {
338 	string[] ret;
339 	old.each!(it => ret ~= it);
340 	return ret;
341 }
342 
343 string[string] dup(const(string[string]) old) {
344 	string[string] ret;
345 	old.byKeyValue.each!(kv => ret[kv.key.dup()] = kv.value.dup());
346 	return ret;
347 }