hlua_badtouch/
tuples.rs

1use AsMutLua;
2use AsLua;
3
4use Push;
5use PushOne;
6use PushGuard;
7use LuaRead;
8use Void;
9
10macro_rules! tuple_impl {
11    ($ty:ident) => (
12        impl<'lua, LU, $ty> Push<LU> for ($ty,) where LU: AsMutLua<'lua>, $ty: Push<LU> {
13            type Err = <$ty as Push<LU>>::Err;
14
15            #[inline]
16            fn push_to_lua(self, lua: LU) -> Result<PushGuard<LU>, (Self::Err, LU)> {
17                self.0.push_to_lua(lua)
18            }
19        }
20
21        impl<'lua, LU, $ty> PushOne<LU> for ($ty,) where LU: AsMutLua<'lua>, $ty: PushOne<LU> {
22        }
23
24        impl<'lua, LU, $ty> LuaRead<LU> for ($ty,) where LU: AsMutLua<'lua>, $ty: LuaRead<LU> {
25            #[inline]
26            fn lua_read_at_position(lua: LU, index: i32) -> Result<($ty,), LU> {
27                LuaRead::lua_read_at_position(lua, index).map(|v| (v,))
28            }
29        }
30    );
31
32    ($first:ident, $($other:ident),+) => (
33        #[allow(non_snake_case)]
34        impl<'lua, LU, FE, OE, $first, $($other),+> Push<LU> for ($first, $($other),+)
35            where LU: AsMutLua<'lua>,
36                  $first: for<'a> Push<&'a mut LU, Err = FE>,
37                  ($($other,)+): for<'a> Push<&'a mut LU, Err = OE>
38        {
39            type Err = TuplePushError<FE, OE>;
40
41            #[inline]
42            fn push_to_lua(self, mut lua: LU) -> Result<PushGuard<LU>, (Self::Err, LU)> {
43                match self {
44                    ($first, $($other),+) => {
45                        let mut total = 0;
46
47                        let first_err = match $first.push_to_lua(&mut lua) {
48                            Ok(pushed) => { total += pushed.forget_internal(); None },
49                            Err((err, _)) => Some(err),
50                        };
51
52                        if let Some(err) = first_err {
53                            return Err((TuplePushError::First(err), lua));
54                        }
55
56                        let rest = ($($other,)+);
57                        let other_err = match rest.push_to_lua(&mut lua) {
58                            Ok(pushed) => { total += pushed.forget_internal(); None },
59                            Err((err, _)) => Some(err),
60                        };
61
62                        if let Some(err) = other_err {
63                            return Err((TuplePushError::Other(err), lua));
64                        }
65
66                        let raw_lua = lua.as_lua();
67                        Ok(PushGuard { lua: lua, size: total, raw_lua: raw_lua })
68                    }
69                }
70            }
71        }
72
73        // TODO: what if T or U are also tuples? indices won't match
74        #[allow(unused_assignments)]
75        #[allow(non_snake_case)]
76        impl<'lua, LU, $first: for<'a> LuaRead<&'a mut LU>, $($other: for<'a> LuaRead<&'a mut LU>),+>
77            LuaRead<LU> for ($first, $($other),+) where LU: AsLua<'lua>
78        {
79            #[inline]
80            fn lua_read_at_position(mut lua: LU, index: i32) -> Result<($first, $($other),+), LU> {
81                let mut i = index;
82
83                let $first: $first = match LuaRead::lua_read_at_position(&mut lua, i) {
84                    Ok(v) => v,
85                    Err(_) => return Err(lua)
86                };
87
88                i += 1;
89
90                $(
91                    let $other: $other = match LuaRead::lua_read_at_position(&mut lua, i) {
92                        Ok(v) => v,
93                        Err(_) => return Err(lua)
94                    };
95                    i += 1;
96                )+
97
98                Ok(($first, $($other),+))
99
100            }
101        }
102
103        tuple_impl!($($other),+);
104    );
105}
106
107tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L, M);
108
109/// Error that can happen when pushing multiple values at once.
110// TODO: implement Error on that thing
111#[derive(Debug, Copy, Clone)]
112pub enum TuplePushError<C, O> {
113    First(C),
114    Other(O),
115}
116
117impl From<TuplePushError<Void, Void>> for Void {
118    #[inline]
119    fn from(_: TuplePushError<Void, Void>) -> Void {
120        unreachable!()
121    }
122}