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
//! A library for parsing Minecraft protocol specification.

pub mod base;
pub mod enums;
pub mod packets;
#[cfg(feature = "spec")]
pub mod spec;
pub mod types;

use specmc_base::parse::{Parse, ParseError};

use enums::Enum;
use packets::Packet;
use types::CustomType;

#[derive(Debug, Clone, PartialEq)]
pub struct Protocol {
    pub enums: Vec<Enum>,
    pub types: Vec<CustomType>,
    pub packets: Vec<Packet>,
}
impl Parse for Protocol {
    fn parse(tokens: &mut Vec<String>) -> Result<Self, specmc_base::parse::ParseError> {
        let mut enums: Vec<Enum> = vec![];
        let mut types: Vec<CustomType> = vec![];
        let mut packets: Vec<Packet> = vec![];
        while !tokens.is_empty() {
            match tokens.last().unwrap().as_str() {
                "enum" => {
                    enums.push(Enum::parse(tokens)?);
                }
                "type" => {
                    types.push(CustomType::parse(tokens)?);
                }
                "packet" => {
                    packets.push(Packet::parse(tokens)?);
                }
                token => {
                    return Err(ParseError::InvalidToken {
                        token: token.to_string(),
                        error: "Expected \"enum\", \"type\" or \"packet\"".to_string(),
                    });
                }
            }
        }

        Ok(Protocol {
            enums,
            types,
            packets,
        })
    }
}

#[cfg(test)]
mod tests {
    #[macro_export]
    macro_rules! test_parse {
        ($tokens:ident, $ty:ty, $value:expr) => {
            assert_eq!(<$ty>::parse(&mut $tokens), $value);
        };
    }
}