1use ffi;
2use any::{AnyLuaValue, AnyHashableLuaValue};
3
4use Push;
5use PushGuard;
6use PushOne;
7use AsMutLua;
8use TuplePushError;
9use LuaRead;
10
11use std::collections::{BTreeMap, HashMap, HashSet};
12use std::hash::Hash;
13use std::iter;
14
15#[inline]
16fn push_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
17 where L: AsMutLua<'lua>,
18 V: for<'b> Push<&'b mut L, Err = E>,
19 I: Iterator<Item = V>
20{
21 unsafe { ffi::lua_newtable(lua.as_mut_lua().0) };
23
24 for (elem, index) in iterator.zip((1..)) {
25 let size = match elem.push_to_lua(&mut lua) {
26 Ok(pushed) => pushed.forget_internal(),
27 Err((_err, _lua)) => panic!(), };
29
30 match size {
31 0 => continue,
32 1 => {
33 let index = index as u32;
34 match index.push_to_lua(&mut lua) {
35 Ok(pushed) => pushed.forget_internal(),
36 Err(_) => unreachable!(),
37 };
38 unsafe { ffi::lua_insert(lua.as_mut_lua().0, -2) }
39 unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) }
40 }
41 2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
42 _ => unreachable!(),
43 }
44 }
45
46 let raw_lua = lua.as_lua();
47 Ok(PushGuard {
48 lua: lua,
49 size: 1,
50 raw_lua: raw_lua,
51 })
52}
53
54#[inline]
55fn push_rec_iter<'lua, L, V, I, E>(mut lua: L, iterator: I) -> Result<PushGuard<L>, (E, L)>
56 where L: AsMutLua<'lua>,
57 V: for<'a> Push<&'a mut L, Err = E>,
58 I: Iterator<Item = V>
59{
60 let (nrec, _) = iterator.size_hint();
61
62 unsafe { ffi::lua_createtable(lua.as_mut_lua().0, 0, nrec as i32) };
64
65 for elem in iterator {
66 let size = match elem.push_to_lua(&mut lua) {
67 Ok(pushed) => pushed.forget_internal(),
68 Err((_err, _lua)) => panic!(), };
70
71 match size {
72 0 => continue,
73 2 => unsafe { ffi::lua_settable(lua.as_mut_lua().0, -3) },
74 _ => unreachable!(),
75 }
76 }
77
78 let raw_lua = lua.as_lua();
79 Ok(PushGuard {
80 lua: lua,
81 size: 1,
82 raw_lua: raw_lua,
83 })
84}
85
86impl<'lua, L, T, E> Push<L> for Vec<T>
87 where L: AsMutLua<'lua>,
88 T: for<'a> Push<&'a mut L, Err = E>
89{
90 type Err = E;
91
92 #[inline]
93 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
94 push_iter(lua, self.into_iter())
95 }
96}
97
98impl<'lua, L, T, E> PushOne<L> for Vec<T>
99 where L: AsMutLua<'lua>,
100 T: for<'a> Push<&'a mut L, Err = E>
101{
102}
103
104impl<'lua, L> LuaRead<L> for Vec<AnyLuaValue>
105 where L: AsMutLua<'lua>
106{
107 fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L> {
108 let mut dict: BTreeMap<i32, AnyLuaValue> = BTreeMap::new();
112
113 let mut me = lua;
114 unsafe { ffi::lua_pushnil(me.as_mut_lua().0) };
115 let index = index - 1;
116
117 loop {
118 if unsafe { ffi::lua_next(me.as_mut_lua().0, index) } == 0 {
119 break;
120 }
121
122 let key = {
123 let maybe_key: Option<i32> =
124 LuaRead::lua_read_at_position(&mut me, -2).ok();
125 match maybe_key {
126 None => {
127 unsafe { ffi::lua_pop(me.as_mut_lua().0, 2) };
129 return Err(me)
130 }
131 Some(k) => k,
132 }
133 };
134
135 let value: AnyLuaValue =
136 LuaRead::lua_read_at_position(&mut me, -1).ok().unwrap();
137
138 unsafe { ffi::lua_pop(me.as_mut_lua().0, 1) };
139
140 dict.insert(key, value);
141 }
142
143 let (maximum_key, minimum_key) =
144 (*dict.keys().max().unwrap_or(&1), *dict.keys().min().unwrap_or(&1));
145
146 if minimum_key != 1 {
147 return Err(me);
150 }
151
152 let mut result =
153 Vec::with_capacity(maximum_key as usize);
154
155 let mut previous_key = 0;
158
159 for (k, v) in dict {
162 if previous_key + 1 != k {
163 return Err(me)
164 } else {
165 result.push(v);
168 previous_key = k;
169 }
170 }
171
172 Ok(result)
173 }
174}
175
176impl<'a, 'lua, L, T, E> Push<L> for &'a [T]
177 where L: AsMutLua<'lua>,
178 T: Clone + for<'b> Push<&'b mut L, Err = E>
179{
180 type Err = E;
181
182 #[inline]
183 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
184 push_iter(lua, self.iter().map(|e| e.clone()))
185 }
186}
187
188impl<'a, 'lua, L, T, E> PushOne<L> for &'a [T]
189 where L: AsMutLua<'lua>,
190 T: Clone + for<'b> Push<&'b mut L, Err = E>
191{
192}
193
194impl<'lua, L> LuaRead<L> for HashMap<AnyHashableLuaValue, AnyLuaValue>
195 where L: AsMutLua<'lua>
196{
197 fn lua_read_at_position(lua: L, index: i32) -> Result<Self, L> {
199 let mut me = lua;
200 unsafe { ffi::lua_pushnil(me.as_mut_lua().0) };
201 let index = index - 1;
202 let mut result = HashMap::new();
203
204 loop {
205 if unsafe { ffi::lua_next(me.as_mut_lua().0, index) } == 0 {
206 break;
207 }
208
209 let key = {
210 let maybe_key: Option<AnyHashableLuaValue> =
211 LuaRead::lua_read_at_position(&mut me, -2).ok();
212 match maybe_key {
213 None => {
214 unsafe { ffi::lua_pop(me.as_mut_lua().0, 2) };
216 return Err(me)
217 }
218 Some(k) => k,
219 }
220 };
221
222 let value: AnyLuaValue =
223 LuaRead::lua_read_at_position(&mut me, -1).ok().unwrap();
224
225 unsafe { ffi::lua_pop(me.as_mut_lua().0, 1) };
226
227 result.insert(key, value);
228 }
229
230 Ok(result)
231 }
232}
233
234impl<'lua, L, K, V, E> Push<L> for HashMap<K, V>
236 where L: AsMutLua<'lua>,
237 K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
238 V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
239{
240 type Err = E;
241
242 #[inline]
243 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
244 match push_rec_iter(lua, self.into_iter()) {
245 Ok(g) => Ok(g),
246 Err((TuplePushError::First(err), lua)) => Err((err, lua)),
247 Err((TuplePushError::Other(err), lua)) => Err((err, lua)),
248 }
249 }
250}
251
252impl<'lua, L, K, V, E> PushOne<L> for HashMap<K, V>
253 where L: AsMutLua<'lua>,
254 K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash,
255 V: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E>
256{
257}
258
259impl<'lua, L, K, E> Push<L> for HashSet<K>
260 where L: AsMutLua<'lua>,
261 K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
262{
263 type Err = E;
264
265 #[inline]
266 fn push_to_lua(self, lua: L) -> Result<PushGuard<L>, (E, L)> {
267 match push_rec_iter(lua, self.into_iter().zip(iter::repeat(true))) {
268 Ok(g) => Ok(g),
269 Err((TuplePushError::First(err), lua)) => Err((err, lua)),
270 Err((TuplePushError::Other(_), _)) => unreachable!(),
271 }
272 }
273}
274
275impl<'lua, L, K, E> PushOne<L> for HashSet<K>
276 where L: AsMutLua<'lua>,
277 K: for<'a, 'b> PushOne<&'a mut &'b mut L, Err = E> + Eq + Hash
278{
279}
280
281#[cfg(test)]
282mod tests {
283 use std::collections::{HashMap, HashSet, BTreeMap};
284 use Lua;
285 use LuaTable;
286 use AnyLuaValue;
287 use AnyHashableLuaValue;
288
289 #[test]
290 fn write() {
291 let mut lua = Lua::new();
292
293 lua.set("a", vec![9, 8, 7]);
294
295 let mut table: LuaTable<_> = lua.get("a").unwrap();
296
297 let values: Vec<(i32, i32)> = table.iter().filter_map(|e| e).collect();
298 assert_eq!(values, vec![(1, 9), (2, 8), (3, 7)]);
299 }
300
301 #[test]
302 fn write_map() {
303 let mut lua = Lua::new();
304
305 let mut map = HashMap::new();
306 map.insert(5, 8);
307 map.insert(13, 21);
308 map.insert(34, 55);
309
310 lua.set("a", map.clone());
311
312 let mut table: LuaTable<_> = lua.get("a").unwrap();
313
314 let values: HashMap<i32, i32> = table.iter().filter_map(|e| e).collect();
315 assert_eq!(values, map);
316 }
317
318 #[test]
319 fn write_set() {
320 let mut lua = Lua::new();
321
322 let mut set = HashSet::new();
323 set.insert(5);
324 set.insert(8);
325 set.insert(13);
326 set.insert(21);
327 set.insert(34);
328 set.insert(55);
329
330 lua.set("a", set.clone());
331
332 let mut table: LuaTable<_> = lua.get("a").unwrap();
333
334 let values: HashSet<i32> = table.iter()
335 .filter_map(|e| e)
336 .map(|(elem, set): (i32, bool)| {
337 assert!(set);
338 elem
339 })
340 .collect();
341
342 assert_eq!(values, set);
343 }
344
345 #[test]
346 fn globals_table() {
347 let mut lua = Lua::new();
348
349 lua.globals_table().set("a", 12);
350
351 let val: i32 = lua.get("a").unwrap();
352 assert_eq!(val, 12);
353 }
354
355 #[test]
356 fn reading_vec_works() {
357 let mut lua = Lua::new();
358
359 let orig = [1., 2., 3.];
360
361 lua.set("v", &orig[..]);
362
363 let read: Vec<_> = lua.get("v").unwrap();
364 for (o, r) in orig.iter().zip(read.iter()) {
365 if let AnyLuaValue::LuaNumber(ref n) = *r {
366 assert_eq!(o, n);
367 } else {
368 panic!("Unexpected variant");
369 }
370 }
371 }
372
373 #[test]
374 fn reading_vec_from_sparse_table_doesnt_work() {
375 let mut lua = Lua::new();
376
377 lua.execute::<()>(r#"v = { [-1] = -1, [2] = 2, [42] = 42 }"#).unwrap();
378
379 let read: Option<Vec<_>> = lua.get("v");
380 if read.is_some() {
381 panic!("Unexpected success");
382 }
383 }
384
385 #[test]
386 fn reading_vec_with_empty_table_works() {
387 let mut lua = Lua::new();
388
389 lua.execute::<()>(r#"v = { }"#).unwrap();
390
391 let read: Vec<_> = lua.get("v").unwrap();
392 assert_eq!(read.len(), 0);
393 }
394
395 #[test]
396 fn reading_vec_with_complex_indexes_doesnt_work() {
397 let mut lua = Lua::new();
398
399 lua.execute::<()>(r#"v = { [-1] = -1, ["foo"] = 2, [{}] = 42 }"#).unwrap();
400
401 let read: Option<Vec<_>> = lua.get("v");
402 if read.is_some() {
403 panic!("Unexpected success");
404 }
405 }
406
407 #[test]
408 fn reading_heterogenous_vec_works() {
409 let mut lua = Lua::new();
410
411 let orig = [
412 AnyLuaValue::LuaNumber(1.),
413 AnyLuaValue::LuaBoolean(false),
414 AnyLuaValue::LuaNumber(3.),
415 ];
418
419 lua.set("v", &orig[..]);
420
421 let read: Vec<_> = lua.get("v").unwrap();
422 assert_eq!(read, orig);
423 }
424
425 #[test]
426 fn reading_vec_set_from_lua_works() {
427 let mut lua = Lua::new();
428
429 lua.execute::<()>(r#"v = { 1, 2, 3 }"#).unwrap();
430
431 let read: Vec<_> = lua.get("v").unwrap();
432 assert_eq!(
433 read,
434 [1., 2., 3.].iter()
435 .map(|x| AnyLuaValue::LuaNumber(*x)).collect::<Vec<_>>());
436 }
437
438 #[test]
439 fn reading_hashmap_works() {
440 let mut lua = Lua::new();
441
442 let orig: HashMap<i32, f64> = [1., 2., 3.].into_iter().enumerate().map(|(k, v)| (k as i32, *v as f64)).collect();
443 let orig_copy = orig.clone();
444 let orig_btree: BTreeMap<_, _> = orig_copy.into_iter().collect();
446
447 lua.set("v", orig);
448
449 let read: HashMap<AnyHashableLuaValue, AnyLuaValue> = lua.get("v").unwrap();
450 let read_btree: BTreeMap<_, _> = read.into_iter().collect();
452 for (o, r) in orig_btree.iter().zip(read_btree.iter()) {
453 if let (&AnyHashableLuaValue::LuaNumber(i), &AnyLuaValue::LuaNumber(n)) = r {
454 let (&o_i, &o_n) = o;
455 assert_eq!(o_i, i);
456 assert_eq!(o_n, n);
457 } else {
458 panic!("Unexpected variant");
459 }
460 }
461 }
462
463 #[test]
464 fn reading_hashmap_from_sparse_table_works() {
465 let mut lua = Lua::new();
466
467 lua.execute::<()>(r#"v = { [-1] = -1, [2] = 2, [42] = 42 }"#).unwrap();
468
469 let read: HashMap<_, _> = lua.get("v").unwrap();
470 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(-1)], AnyLuaValue::LuaNumber(-1.));
471 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(2)], AnyLuaValue::LuaNumber(2.));
472 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(42)], AnyLuaValue::LuaNumber(42.));
473 assert_eq!(read.len(), 3);
474 }
475
476 #[test]
477 fn reading_hashmap_with_empty_table_works() {
478 let mut lua = Lua::new();
479
480 lua.execute::<()>(r#"v = { }"#).unwrap();
481
482 let read: HashMap<_, _> = lua.get("v").unwrap();
483 assert_eq!(read.len(), 0);
484 }
485
486 #[test]
487 fn reading_hashmap_with_complex_indexes_works() {
488 let mut lua = Lua::new();
489
490 lua.execute::<()>(r#"v = { [-1] = -1, ["foo"] = 2, [2.] = 42 }"#).unwrap();
491
492 let read: HashMap<_, _> = lua.get("v").unwrap();
493 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(-1)], AnyLuaValue::LuaNumber(-1.));
494 assert_eq!(read[&AnyHashableLuaValue::LuaString("foo".to_owned())], AnyLuaValue::LuaNumber(2.));
495 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(2)], AnyLuaValue::LuaNumber(42.));
496 assert_eq!(read.len(), 3);
497 }
498
499 #[test]
500 fn reading_hashmap_with_floating_indexes_works() {
501 let mut lua = Lua::new();
502
503 lua.execute::<()>(r#"v = { [-1.25] = -1, [2.5] = 42 }"#).unwrap();
504
505 let read: HashMap<_, _> = lua.get("v").unwrap();
506 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(-1)], AnyLuaValue::LuaNumber(-1.));
509 assert_eq!(read[&AnyHashableLuaValue::LuaNumber(2)], AnyLuaValue::LuaNumber(42.));
510 assert_eq!(read.len(), 2);
511 }
512
513 #[test]
514 fn reading_heterogenous_hashmap_works() {
515 let mut lua = Lua::new();
516
517 let mut orig = HashMap::new();
518 orig.insert(AnyHashableLuaValue::LuaNumber(42), AnyLuaValue::LuaNumber(42.));
519 orig.insert(AnyHashableLuaValue::LuaString("foo".to_owned()), AnyLuaValue::LuaString("foo".to_owned()));
520 orig.insert(AnyHashableLuaValue::LuaBoolean(true), AnyLuaValue::LuaBoolean(true));
521
522 let orig_clone = orig.clone();
523 lua.set("v", orig);
524
525 let read: HashMap<_, _> = lua.get("v").unwrap();
526 assert_eq!(read, orig_clone);
527 }
528
529 #[test]
530 fn reading_hashmap_set_from_lua_works() {
531 let mut lua = Lua::new();
532
533 lua.execute::<()>(r#"v = { [1] = 2, [2] = 3, [3] = 4 }"#).unwrap();
534
535 let read: HashMap<_, _> = lua.get("v").unwrap();
536 assert_eq!(
537 read,
538 [2., 3., 4.].iter().enumerate()
539 .map(|(k, v)| (AnyHashableLuaValue::LuaNumber((k + 1) as i32), AnyLuaValue::LuaNumber(*v))).collect::<HashMap<_, _>>());
540 }
541}