1 /**
2 Internal module for pushing and getting associative arrays.
3 All associative arrays with LuaD compatible key and value types are supported.
4 For tables with heterogeneous key or value types, use $(D Algebraic) (see $(DPMODULE2 conversions,variant)) keys/values or $(DPREF table,LuaTable).
5 For string keys and heterogeneous value types, consider using a $(D struct) (see $(DPMODULE2 conversions,structs)).
6 */
7 module luad.conversions.assocarrays;
8 
9 import luad.c.all;
10 import std.traits;
11 import luad.stack;
12 
13 void pushAssocArray(T, U)(lua_State* L, T[U] aa)
14 {
15 	assert(aa.length <= int.max, "lua_createtable only supports int.max many elements");
16 	lua_createtable(L, 0, cast(int) aa.length);
17 	foreach(key, value; aa)
18 	{
19 		pushValue(L, key);
20 		pushValue(L, value);
21 		lua_rawset(L, -3);
22 	}
23 }
24 
25 T getAssocArray(T)(lua_State* L, int idx) if (isAssociativeArray!T)
26 {
27 	T aa;
28 	alias typeof(aa.values[0]) ElemType;
29 	alias typeof(aa.keys[0]) KeyType;
30 
31 	lua_pushnil(L);
32 	while(lua_next(L, idx < 0? idx - 1 : idx) != 0)
33 	{
34 		aa[getValue!KeyType(L, -2)] = getValue!ElemType(L, -1);
35 		lua_pop(L, 1);
36 	}
37 
38 	return aa;
39 }
40 
41 version(unittest) import luad.testing;
42 
43 unittest
44 {
45 	lua_State* L = luaL_newstate();
46 	scope(success) lua_close(L);
47 	luaL_openlibs(L);
48 
49 	pushValue(L, ["foo": "bar", "hello": "world"]);
50 	lua_setglobal(L, "aa");
51 
52 	unittest_lua(L, `
53 		assert(aa.foo == "bar")
54 		assert(aa.hello == "world")
55 
56 		aa = {one = 1, two = 2}
57 	`);
58 
59 	lua_getglobal(L, "aa");
60 	auto aa = popValue!(uint[string])(L);
61 	assert(aa["one"] == 1);
62 	assert(aa["two"] == 2);
63 }