1 /**
2 Internal module for pushing and getting _arrays.
3 All _arrays with LuaD compatible element types are supported.
4 */
5 module luad.conversions.arrays;
6 
7 import std.traits;
8 import std.range : ElementType;
9 
10 import luad.c.all;
11 import luad.stack;
12 
13 void pushArray(T)(lua_State* L, ref T arr) if (isArray!T)
14 {
15 	assert(arr.length <= int.max, "lua_createtable only supports int.max many elements");
16 	lua_createtable(L, cast(int) arr.length, 0);
17 	foreach(i, v; arr)
18 	{
19 		pushValue(L, i + 1); //Lua tables start at 1, not 0
20 		pushValue(L, v);
21 		lua_rawset(L, -3);
22 	}
23 }
24 
25 // TODO: do the immutable/const initialization *properly*
26 T getArray(T)(lua_State* L, int idx) if (isArray!T)
27 {
28 	alias ElemType = ElementType!T;
29 	auto len = lua_objlen(L, idx);
30 
31 	static if(isStaticArray!T)
32 	{
33 		if(len != T.length)
34 			luaL_error(L, "Incorrect number of array elements: %d, expected: %d", len, T.length);
35 
36 		Unqual!ElemType[T.length] arr;
37 	}
38 	else
39 		auto arr = new Unqual!ElemType[len];
40 
41 	foreach(i; 0 .. len)
42 	{
43 		lua_pushinteger(L, i + 1);
44 		lua_gettable(L, idx < 0? idx - 1 : idx);
45 		arr[i] = popValue!ElemType(L);
46 	}
47 
48 	return cast(T)arr;
49 }
50 
51 void fillStaticArray(T)(lua_State* L, ref T arr) if(isStaticArray!T)
52 {
53 	foreach(i, ref elem; arr)
54 	{
55 		elem = getValue!(typeof(elem))(L, cast(int)(-arr.length + i));
56 	}
57 }
58 
59 void pushStaticArray(T)(lua_State* L, ref T arr) if(isStaticArray!T)
60 {
61 	foreach(elem; arr)
62 		pushValue(L, elem);
63 }
64 
65 version(unittest) import luad.testing;
66 
67 unittest
68 {
69 	lua_State* L = luaL_newstate();
70 	scope(success) lua_close(L);
71 	luaL_openlibs(L);
72 
73 	{
74 		int[] arr = [1, 2, 3];
75 		pushValue(L, arr);
76 		assert(lua_istable(L, -1));
77 		lua_setglobal(L, "array");
78 
79 		unittest_lua(L, `
80 			for i, expected in pairs{1, 2, 3} do
81 				local value = array[i]
82 				assert(value == expected,
83 					("bad array index: '%s' = '%s' (expected '%s')"):format(i, value, expected)
84 				)
85 			end
86 		`);
87 	}
88 
89 	{
90 		unittest_lua(L, `array = {"hello", "from", "lua"}`);
91 
92 		lua_getglobal(L, "array");
93 		string[] arr = popValue!(string[])(L);
94 		assert(arr[0] == "hello");
95 		assert(arr[1] == "from");
96 		assert(arr[2] == "lua");
97 	}
98 }