luaext/types/
table.rs

1use lua::{Index, ToLua, FromLua, State, Type};
2use types::{LuaStackable, LuaGeneric};
3use context::Context;
4
5/// Represents a Lua table on the Lua stack.
6pub struct LuaTable {
7    index: Index
8}
9
10impl LuaTable {
11    /// Create a new LuaTable at the given index.
12    pub fn new(i: Index) -> LuaTable {
13        LuaTable {
14            index: i
15        }
16    }
17
18    /// Set this table's metatable.
19    ///
20    /// Equivalent to the Lua `setmetatable` function
21    pub fn set_metatable(&self, context: &mut Context, meta: &LuaTable) {
22        context.get_state().push_value(meta.get_pos());
23        context.get_state().set_metatable(self.get_pos());
24    }
25
26    /// Set a value in this table
27    /// May call the __newindex metamethod
28    ///
29    /// Equivalent to `table[key] = value` in Lua
30    pub fn set(&self, context: &mut Context, key: &ToLua, value: &ToLua) {
31        key.to_lua(context.get_state());
32        value.to_lua(context.get_state());
33        context.get_state().set_table(self.get_pos());
34    }
35
36    /// Set a value in this table without invoking metamethods
37    ///
38    /// Equivalent to the Lua `rawset` function
39    pub fn set_raw(&self, context: &mut Context, key: &ToLua, value: &ToLua) {
40        key.to_lua(context.get_state());
41        value.to_lua(context.get_state());
42        context.get_state().raw_set(self.get_pos());
43    }
44
45    /// Get a value from this table
46    /// May call the __index metamethod
47    ///
48    /// Equivalent to `table[key]` in Lua
49    pub fn get(&self, context: &mut Context, key: &ToLua) -> LuaGeneric {
50        key.to_lua(context.get_state());
51        context.get_state().get_table(self.get_pos());
52        LuaGeneric::new(context.get_state().get_top())
53    }
54
55    /// Get a value from this table without invoking metamethods
56    ///
57    /// Equivalent to the Lua `rawget` function
58    pub fn get_raw(&self, context: &mut Context, key: &ToLua) -> LuaGeneric {
59        key.to_lua(context.get_state());
60        context.get_state().raw_get(self.get_pos());
61        LuaGeneric::new(context.get_state().get_top())
62    }
63
64    /// Get a value from this table as type T
65    pub fn get_typed<T: FromLua>(&self, context: &mut Context, key: &ToLua) -> Option<T> {
66        key.to_lua(context.get_state());
67        context.get_state().get_table(self.get_pos());
68        let top = context.get_state().get_top();
69        let ret = context.get_state().to_type(top);
70        ret
71    }
72
73    /// Count the number of elements in this table as an array
74    /// May call the `__len` metamethod
75    ///
76    /// Equivalent to the Lua `#` operator
77    ///
78    /// # Panics
79    ///
80    /// This method will panic if this table has a `__len`
81    /// metamethod that does not return an integer
82    pub fn len(&self, context: &mut Context) -> i64 {
83        context.get_state().len_direct(self.get_pos())
84    }
85
86    /// Count the number of elements in this table as an array without calling the `__len` metamethod
87    ///
88    /// Equivalent to the Lua `rawlen` function
89    pub fn len_raw(&self, context: &mut Context) -> usize {
90        context.get_state().raw_len(self.get_pos())
91    }
92
93    /// Iterate through every (i, value) pair where i is an integer and is continuous from 1 to
94    /// this table's length.
95    ///
96    /// Similar to the Lua `ipairs` function
97    pub fn iter_array<F>(&self, context: &mut Context, mut func: F)
98            where F: FnMut(Context, i64, LuaGeneric) {
99        for key in 1.. {
100            let mut new_context = context.push_context();
101            let value = self.get(&mut new_context, &key);
102            let t = value.type_of(&mut new_context);
103            match t {
104                Type::Nil => break,
105                _ => func(new_context, key, value)
106            };
107        }
108    }
109
110    /// Add an element to the end of the table
111    ///
112    /// Equivalent to the Lua `table.insert` function
113    pub fn append(&self, context: &mut Context, value: &ToLua) {
114        let length = self.len_raw(context);
115        self.set(context, &(length as i64+1), value);
116    }
117}
118
119impl LuaStackable for LuaTable {
120    fn get_pos(&self) -> Index {
121        self.index
122    }
123}
124
125impl ToLua for LuaTable {
126    fn to_lua(&self, state: &mut State) {
127        state.push_value(self.get_pos());
128    }
129}
130
131impl FromLua for LuaTable {
132    fn from_lua(state: &mut State, index: Index) -> Option<LuaTable> {
133        if state.is_table(index) {
134            Some(LuaTable::new(index))
135        } else {
136            None
137        }
138    }
139}