1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use crate::deser::{Deser, Result, Tracker};
use crate::tokens::{Token, TokenKind};

macro_rules! tuple {
    ({ $(($n:ident, $i:tt)),* }) => {
        impl<$($n),*> Deser for ($($n),*)
            where $($n : Deser),*
        {
            fn deser<'a, 'b>(tracker: &mut Tracker<'a, 'b>) -> Result<Self> {
                let open = Token::new_borrowed(TokenKind::TupleOpen, "(");
                let close = Token::new_borrowed(TokenKind::TupleClose, ")");
                let comma = Token::new_borrowed(TokenKind::Comma, ", ");

                tracker.try_token(&open)?;
                Ok(($(
                    {
                        let x : $n = Deser::deser(tracker)?;
                        if $i {
                            tracker.try_token(&close)?;
                        } else {
                            tracker.try_token(&comma)?;
                        }
                        x
                    }
                ),*))
            }
        }
    };
}

tuple!({(A, false), (B, true)});
tuple!({(A, false), (B, false), (C, true)});
tuple!({(A, false), (B, false), (C, false), (D, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, false), (F, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, false), (F, false), (G, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, false), (F, false), (G, false), (H, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, false), (F, false), (G, false), (H, false), (I, true)});
tuple!({(A, false), (B, false), (C, false), (D, false), (E, false), (F, false), (G, false), (H, false), (I, false), (J, true)});

impl<A> Deser for (A,)
where
    A: Deser,
{
    fn deser<'a, 'b>(tracker: &mut Tracker<'a, 'b>) -> Result<Self> {
        let open = Token::new_borrowed(TokenKind::TupleOpen, "(");
        let close = Token::new_borrowed(TokenKind::TupleClose, ")");
        tracker.try_token(&open)?;
        let a = Deser::deser(tracker)?;
        // TODO: allow for an extra ',' token
        tracker.try_token(&close)?;
        Ok((a,))
    }
}

impl Deser for () {
    fn deser<'a, 'b>(tracker: &mut Tracker<'a, 'b>) -> Result<Self> {
        let open = Token::new_borrowed(TokenKind::TupleOpen, "(");
        let close = Token::new_borrowed(TokenKind::TupleClose, ")");
        tracker.try_token(&open)?;
        tracker.try_token(&close)?;
        Ok(())
    }
}