1 module nxt.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`).
7 
8     See_Also: http://www.boost.org/doc/libs/1_65_1/libs/bimap/doc/html/boost_bimap/one_minute_tutorial.html
9  */
10 struct BiMap(X, Y,
11              alias Map = Y[X])
12 {
13 @safe pure nothrow:
14     alias LeftMap = Map!(X, Y);
15     alias RightMap = Map!(Y, X);
16 
17     /// Insert (`x`, `y`).
18     void insert(X x, Y y)
19     {
20         version(D_Coverage) {} else pragma(inline, true);
21         _left[x] = y;
22         _right[y] = x;
23     }
24 
25     /// Check if (`x`, `y`) is stored.
26     bool contains(scope const X x,
27                   scope const Y y) const
28     {
29         version(LDC) pragma(inline, true);
30         // TODO do this symmetric?
31         if (const hitPtr = x in _left)
32         {
33             return *hitPtr == y;
34         }
35         return false;
36     }
37 
38     /// Clear contents.
39     void clear() @trusted       // TODO ok for this to be `@trusted`?
40     {
41         version(D_Coverage) {} else pragma(inline, true);
42         _left.clear();
43         _right.clear();
44     }
45 
46 @nogc:
47 
48     /// Check if empty.
49     bool empty() const
50     {
51         version(D_Coverage) {} else pragma(inline, true);
52         return length == 0;
53     }
54 
55     /// Get length.
56     size_t length() const
57     {
58         version(D_Coverage) {} else pragma(inline, true);
59         return _left.length;
60     }
61 
62     /// Access to left map must be non-mutating.
63     ref const(LeftMap) left() const
64     {
65         version(D_Coverage) {} else pragma(inline, true);
66         return _left;
67     }
68 
69     /// Access to right map must be non-mutating.
70     ref const(RightMap) right() const
71     {
72         version(D_Coverage) {} else pragma(inline, true);
73         return _right;
74     }
75 
76 private:
77     LeftMap _left;              ///< Left map.
78     RightMap _right;            ///< Right map.
79 }
80 
81 @safe pure nothrow:
82 
83 /// test with builtin associative arrays
84 unittest
85 {
86     alias HashMap(Key, Value) = Value[Key];
87     BiMap!(size_t, string, HashMap) bm;
88 
89     bm.insert(42, "42");
90 
91     assert(bm.left.length == 1);
92     assert(bm.right.length == 1);
93 
94     assert(bm.contains(42, "42"));
95 
96     bm.clear();
97     assert(bm.empty);
98 }