1 module mutils.container.ct_map;
2 
3 import std.meta;
4 import std.traits;
5 
6 import mutils.meta;
7 
8 struct CTMap(ElementsPar...) {
9 	static assert(ElementsPar.length % 2 == 0);
10 	alias Elements = ElementsPar;
11 
12 	struct KeyValue(alias KeyPar, alias ValPar) {
13 		alias key = KeyPar;
14 		alias value = ValPar;
15 	}
16 
17 	struct KeyValue(alias KeyPar, ValPar) {
18 		alias key = KeyPar;
19 		alias value = ValPar;
20 	}
21 
22 	struct KeyValue(KeyPar, alias ValPar) {
23 		alias key = KeyPar;
24 		alias value = ValPar;
25 	}
26 
27 	template getValues() {
28 		alias getValues = removeEven!Elements;
29 	}
30 
31 	template getKeys() {
32 		alias getKeys = removeOdd!Elements;
33 	}
34 
35 	template getValueType() {
36 		static assert(valuesHaveSameType);
37 		alias getValueType = typeof(Elements[1]);
38 	}
39 
40 	template getKeyType() {
41 		static assert(keysHaveSameType);
42 		alias getKeyType = typeof(Elements[0]);
43 	}
44 
45 	static bool valuesAreValueType() {
46 		return allSatisfy!(isExpressions, getValues!());
47 	}
48 
49 	static bool keysAreValueType() {
50 		return allSatisfy!(isExpressions, getKeys!());
51 	}
52 
53 	static bool valuesHaveSameType() {
54 		static if (keysAreValueType) {
55 			alias Types = staticMap!(getType, getValues!());
56 			return NoDuplicates!(Types).length == 1;
57 		} else {
58 			return false;
59 		}
60 	}
61 
62 	static bool keysHaveSameType() {
63 		static if (keysAreValueType) {
64 			alias Types = staticMap!(getType, getKeys!());
65 			return NoDuplicates!(Types).length == 1;
66 		} else {
67 			return false;
68 		}
69 	}
70 
71 	template getImpl() {
72 		auto getImpl() {
73 			foreach (i, Key; Elements) {
74 				static if (i % 2 == 0 && ((__traits(compiles, T == Key)
75 						&& T == Key) || (__traits(compiles, is(T == Key)) && is(T == Key)))) { //even elements are keys
76 					struct Returner {
77 						static if (isExpressions!(Elements[i + 1])) {
78 							enum value = Elements[i + 1];
79 						} else {
80 							alias value = Elements[i + 1];
81 						}
82 					}
83 
84 					Returner ret;
85 					return ret;
86 				}
87 
88 			}
89 		}
90 
91 	}
92 
93 	static auto get(T)() {
94 		mixin getImpl;
95 		return getImpl();
96 	}
97 
98 	static auto get(alias T)() {
99 		mixin getImpl;
100 		return getImpl();
101 	}
102 
103 	//static if(valuesHaveSameType && keysHaveSameType){
104 	alias byKeyValue = toKeyValue!(Elements);
105 	//}
106 
107 	private template toKeyValue(Arr...) {
108 		static if (Arr.length > 2) {
109 			alias toKeyValue = AliasSeq!(KeyValue!(Arr[0], Arr[1]), toKeyValue!(Arr[2 .. $]));
110 		} else static if (Arr.length == 2) {
111 			alias toKeyValue = AliasSeq!(KeyValue!(Arr[0], Arr[1]));
112 		} else {
113 			alias toKeyValue = AliasSeq!();
114 		}
115 	}
116 
117 }
118 
119 unittest {
120 	alias myMap = CTMap!(6, int, long, 12, 18, 23);
121 
122 	static assert(is(myMap.get!(6).value == int));
123 	static assert(myMap.get!(long).value == 12);
124 	static assert(myMap.get!(18).value == 23);
125 	static assert(!myMap.keysAreValueType);
126 	static assert(!myMap.valuesAreValueType);
127 }
128 
129 unittest {
130 	alias myMap = CTMap!("str1", 8, "str2", 12, "str3", 23);
131 
132 	static assert(myMap.keysAreValueType);
133 	static assert(myMap.valuesAreValueType);
134 	static assert(myMap.keysHaveSameType);
135 	static assert(myMap.valuesHaveSameType);
136 	static assert(is(myMap.getValueType!() == int));
137 	static assert(is(myMap.getKeyType!() == string));
138 
139 }
140 
141 unittest {
142 	alias myMap = CTMap!("str1", 8, "str2", 12, "str3", 23);
143 
144 	int runtimeLookUp(string var) {
145 		switch (var) {
146 			foreach (keyValue; myMap.byKeyValue) {
147 		case keyValue.key:
148 				return keyValue.value;
149 			}
150 		default:
151 			return 0;
152 		}
153 	}
154 
155 	assert(runtimeLookUp("str0") == 0);
156 	assert(runtimeLookUp("str1") == 8);
157 	assert(runtimeLookUp("str2") == 12);
158 	assert(runtimeLookUp("str3") == 23);
159 	assert(runtimeLookUp("str4") == 0);
160 }