1 /**
2  * Associative Array utility functions
3  *
4  * License:
5  *   This Source Code Form is subject to the terms of
6  *   the Mozilla Public License, v. 2.0. If a copy of
7  *   the MPL was not distributed with this file, You
8  *   can obtain one at http://mozilla.org/MPL/2.0/.
9  *
10  * Authors:
11  *   Vladimir Panteleev <vladimir@thecybershadow.net>
12  */
13 
14 module ae.utils.aa;
15 
16 import std.algorithm;
17 import std.range;
18 import std.traits;
19 import std.typecons;
20 
21 // ***************************************************************************
22 
23 /// Polyfill for object.require
24 static if (!__traits(hasMember, object, "require"))
25 ref V require(K, V)(ref V[K] aa, K key, lazy V value = V.init)
26 {
27 	auto p = key in aa;
28 	if (p)
29 		return *p;
30 	return aa[key] = value;
31 }
32 
33 unittest
34 {
35 	int[int] aa;
36 	aa.require(1, 2);
37 	assert(aa[1] == 2);
38 	aa.require(2, 3) = 4;
39 	assert(aa[2] == 4);
40 	aa.require(1, 5);
41 	assert(aa[1] == 2);
42 	aa.require(1, 6) = 7;
43 	assert(aa[1] == 7);
44 }
45 
46 static if (!__traits(hasMember, object, "update"))
47 {
48 	/// Polyfill for object.update
49 	void updatePolyfill(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
50 	if (is(typeof(create()) : V) && is(typeof(update(aa[K.init])) : V))
51 	{
52 		auto p = key in aa;
53 		if (p)
54 			*p = update(*p);
55 		else
56 			aa[key] = create();
57 	}
58 
59 	/// Work around https://issues.dlang.org/show_bug.cgi?id=15795
60 	alias update = updatePolyfill;
61 }
62 
63 // https://github.com/dlang/druntime/pull/3012
64 private enum haveObjectUpdateWithVoidUpdate = is(typeof({
65 	int[int] aa;
66 	.object.update(aa, 0, { return 0; }, (ref int v) { });
67 }));
68 
69 static if (!haveObjectUpdateWithVoidUpdate)
70 {
71 	/// Polyfill for object.update with void update function
72 	void updateVoid(K, V, C, U)(ref V[K] aa, K key, scope C create, scope U update)
73 	if (is(typeof(create()) : V) && is(typeof(update(aa[K.init])) == void))
74 	{
75 		// We can polyfill this in two ways.
76 		// What's more expensive, copying the value, or a second key lookup?
77 		enum haveObjectUpdate = __traits(hasMember, object, "update");
78 		enum valueIsExpensiveToCopy = V.sizeof > string.sizeof
79 			|| hasElaborateCopyConstructor!V
80 			|| hasElaborateDestructor!V;
81 		static if (haveObjectUpdate && !valueIsExpensiveToCopy)
82 		{
83 			.object.update(aa, key, create,
84 				(ref V v) { update(v); return v; });
85 		}
86 		else
87 		{
88 			auto p = key in aa;
89 			if (p)
90 				update(*p);
91 			else
92 				aa[key] = create();
93 		}
94 	}
95 
96 	/// Work around https://issues.dlang.org/show_bug.cgi?id=15795
97 	alias update = updateVoid;
98 }
99 else
100 	alias updateVoid = object.update;
101 
102 // Inject overload
103 static if (__traits(hasMember, object, "update"))
104 	private alias update = object.update;
105 
106 // ***************************************************************************
107 
108 /// Get a value from an AA, and throw an exception (not an error) if not found
109 ref auto aaGet(AA, K)(auto ref AA aa, auto ref K key)
110 	if (is(typeof(key in aa)))
111 {
112 	import std.conv;
113 
114 	auto p = key in aa;
115 	if (p)
116 		return *p;
117 	else
118 		static if (is(typeof(text(key))))
119 			throw new Exception("Absent value: " ~ text(key));
120 		else
121 			throw new Exception("Absent value");
122 }
123 
124 /// If key is not in aa, add it with defaultValue.
125 /// Returns a reference to the value corresponding to key.
126 ref V getOrAdd(K, V)(ref V[K] aa, auto ref K key, auto ref V defaultValue)
127 {
128 	return aa.require(key, defaultValue);
129 }
130 
131 /// ditto
132 ref V getOrAdd(K, V)(ref V[K] aa, auto ref K key)
133 {
134 	return getOrAdd(aa, key, V.init);
135 }
136 
137 unittest
138 {
139 	int[int] aa;
140 	aa.getOrAdd(1, 2) = 3;
141 	assert(aa[1] == 3);
142 	assert(aa.getOrAdd(1, 4) == 3);
143 }
144 
145 /// If key is not in aa, add it with the given value, and return true.
146 /// Otherwise, return false.
147 bool addNew(K, V)(ref V[K] aa, auto ref K key, auto ref V value)
148 {
149 	bool added = void;
150 	updateVoid(aa, key,
151 		delegate V   (       ) { added = true ; return value; },
152 		delegate void(ref V v) { added = false;               },
153 	);
154 	return added;
155 }
156 
157 unittest
158 {
159 	int[int] aa;
160 	assert( aa.addNew(1, 2));
161 	assert(!aa.addNew(1, 3));
162 	assert(aa[1] == 2);
163 }
164 
165 // ***************************************************************************
166 
167 struct KeyValuePair(K, V) { K key; V value; }
168 
169 /// Get key/value pairs from AA
170 deprecated KeyValuePair!(K, V)[] pairs(K, V)(V[K] aa)
171 {
172 	KeyValuePair!(K, V)[] result;
173 	foreach (key, value; aa)
174 		result ~= KeyValuePair!(K, V)(key, value);
175 	return result;
176 }
177 
178 /// Get key/value pairs from AA, sorted by keys
179 KeyValuePair!(K, V)[] sortedPairs(K, V)(V[K] aa)
180 {
181 	KeyValuePair!(K, V)[] result;
182 	foreach (key; aa.keys.sort)
183 		result ~= KeyValuePair!(K, V)(key, aa[key]);
184 	return result;
185 }
186 
187 /// Get values from AA, sorted by keys
188 V[] sortedValues(K, V)(in V[K] aa)
189 {
190 	V[] result;
191 	foreach (key; aa.keys.sort())
192 		result ~= aa[key];
193 	return result;
194 }
195 
196 /// Merge source into target. Return target.
197 V[K] merge(K, V)(auto ref V[K] target, in V[K] source)
198 {
199 	foreach (k, v; source)
200 		target[k] = v;
201 	return target;
202 }
203 
204 unittest
205 {
206 	int[int] target;
207 	int[int] source = [2:4];
208 	merge(target, source);
209 	assert(source == target);
210 
211 	target = [1:1, 2:2, 3:3];
212 	merge(target, source);
213 	assert(target == [1:1, 2:4, 3:3]);
214 
215 	assert(merge([1:1], [2:2]) == [1:1, 2:2]);
216 }
217 
218 /// Slurp a range of two elements (or two-element struct/class) into an AA.
219 auto toAA(R)(R r)
220 	if (is(typeof(r.front[1])))
221 {
222 	alias K = typeof(r.front[0]);
223 	alias V = typeof(r.front[1]);
224 	V[K] result;
225 	foreach (pair; r)
226 	{
227 		assert(pair.length == 2);
228 		result[pair[0]] = pair[1];
229 	}
230 	return result;
231 }
232 
233 /// ditto
234 auto toAA(R)(R r)
235 	if (is(typeof(r.front.tupleof)) && r.front.tupleof.length == 2 && !is(typeof(r.front[1])))
236 {
237 	return r.map!(el => tuple(el.tupleof)).toAA();
238 }
239 
240 deprecated unittest
241 {
242 	assert([[2, 4]].toAA() == [2:4]);
243 	assert([2:4].pairs.toAA() == [2:4]);
244 }
245 
246 /// Ensure that arr is non-null if empty.
247 V[K] nonNull(K, V)(V[K] aa)
248 {
249 	if (aa !is null)
250 		return aa;
251 	aa[K.init] = V.init;
252 	aa.remove(K.init);
253 	assert(aa !is null);
254 	return aa;
255 }
256 
257 unittest
258 {
259 	int[int] aa;
260 	assert(aa is null);
261 	aa = aa.nonNull;
262 	assert(aa !is null);
263 	assert(aa.length == 0);
264 }
265 
266 // ***************************************************************************
267 
268 // Helpers for HashCollection
269 private
270 {
271 	alias Void = void[0]; // Zero-sized type
272 	static assert(Void.sizeof == 0);
273 
274 	// Abstraction layer for single/multi-value type holding one or many T.
275 	// Optimizer representation for Void.
276 	struct SingleOrMultiValue(bool multi, T)
277 	{
278 		alias ValueType = Select!(multi,
279 			// multi==true
280 			Select!(is(T == Void),
281 				size_t, // "store" the items by keeping track of their count only.
282 				T[],
283 			),
284 
285 			// multi==false
286 			Select!(is(T == Void),
287 				Void,
288 				T[1],
289 			),
290 		);
291 
292 		// Using free functions instead of struct methods,
293 		// as structs always have non-zero size.
294 	static:
295 
296 		size_t length(ref const ValueType v) nothrow
297 		{
298 			static if (is(T == Void))
299 				static if (multi)
300 					return v; // count
301 				else
302 					return 1;
303 			else
304 				return v.length; // static or dynamic array
305 		}
306 	}
307 }
308 
309 /// Base type for ordered/unordered single-value/multi-value map/set
310 /*private*/ struct HashCollection(K, V, bool ordered, bool multi)
311 {
312 private:
313 	enum bool haveValues = !is(V == void); // Not a set
314 
315 	// The type for values used when a value variable is needed
316 	alias ValueVarType = Select!(haveValues, V, Void);
317 
318 	// The type of a single element of the values of `this.lookup`.
319 	// When ordered==true, we use size_t (index into `this.items`).
320 	alias LookupItem = Select!(ordered, size_t, ValueVarType);
321 
322 	// The type of the values of `this.lookup`.
323 	alias SM = SingleOrMultiValue!(multi, LookupItem);
324 	alias LookupValue = SM.ValueType;
325 
326 	static if (haveValues)
327 	{
328 		alias ReturnType(Fallback) = V;
329 		alias SingleIterationType = V;
330 		alias OpIndexKeyType = K;
331 		alias OpIndexValueType = V;
332 	}
333 	else
334 	{
335 		alias SingleIterationType = const(K);
336 		static if (ordered)
337 		{
338 			alias OpIndexKeyType = size_t;
339 			alias OpIndexValueType = K;
340 			alias ReturnType(Fallback) = K;
341 		}
342 		else
343 		{
344 			alias OpIndexKeyType = void;
345 			alias OpIndexValueType = void;
346 			alias ReturnType(Fallback) = Fallback;
347 		}
348 	}
349 	enum haveReturnType = !is(ReturnType!void == void);
350 	enum haveIndexing = haveValues || ordered;
351 
352 	alias IK = OpIndexKeyType;
353 	alias IV = OpIndexValueType;
354 
355 	// The contract we try to follow is that adding/removing items in
356 	// one copy of the object will not affect other copies.
357 	// Therefore, when we have array fields, make sure they are dup'd
358 	// on copy, so that we don't trample older copies' data.
359 	enum bool needDupOnCopy = ordered;
360 
361 	static if (haveReturnType)
362 	{
363 		static if (ordered)
364 			/*  */ ref inout(ReturnType!void) lookupToReturnValue(in        LookupItem  lookupItem) inout { return items[lookupItem].returnValue; }
365 		else
366 			static ref inout(ReturnType!void) lookupToReturnValue(ref inout(LookupItem) lookupItem)       { return       lookupItem             ; }
367 	}
368 
369 	// *** Data ***
370 
371 	// This is used for all key hash lookups.
372 	LookupValue[K] lookup;
373 
374 	static if (ordered)
375 	{
376 		struct Item
377 		{
378 			K key;
379 			ValueVarType value;
380 
381 			static if (haveValues)
382 				private alias returnValue = value;
383 			else
384 				private alias returnValue = key;
385 		}
386 		Item[] items;
387 
388 		enum bool canDup = is(typeof(lookup.dup)) && is(typeof(items.dup));
389 	}
390 	else
391 	{
392 		enum bool canDup = is(typeof(lookup.dup));
393 	}
394 
395 public:
396 
397 	// *** Lifetime ***
398 
399 	/// Postblit
400 	static if (needDupOnCopy)
401 	{
402 		static if (canDup)
403 			this(this)
404 			{
405 				lookup = lookup.dup;
406 				items = items.dup;
407 			}
408 		else
409 			@disable this(this);
410 	}
411 
412 	/// Create shallow copy
413 	static if (canDup)
414 	typeof(this) dup()
415 	{
416 		static if (needDupOnCopy)
417 			return this;
418 		else
419 		{
420 			typeof(this) copy;
421 			copy.lookup = lookup.dup;
422 			static if (ordered)
423 				copy.items = items.dup;
424 			return copy;
425 		}
426 	}
427 	
428 	// *** Conversions (from) ***
429 
430 	/// Construct from something else
431 	this(Input)(Input input)
432 	if (is(typeof(opAssign(input))))
433 	{
434 		opAssign(input);
435 	}
436 
437 	/// Null assignment
438 	ref typeof(this) opAssign(typeof(null) _)
439 	{
440 		clear();
441 		return this;
442 	}
443 
444 	/// Convert from an associative type
445 	ref typeof(this) opAssign(AA)(AA aa)
446 	if (haveValues
447 		&& !is(AA : typeof(this))
448 		&& is(typeof({ foreach (ref k, ref v; aa) add(k, v); })))
449 	{
450 		clear();
451 		foreach (ref k, ref v; aa)
452 			add(k, v);
453 		return this;
454 	}
455 
456 	/// Convert from an associative type of multiple items
457 	ref typeof(this) opAssign(AA)(AA aa)
458 	if (haveValues
459 		&& multi
460 		&& !is(AA : typeof(this))
461 		&& is(typeof({ foreach (ref k, ref vs; aa) foreach (ref v; vs) add(k, v); })))
462 	{
463 		clear();
464 		foreach (ref k, ref vs; aa)
465 			foreach (ref v; vs)
466 				add(k, v);
467 		return this;
468 	}
469 
470 	/// Convert from a range of tuples
471 	ref typeof(this) opAssign(R)(R input)
472 	if (haveValues
473 		&& is(typeof({ foreach (ref pair; input) add(pair[0], pair[1]); }))
474 		&& !is(typeof({ foreach (ref k, ref v; input) add(k, v); }))
475 		&& is(typeof(input.front.length))
476 		&& input.front.length == 2)
477 	{
478 		clear();
479 		foreach (ref pair; input)
480 			add(pair[0], pair[1]);
481 		return this;
482 	}
483 
484 	/// Convert from a range of key/value pairs
485 	ref typeof(this) opAssign(R)(R input)
486 	if (haveValues
487 		&& is(typeof({ foreach (ref pair; input) add(pair.key, pair.value); }))
488 		&& !is(typeof({ foreach (ref k, ref v; input) add(k, v); })))
489 	{
490 		clear();
491 		foreach (ref pair; input)
492 			add(pair.key, pair.value);
493 		return this;
494 	}
495 
496 	/// Convert from a range of values
497 	ref typeof(this) opAssign(R)(R input)
498 	if (!haveValues
499 		&& !is(R : typeof(this))
500 		&& is(typeof({ foreach (ref v; input) add(v); })))
501 	{
502 		clear();
503 		foreach (ref v; input)
504 			add(v);
505 		return this;
506 	}
507 
508 	// *** Conversions (to) ***
509 
510 	/// Convert to bool (true if non-null)
511 	bool opCast(T)() const
512 	if (is(T == bool))
513 	{
514 		return lookup !is null;
515 	}
516 
517 	/// Convert to D associative array
518 	static if (!ordered)
519 	{
520 		const(LookupValue[K]) toAA() const
521 		{
522 			return lookup;
523 		}
524 
525 		LookupValue[K] toAA()
526 		{
527 			return lookup.dup;
528 		}
529 
530 		deprecated alias items = toAA;
531 	}
532 
533 	// *** Query (basic) ***
534 
535 	/// True when there are no items.
536 	bool empty() pure const nothrow @nogc @trusted
537 	{
538 		static if (ordered)
539 			return items.length == 0; // optimization
540 		else
541 			return lookup.byKey.empty; // generic version
542 	}
543 
544 	/// Total number of items, including with duplicate keys.
545 	size_t length() pure const nothrow @nogc @trusted
546 	{
547 		static if (ordered)
548 			return items.length; // optimization
549 		else
550 		static if (!multi)
551 			return lookup.length; // optimization
552 		else // generic version
553 		{
554 			size_t result;
555 			foreach (ref v; lookup.byValue)
556 				result += SM.length(v);
557 			return result;
558 		}
559 	}
560 
561 	// *** Query (by key) ***
562 
563 	/// Check if item with this key has been added.
564 	/// When applicable, return a pointer to the last value added with this key.
565 	Select!(haveReturnType, inout(ReturnType!void)*, bool) opBinaryRight(string op : "in", _K)(auto ref _K key) inout
566 	if (is(typeof(key in lookup)))
567 	{
568 		enum missValue = select!haveReturnType(null, false);
569 
570 		auto p = key in lookup;
571 		if (!p)
572 			return missValue;
573 
574 		static if (haveReturnType)
575 			return &lookupToReturnValue((*p)[$-1]);
576 		else
577 			return true;
578 	}
579 
580 	/// Index operator.
581 	/// The key must exist. Indexing with a key which does not exist
582 	/// is an error.
583 	static if (haveIndexing)
584 	ref inout(IV) opIndex()(auto ref IK k) inout
585 	{
586 		static if (haveValues)
587 			return lookupToReturnValue(lookup[k][$-1]);
588 		else
589 			return items[k].returnValue;
590 	}
591 
592 	/// Retrieve last value associated with key, or `defaultValue` if none.
593 	static if (haveIndexing)
594 	auto ref inout(IV) get()(auto ref IK k, auto ref inout(IV) defaultValue) inout
595 	{
596 		static if (haveValues)
597 		{
598 			auto p = k in lookup;
599 			return p ? lookupToReturnValue((*p)[$-1]) : defaultValue;
600 		}
601 		else
602 			return k < items.length ? items[k].returnValue : defaultValue;
603 	}
604 
605 	// *** Query (ranges) ***
606 
607 	/// Return a range which iterates over key/value pairs.
608 	static if (haveValues)
609 	auto byKeyValue(this This)()
610 	{
611 		static if (ordered)
612 			return items;
613 		else
614 		{
615 			return lookup
616 				.byKeyValue
617 				.map!(pair =>
618 					pair
619 					.value
620 					.map!(value => KeyValuePair!(K, V)(pair.key, value))
621 				)
622 				.joiner;
623 		}
624 	}
625 
626 	/// ditto
627 	static if (haveValues)
628 	auto byPair(this This)()
629 	{
630 		return byKeyValue
631 			.map!(pair => tuple!("key", "value")(pair.key, pair.value));
632 	}
633 
634 	/// Return a range which iterates over all keys.
635 	/// Duplicate keys will occur several times in the range.
636 	auto byKey(this This)()
637 	{
638 		static if (ordered)
639 		{
640 			static ref getKey(MItem)(ref MItem item) { return item.key; }
641 			return items.map!getKey;
642 		}
643 		else
644 		{
645 			return lookup
646 				.byKeyValue
647 				.map!(pair =>
648 					pair.key.repeat(SM.length(pair.value))
649 				)
650 				.joiner;
651 		}
652 	}
653 
654 	/// Return a range which iterates over all values.
655 	static if (haveValues)
656 	auto byValue(this This)()
657 	{
658 		static if (ordered)
659 		{
660 			static ref getValue(MItem)(ref MItem item) { return item.value; }
661 			return items.map!getValue;
662 		}
663 		else
664 		{
665 			return lookup
666 				.byKeyValue
667 				.map!(pair =>
668 					pair
669 					.value
670 				)
671 				.joiner;
672 		}
673 	}
674 
675 	@property auto keys(this This)() { return byKey.array; }
676 	@property auto values(this This)() { return byValue.array; }
677 
678 	// *** Query (search by key) ***
679 
680 	static if (ordered)
681 	{
682 		size_t indexOf()(auto ref const K k)
683 		{
684 			auto p = k in lookup;
685 			return p ? (*p)[0] : -1;
686 		}
687 
688 		size_t[] indicesOf()(auto ref const K k)
689 		{
690 			auto p = k in lookup;
691 			return p ? (*p)[] : null;
692 		}
693 	}
694 
695 	/// Return the number of items with the given key.
696 	/// When multi==false, always returns 0 or 1.
697 	size_t count()(auto ref K k)
698 	{
699 		static if (ordered)
700 			return indicesOf(k).length;
701 		else
702 		{
703 			auto p = k in lookup;
704 			return p ? SM.length(*p) : 0;
705 		}
706 	}
707 
708 	/// Return a range with all values with the given key.
709 	/// If the key is not present, returns an empty range.
710 	static if (haveValues)
711 	auto byValueOf(this This)(auto ref K k)
712 	{
713 		static if (ordered)
714 			return indicesOf(k).map!(index => items[index].value);
715 		else
716 			return valuesOf(k);
717 	}
718 
719 	/// Return an array with all values with the given key.
720 	/// If the key is not present, returns an empty array.
721 	static if (haveValues)
722 	V[] valuesOf()(auto ref K k)
723 	{
724 		static if (ordered)
725 			return byValueOf(k).array;
726 		else
727 		{
728 			static if (multi)
729 				return lookup.get(k, null);
730 			else
731 			{
732 				auto p = k in lookup;
733 				return p ? (*p)[] : null;
734 			}
735 		}
736 	}
737 
738 	static if (haveValues)
739 	deprecated alias getAll = valuesOf;
740 
741 	// *** Iteration ***
742 
743 	private int opApplyImpl(this This, Dg)(Dg dg)
744 	{
745 		enum single = arity!dg == 1;
746 
747 		int result = 0;
748 
749 		static if (ordered)
750 		{
751 			foreach (ref item; items)
752 			{
753 				static if (single)
754 					result = dg(item.returnValue);
755 				else
756 					result = dg(item.key, item.value);
757 				if (result)
758 					break;
759 			}
760 		}
761 		else
762 		{
763 		outer:
764 			foreach (ref key, ref values; lookup)
765 				static if (haveValues)
766 				{
767 					foreach (ref value; values)
768 					{
769 						static if (single)
770 							result = dg(value);
771 						else
772 							result = dg(key, value);
773 						if (result)
774 							break outer;
775 					}
776 				}
777 				else
778 				{
779 					foreach (iteration; 0 .. SM.length(values))
780 					{
781 						static assert(single);
782 						result = dg(key);
783 						if (result)
784 							break outer;
785 					}
786 				}
787 		}
788 		return result;
789 	}
790 
791 	/// Iterate over keys (sets) / values (maps).
792 	int opApply(int delegate(ref SingleIterationType x) dg)
793 	{
794 		return opApplyImpl(dg);
795 	}
796 
797 	/// ditto
798 	int opApply(int delegate(const ref SingleIterationType x) dg) const
799 	{
800 		return opApplyImpl(dg);
801 	}
802 
803 	static if (haveValues)
804 	{
805 		/// Iterate over keys and values.
806 		int opApply(int delegate(K k, ref V v) dg)
807 		{
808 			return opApplyImpl(dg);
809 		}
810 
811 		/// ditto
812 		int opApply(int delegate(K k, const ref V v) dg) const
813 		{
814 			return opApplyImpl(dg);
815 		}
816 	}
817 
818 	// *** Mutation (addition) ***
819 
820 	private enum AddMode
821 	{
822 		add,     /// Always add value
823 		replace, /// Replace all previous values
824 		require, /// Only add value if it did not exist before
825 	}
826 
827 	private ref ReturnType!void addImpl(AddMode mode, AK, GV)(ref AK key, scope GV getValue)
828 	if (is(AK : K))
829 	{
830 		static if (ordered)
831 		{
832 			size_t addedIndex;
833 
834 			static if (multi && mode == AddMode.add)
835 			{
836 				addedIndex = items.length;
837 				lookup[key] ~= addedIndex;
838 				items ~= Item(key, getValue());
839 			}
840 			else
841 			{
842 				lookup.updateVoid(key,
843 					delegate LookupValue()
844 					{
845 						addedIndex = items.length;
846 						items ~= Item(key, getValue());
847 						return [addedIndex];
848 					},
849 					delegate void(ref LookupValue existingIndex)
850 					{
851 						addedIndex = existingIndex[0];
852 						static if (mode != AddMode.require)
853 						{
854 							static if (multi)
855 							{
856 								static assert(mode == AddMode.replace);
857 								existingIndex = existingIndex[0 .. 1];
858 							}
859 							items[addedIndex].value = getValue();
860 						}
861 					});
862 			}
863 
864 			return items[addedIndex].returnValue;
865 		}
866 		else // ordered
867 		{
868 			static if (haveValues)
869 			{
870 				static if (mode == AddMode.require)
871 					return (lookup.require(key, [getValue()]))[0];
872 				else
873 				static if (multi && mode == AddMode.add)
874 					return (lookup[key] ~= getValue())[$-1];
875 				else
876 					return (lookup[key] = [getValue()])[0];
877 			}
878 			else
879 			{
880 				static if (multi)
881 				{
882 					static if (mode == AddMode.require)
883 						lookup.require(key, 1);
884 					else
885 					static if (mode == AddMode.add)
886 						lookup[key]++;
887 					else
888 						lookup[key] = 1;
889 				}
890 				else
891 					lookup[key] = LookupValue.init;
892 				// This branch returns void, as there is no reasonable
893 				// ref to an AA key that we can return here.
894 			}
895 		}
896 	}
897 
898 	/*private*/ template addSetFunc(AddMode mode)
899 	{
900 		static if (haveValues)
901 		{
902 			ref ReturnType!void addSetFunc(AK, AV)(auto ref AK key, auto ref AV value)
903 			if (is(AK : K) && is(AV : V))
904 			{
905 				return addImpl!mode(key, () => value);
906 			}
907 		}
908 		else
909 		{
910 			ref ReturnType!void addSetFunc(AK)(auto ref AK key)
911 			if (is(AK : K))
912 			{
913 				ValueVarType value; // void[0]
914 				return addImpl!mode(key, () => value);
915 			}
916 		}
917 	}
918 
919 	/// Add an item.
920 	alias add = addSetFunc!(AddMode.add);
921 
922 	/// Ensure a key exists (with the given value).
923 	/// When `multi==true`, replaces all previous entries with this key.
924 	/// Otherwise, behaves identically to `add`.
925 	alias set = addSetFunc!(AddMode.replace);
926 
927 	/// Add `value` only if `key` is not present.
928 	static if (haveValues)
929 	ref V require()(auto ref K key, lazy V value = V.init)
930 	{
931 		return addImpl!(AddMode.require)(key, () => value);
932 	}
933 
934 	deprecated alias getOrAdd = require;
935 
936 	private alias UpdateFuncRT(U) = typeof({ U u = void; V v = void; return u(v); }());
937 
938 	/// If `key` is present, call `update` for every value;
939 	/// otherwise, add new value with `create`.
940 	static if (haveValues)
941 	void update(C, U)(auto ref K key, scope C create, scope U update)
942 	if (is(typeof(create()) : V) && (is(UpdateFuncRT!U : V) || is(UpdateFuncRT!U == void)))
943 	{
944 		static if (ordered)
945 		{
946 			lookup.updateVoid(key,
947 				delegate LookupValue()
948 				{
949 					auto addedIndex = items.length;
950 					items ~= Item(key, create());
951 					return [addedIndex];
952 				},
953 				delegate void(ref LookupValue existingIndex)
954 				{
955 					foreach (i; existingIndex)
956 						static if (is(UpdateFuncRT!U == void))
957 							update(items[i].value);
958 						else
959 							items[i].value = update(items[i].value);
960 				});
961 		}
962 		else // ordered
963 		{
964 			lookup.updateVoid(key,
965 				delegate LookupValue ()
966 				{
967 					return [create()];
968 				},
969 				delegate void (ref LookupValue values)
970 				{
971 					foreach (ref value; values)
972 						static if (is(UpdateFuncRT!U == void))
973 							update(value);
974 						else
975 							value = update(value);
976 				});
977 		}
978 	}
979 
980 	// *** Mutation (editing) ***
981 
982 	static if (haveIndexing)
983 	{
984 		static if (haveValues)
985 		{
986 			/// Same as `set(k, v)`.
987 			ref IV opIndexAssign(AK, AV)(auto ref AV v, auto ref AK k)
988 			if (is(AK : K) && is(AV : V))
989 			{
990 				return set(k, v);
991 			}
992 
993 			/// Perform cumulative operation with value
994 			/// (initialized with `.init` if the key does not exist).
995 			ref IV opIndexOpAssign(string op, AK, AV)(auto ref AV v, auto ref AK k)
996 			if (is(AK : K) && is(AV : V))
997 			{
998 				auto pv = &require(k);
999 				return mixin("(*pv) " ~ op ~ "= v");
1000 			}
1001 
1002 			/// Perform unary operation with value
1003 			/// (initialized with `.init` if the key does not exist).
1004 			ref IV opIndexUnary(string op, AK)(auto ref AK k)
1005 			if (is(AK : K))
1006 			{
1007 				auto pv = &require(k);
1008 				mixin("(*pv) " ~ op ~ ";");
1009 				return *pv;
1010 			}
1011 		}
1012 		else
1013 		{
1014 			private ref K editIndex(size_t index, scope void delegate(ref K) edit)
1015 			{
1016 				auto item = &items[index];
1017 				K oldKey = item.key;
1018 				auto pOldIndices = oldKey in lookup;
1019 				assert(pOldIndices);
1020 
1021 				edit(item.key);
1022 
1023 				// Add new value
1024 
1025 				lookup.updateVoid(item.key,
1026 					delegate LookupValue()
1027 					{
1028 						// New value did not exist.
1029 						if ((*pOldIndices).length == 1)
1030 						{
1031 							// Optimization - migrate the Indexes value
1032 							assert((*pOldIndices)[0] == index);
1033 							return *pOldIndices;
1034 						}
1035 						else
1036 							return [index];
1037 					},
1038 					delegate void(ref LookupValue existingIndex)
1039 					{
1040 						// Value(s) with the new key already existed
1041 						static if (multi)
1042 							existingIndex ~= index;
1043 						else
1044 							assert(false, "Collision after in-place edit of a non-multi ordered set element");
1045 					});
1046 
1047 				// Remove old value
1048 
1049 				if ((*pOldIndices).length == 1)
1050 					lookup.remove(oldKey);
1051 				else
1052 				static if (multi)
1053 					*pOldIndices = (*pOldIndices).remove!(i => i == index);
1054 				else
1055 					assert(false); // Should be unreachable (`if` above will always be true)
1056 
1057 				return item.key;
1058 			}
1059 
1060 			/// Allows writing to ordered sets by index.
1061 			/// The total number of elements never changes as a result
1062 			/// of such an operation - a consequence of which is that
1063 			/// if multi==false, changing the value to one that's
1064 			/// already in the set is an error.
1065 			ref IV opIndexAssign()(auto ref IV v, auto ref IK k)
1066 			{
1067 				static if (haveValues)
1068 					return set(k, v);
1069 				else
1070 					return editIndex(k, (ref IV e) { e = v; });
1071 			}
1072 
1073 			/// Perform cumulative operation with value at index.
1074 			ref IV opIndexOpAssign(string op)(auto ref VV v, auto ref IK k)
1075 			{
1076 				return editIndex(k, (ref IV e) { mixin("e " ~ op ~ "= v;"); });
1077 			}
1078 
1079 			/// Perform unary operation with value at index.
1080 			ref IV opIndexUnary(string op)(auto ref IK k)
1081 			{
1082 				return editIndex(k, (ref IV e) { mixin("e " ~ op ~ ";"); });
1083 			}
1084 		}
1085 	}
1086 
1087 	// *** Mutation (removal) ***
1088 
1089 	/// Removes all elements with the given key.
1090 	bool remove(AK)(auto ref AK key)
1091 	if (is(typeof(lookup.remove(key))))
1092 	{
1093 		static if (ordered)
1094 		{
1095 			auto p = key in lookup;
1096 			if (!p)
1097 				return false;
1098 
1099 			auto targets = *p;
1100 			foreach (target; targets)
1101 			{
1102 				items = items.remove!(SwapStrategy.stable)(target);
1103 				foreach (ref k, ref vs; lookup)
1104 					foreach (ref v; vs)
1105 						if (v > target)
1106 							v--;
1107 			}
1108 			auto success = lookup.remove(key);
1109 			assert(success);
1110 			return true;
1111 		}
1112 		else
1113 			return lookup.remove(key);
1114 	}
1115 
1116 	/// Removes all elements.
1117 	void clear()
1118 	{
1119 		lookup.clear();
1120 		static if (ordered)
1121 			items.length = 0;
1122 	}
1123 }
1124 
1125 /// An associative array which retains the order in which elements were added.
1126 alias OrderedMap(K, V) = HashCollection!(K, V, true, false);
1127 
1128 unittest
1129 {
1130 	alias M = OrderedMap!(string, int);
1131 	M m;
1132 	m["a"] = 1;
1133 	m["b"] = 2;
1134 	m["c"] = 3;
1135 	assert(m.length == 3);
1136 	assert("a" in m);
1137 	assert("d" !in m);
1138 
1139 	{
1140 		auto r = m.byKeyValue;
1141 		assert(!r.empty);
1142 		assert(r.front.key == "a");
1143 		r.popFront();
1144 		assert(!r.empty);
1145 		assert(r.front.key == "b");
1146 		r.popFront();
1147 		assert(!r.empty);
1148 		assert(r.front.key == "c");
1149 		r.popFront();
1150 		assert(r.empty);
1151 	}
1152 
1153 	assert(m.byKey.equal(["a", "b", "c"]));
1154 	assert(m.byValue.equal([1, 2, 3]));
1155 	assert(m.byKeyValue.map!(p => p.key).equal(m.byKey));
1156 	assert(m.byKeyValue.map!(p => p.value).equal(m.byValue));
1157 	assert(m.keys == ["a", "b", "c"]);
1158 	assert(m.values == [1, 2, 3]);
1159 
1160 	{
1161 		const(M)* c = &m;
1162 		assert(c.byKey.equal(["a", "b", "c"]));
1163 		assert(c.byValue.equal([1, 2, 3]));
1164 		assert(c.keys == ["a", "b", "c"]);
1165 		assert(c.values == [1, 2, 3]);
1166 	}
1167 
1168 	m.byValue.front = 5;
1169 	assert(m.byValue.equal([5, 2, 3]));
1170 
1171 	m.remove("a");
1172 	assert(m.length == 2);
1173 	m["x"] -= 1;
1174 	assert(m["x"] == -1);
1175 	++m["y"];
1176 	assert(m["y"] == 1);
1177 	auto cm = cast(const)m.dup;
1178 	foreach (k, v; cm)
1179 		if (k == "x")
1180 			assert(v == -1);
1181 }
1182 
1183 unittest
1184 {
1185 	OrderedMap!(string, int) m;
1186 	m["a"] = 1;
1187 	m["b"] = 2;
1188 	m.remove("a");
1189 	assert(m["b"] == 2);
1190 }
1191 
1192 unittest
1193 {
1194 	OrderedMap!(string, int) m;
1195 	m["a"] = 1;
1196 	auto m2 = m;
1197 	m2.remove("a");
1198 	m2["b"] = 2;
1199 	assert(m["a"] == 1);
1200 }
1201 
1202 unittest
1203 {
1204 	OrderedMap!(string, int) m;
1205 	m["a"] = 1;
1206 	m["b"] = 2;
1207 	auto m2 = m;
1208 	m.remove("a");
1209 	assert(m2["a"] == 1);
1210 }
1211 
1212 unittest
1213 {
1214 	class C {}
1215 	const OrderedMap!(string, C) m;
1216 	cast(void)m.byKeyValue;
1217 }
1218 
1219 unittest
1220 {
1221 	OrderedMap!(int, int) m;
1222 	m.update(10,
1223 		{ return 20; },
1224 		(ref int k) { k++; return 30; },
1225 	);
1226 	assert(m.length == 1 && m[10] == 20);
1227 	m.update(10,
1228 		{ return 40; },
1229 		(ref int k) { k++; return 50; },
1230 	);
1231 	assert(m.length == 1 && m[10] == 50);
1232 }
1233 
1234 // https://issues.dlang.org/show_bug.cgi?id=18606
1235 unittest
1236 {
1237 	struct S
1238 	{
1239 		struct T
1240 		{
1241 			int foo;
1242 			int[] bar;
1243 		}
1244 
1245 		OrderedMap!(int, T) m;
1246 	}
1247 }
1248 
1249 unittest
1250 {
1251 	OrderedMap!(string, int) m;
1252 	static assert(is(typeof(m.keys)));
1253 	static assert(is(typeof(m.values)));
1254 }
1255 
1256 unittest
1257 {
1258 	OrderedMap!(string, int) m;
1259 	foreach (k, v; m)
1260 		k = k ~ k;
1261 }
1262 
1263 /// Like assocArray
1264 auto orderedMap(R)(R input)
1265 if (is(typeof(input.front.length) : size_t) && input.front.length == 2)
1266 {
1267 	alias K = typeof(input.front[0]);
1268 	alias V = typeof(input.front[1]);
1269 	return OrderedMap!(K, V)(input);
1270 }
1271 
1272 auto orderedMap(R)(R input) /// ditto
1273 if (is(typeof(input.front.key)) && is(typeof(input.front.value)) && !is(typeof(input.front.length)))
1274 {
1275 	alias K = typeof(input.front.key);
1276 	alias V = typeof(input.front.value);
1277 	return OrderedMap!(K, V)(input);
1278 }
1279 
1280 unittest
1281 {
1282 	auto map = 3.iota.map!(n => tuple(n, n + 1)).orderedMap;
1283 	assert(map.length == 3 && map[1] == 2);
1284 }
1285 
1286 unittest
1287 {
1288 	OrderedMap!(string, int) m;
1289 	m = m.byKeyValue.orderedMap;
1290 	m = m.byPair.orderedMap;
1291 }
1292 
1293 // ***************************************************************************
1294 
1295 /// Helper/wrapper for void[0][T]
1296 alias HashSet(T) = HashCollection!(T, void, false, false);
1297 
1298 unittest
1299 {
1300 	HashSet!int s;
1301 	assert(!s);
1302 	assert(s.length == 0);
1303 	assert(!(1 in s));
1304 	assert(1 !in s);
1305 	s.add(1);
1306 	assert(1 in s);
1307 	assert(s.length == 1);
1308 	foreach (k; s)
1309 		assert(k == 1);
1310 	s.remove(1);
1311 	assert(s.length == 0);
1312 
1313 	s.add(1);
1314 	auto t = s.dup;
1315 	s.add(2);
1316 	assert(t.length==1);
1317 	t.remove(1);
1318 	assert(t.length==0);
1319 }
1320 
1321 unittest
1322 {
1323 	struct S { int[int] aa; }
1324 	HashSet!S set;
1325 	S s;
1326 	set.add(s);
1327 	assert(s in set);
1328 }
1329 
1330 auto toSet(R)(R r)
1331 {
1332 	alias E = ElementType!R;
1333 	return HashSet!E(r);
1334 }
1335 
1336 unittest
1337 {
1338 	auto set = [1, 2, 3].toSet();
1339 	assert(2 in set);
1340 	assert(4 !in set);
1341 }
1342 
1343 unittest
1344 {
1345 	HashSet!int m;
1346 	const int i;
1347 	m.remove(i);
1348 }
1349 
1350 unittest
1351 {
1352 	HashSet!Object m;
1353 	Object o;
1354 	m.remove(o);
1355 }
1356 
1357 // ***************************************************************************
1358 
1359 alias OrderedSet(T) = HashCollection!(T, void, true, false);
1360 
1361 unittest
1362 {
1363 	OrderedSet!int set;
1364 
1365 	assert(1 !in set);
1366 	set.add(1);
1367 	assert(1 in set);
1368 	set.remove(1);
1369 	assert(1 !in set);
1370 
1371 	set.add(1);
1372 	set.clear();
1373 	assert(1 !in set);
1374 
1375 	set = set.init;
1376 	assert(!set);
1377 	set.add(1);
1378 	assert(!!set);
1379 
1380 	assert(set[0] == 1);
1381 	set[0] = 2;
1382 	assert(set[0] == 2);
1383 	assert(1 !in set);
1384 	assert(2 in set);
1385 
1386 	assert(set.length == 1);
1387 	set.remove(2);
1388 	assert(set.length == 0);
1389 
1390 	set.add(1);
1391 	auto set2 = set;
1392 	set.remove(1);
1393 	set.add(2);
1394 	assert(1 !in set && 2 in set);
1395 	assert(1 in set2 && 2 !in set2);
1396 
1397 	foreach (v; set)
1398 		assert(v == 2);
1399 }
1400 
1401 auto orderedSet(R)(R r)
1402 {
1403 	alias E = ElementType!R;
1404 	return OrderedSet!E(r);
1405 }
1406 
1407 // ***************************************************************************
1408 
1409 /// An object which acts mostly as an associative array,
1410 /// with the added property of being able to hold keys with
1411 /// multiple values. These are only exposed explicitly and
1412 /// through iteration
1413 alias MultiAA(K, V) = HashCollection!(K, V, false, true);
1414 
1415 unittest
1416 {
1417 	alias MASS = MultiAA!(string, int);
1418 	MASS aa;
1419 	aa.add("foo", 42);
1420 	assert(aa["foo"] == 42);
1421 	assert(aa.valuesOf("foo") == [42]);
1422 	assert(aa.byPair.front.key == "foo");
1423 
1424 	auto aa2 = MASS([tuple("foo", 42)]);
1425 	aa2 = ["a":1,"b":2];
1426 
1427 	const int i;
1428 	aa["a"] = i;
1429 }
1430 
1431 unittest
1432 {
1433 	MultiAA!(int, int) m;
1434 	int[][int] a;
1435 	m = a;
1436 }