1 /++ Construction of types.
2 
3 	Typically used for functional construction of containers.
4 
5 	These generic factory functions prevents the need for defining separate
6 	member factory functions for each container/collection class opposite to
7 	what Rust's std.collection types define as `withLength`, `withCapacity`,
8 	etc. This adhere's to the dry-principle.
9 
10 	See: nxt.container and std.container.
11  +/
12 module nxt.construction;
13 
14 import std.range.primitives : isInputRange, ElementType;
15 
16 /++ Construct an instance of `T` with capacity `capacity`.
17  +/
18 T makeOfCapacity(T, Capacity)(Capacity capacity)
19 if (/+is(typeof(T.init.reserve(0))) && +/is(Capacity : size_t)) {
20 	T t;
21 	t.reserve(capacity); /+ TODO: Check that this allowed in template-restriction +/
22 	return t;
23 }
24 
25 ///
26 @safe pure unittest {
27 	alias A = int[];
28 	const n = 3;
29 	const a = makeOfCapacity!(A)(n);
30 	assert(a.capacity == n);
31 }
32 
33 /++ Construct an instance of `T` with length `n`.
34  +/
35 T makeOfLength(T, Length)(Length length) if (is(Length : size_t)) {
36 	T t;
37 	t.length = length; /+ TODO: Check that this allowed in template-restriction +/
38 	return t;
39 }
40 
41 ///
42 @safe pure unittest {
43 	alias A = int[];
44 	const n = 3;
45 	const a = makeOfLength!(A)(n);
46 	assert(a.length == n);
47 }
48 
49 /++ Construct an instance of `T` with `elements`.
50  +/
51 T makeWithElements(T, R)(R elements) if (isInputRange!R) {
52 	import std.range.primitives : hasLength;
53 	static if (is(typeof(T.init.reserve(0))) && hasLength!R) {
54 		// pragma(msg, __FILE__, "(", __LINE__, ",1): Debug: ", T);
55 		T t = makeOfCapacity!T(elements.length);
56 	}
57 	else
58 		T t;
59 	t ~= elements; // TODO: use `.put` instead?
60 	return t;
61 }
62 
63 ///
64 @safe pure unittest {
65 	alias A = int[];
66 	const elements = [1,2,3];
67 	const a = makeWithElements!(A)(elements);
68 	assert(a.capacity == elements.length);
69 	assert(a.length == elements.length);
70 }
71 
72 /// Returns: shallow duplicate of `a`.
73 T dupShallow(T)(in T a)
74 if (is(typeof(T.init[])) && // `hasSlicing!T`
75 	!is(T == const(U)[], U) && // builtin arrays already have `.dup` property
76 	__traits(isCopyable, ElementType!T)) {
77 	/+ TODO: delay slicing of `a` when T is a static array for compile-time
78        length optimization: +/
79 	return makeWithElements!(T)(a[]);
80 }
81 alias dup = dupShallow;
82 
83 ///
84 version (none)
85 @safe pure unittest {
86 	alias A = int[];
87 	const elements = [1,2,3];
88 	const a = makeWithElements!(A)(elements);
89 	const b = a.dupShallow;
90 	assert(a == b);
91 	assert(a.ptr !is b.ptr);
92 }