1 module nxt.container.bimap;
2 
3 @safe pure:
4 
5 /** Bidirectional map between key-and-values of type `X` and `Y` inspired by C++
6 	Boost Bimap (`boost::bimap`). Map-type defaults to a builtin associative
7 	array (AA).
8 
9 	See_Also: http://www.boost.org/doc/libs/1_65_1/libs/bimap/doc/html/boost_bimap/one_minute_tutorial.html
10  */
11 struct BiMap(X, Y, alias Map = Y[X]) {
12 @safe pure nothrow:
13 	alias LeftMap = Map!(X, Y);
14 	alias RightMap = Map!(Y, X);
15 
16 	/// Insert (`x`, `y`).
17 	void insert(X x, Y y) {
18 		pragma(inline, true);
19 		_left[x] = y;
20 		_right[y] = x;
21 	}
22 
23 	/// Check if (`x`, `y`) is stored.
24 	bool contains(scope const X x,
25 				  scope const Y y) const
26 	{
27 		version (LDC) pragma(inline, true);
28 		/+ TODO: do this symmetric? +/
29 		if (const hitPtr = x in _left)
30 			return *hitPtr == y;
31 		return false;
32 	}
33 
34 	/// Clear contents.
35 	void clear() @trusted	   /+ TODO: ok for this to be `@trusted`? +/
36 	{
37 		version (D_Coverage) {} else pragma(inline, true);
38 		_left.clear();
39 		_right.clear();
40 	}
41 
42 	/// Check if empty.
43 	bool empty() const @property @nogc => length == 0;
44 	/// Get length.
45 	size_t length() const @nogc => _left.length;
46 	/// Access to left map must be non-mutating.
47 	ref const(LeftMap) left() const @nogc => _left;
48 	/// Access to right map must be non-mutating.
49 	ref const(RightMap) right() const @nogc => _right;
50 private:
51 	LeftMap _left;			  ///< Left map.
52 	RightMap _right;			///< Right map.
53 }
54 
55 /// test with builtin associative arrays
56 pure nothrow @safe unittest {
57 	alias HashMap(Key, Value) = Value[Key];
58 	BiMap!(size_t, string, HashMap) bm;
59 
60 	bm.insert(42, "42");
61 
62 	assert(bm.left.length == 1);
63 	assert(bm.right.length == 1);
64 
65 	assert(bm.contains(42, "42"));
66 
67 	bm.clear();
68 	assert(bm.empty);
69 }