gameServer2/src/protocol/parser.rs
changeset 13431 6a818f9192f4
parent 13423 87a6cad20c90
child 13432 ee3fa3b8809d
equal deleted inserted replaced
13430:eb91b889101b 13431:6a818f9192f4
       
     1 /** The parsers for the chat and multiplayer protocol. The main parser is `message`.
       
     2  * # Protocol
       
     3  * All messages consist of `\n`-separated strings. The end of a message is
       
     4  * indicated by a double newline - `\n\n`.
       
     5  *
       
     6  * For example, a nullary command like PING will be actually sent as `PING\n\n`.
       
     7  * A unary command, such as `START_GAME nick` will be actually sent as `START_GAME\nnick\n\n`.
       
     8  */
       
     9 
     1 use nom::*;
    10 use nom::*;
     2 
    11 
     3 use std::{
    12 use std::{
     4     str, str::FromStr,
    13     str, str::FromStr,
     5     ops::Range
    14     ops::Range
    26               h3: hog_line >> eol >> h4: hog_line >> eol >>
    35               h3: hog_line >> eol >> h4: hog_line >> eol >>
    27               h5: hog_line >> eol >> h6: hog_line >> eol >>
    36               h5: hog_line >> eol >> h6: hog_line >> eol >>
    28               h7: hog_line >> eol >> h8: hog_line >>
    37               h7: hog_line >> eol >> h8: hog_line >>
    29               ([h1, h2, h3, h4, h5, h6, h7, h8])));
    38               ([h1, h2, h3, h4, h5, h6, h7, h8])));
    30 
    39 
       
    40 /** Recognizes messages which do not take any parameters */
    31 named!(basic_message<&[u8], HWProtocolMessage>, alt!(
    41 named!(basic_message<&[u8], HWProtocolMessage>, alt!(
    32       do_parse!(tag!("PING") >> (Ping))
    42       do_parse!(tag!("PING") >> (Ping))
    33     | do_parse!(tag!("PONG") >> (Pong))
    43     | do_parse!(tag!("PONG") >> (Pong))
    34     | do_parse!(tag!("LIST") >> (List))
    44     | do_parse!(tag!("LIST") >> (List))
    35     | do_parse!(tag!("BANLIST")        >> (BanList))
    45     | do_parse!(tag!("BANLIST")        >> (BanList))
    40     | do_parse!(tag!("TOGGLE_RESTRICT_JOINS")  >> (ToggleRestrictJoin))
    50     | do_parse!(tag!("TOGGLE_RESTRICT_JOINS")  >> (ToggleRestrictJoin))
    41     | do_parse!(tag!("TOGGLE_RESTRICT_TEAMS")  >> (ToggleRestrictTeams))
    51     | do_parse!(tag!("TOGGLE_RESTRICT_TEAMS")  >> (ToggleRestrictTeams))
    42     | do_parse!(tag!("TOGGLE_REGISTERED_ONLY") >> (ToggleRegisteredOnly))
    52     | do_parse!(tag!("TOGGLE_REGISTERED_ONLY") >> (ToggleRegisteredOnly))
    43 ));
    53 ));
    44 
    54 
       
    55 /** Recognizes messages which take exactly one parameter */
    45 named!(one_param_message<&[u8], HWProtocolMessage>, alt!(
    56 named!(one_param_message<&[u8], HWProtocolMessage>, alt!(
    46       do_parse!(tag!("NICK")    >> eol >> n: a_line >> (Nick(n)))
    57       do_parse!(tag!("NICK")    >> eol >> n: a_line >> (Nick(n)))
    47     | do_parse!(tag!("INFO")    >> eol >> n: a_line >> (Info(n)))
    58     | do_parse!(tag!("INFO")    >> eol >> n: a_line >> (Info(n)))
    48     | do_parse!(tag!("CHAT")    >> eol >> m: a_line >> (Chat(m)))
    59     | do_parse!(tag!("CHAT")    >> eol >> m: a_line >> (Chat(m)))
    49     | do_parse!(tag!("PART")    >> msg: opt_param   >> (Part(msg)))
    60     | do_parse!(tag!("PART")    >> msg: opt_param   >> (Part(msg)))
    58     | do_parse!(tag!("PROTO")   >> eol >> d: u32_line >> (Proto(d)))
    69     | do_parse!(tag!("PROTO")   >> eol >> d: u32_line >> (Proto(d)))
    59 
    70 
    60     | do_parse!(tag!("QUIT")   >> msg: opt_param >> (Quit(msg)))
    71     | do_parse!(tag!("QUIT")   >> msg: opt_param >> (Quit(msg)))
    61 ));
    72 ));
    62 
    73 
       
    74 /** Recognizes messages preceded with CMD */
    63 named!(cmd_message<&[u8], HWProtocolMessage>, preceded!(tag!("CMD\n"), alt!(
    75 named!(cmd_message<&[u8], HWProtocolMessage>, preceded!(tag!("CMD\n"), alt!(
    64       do_parse!(tag_no_case!("STATS") >> (Stats))
    76       do_parse!(tag_no_case!("STATS") >> (Stats))
    65     | do_parse!(tag_no_case!("FIX")   >> (Fix))
    77     | do_parse!(tag_no_case!("FIX")   >> (Fix))
    66     | do_parse!(tag_no_case!("UNFIX") >> (Unfix))
    78     | do_parse!(tag_no_case!("UNFIX") >> (Unfix))
    67     | do_parse!(tag_no_case!("RESTART_SERVER") >> eol >> tag!("YES") >> (RestartServer))
    79     | do_parse!(tag_no_case!("RESTART_SERVER") >> eol >> tag!("YES") >> (RestartServer))
    78     | do_parse!(tag_no_case!("GREETING") >> eol >> m: a_line  >> (Greeting(m)))
    90     | do_parse!(tag_no_case!("GREETING") >> eol >> m: a_line  >> (Greeting(m)))
    79     | do_parse!(tag_no_case!("VOTE")     >> eol >> m: a_line  >> (Vote(m)))
    91     | do_parse!(tag_no_case!("VOTE")     >> eol >> m: a_line  >> (Vote(m)))
    80     | do_parse!(tag_no_case!("FORCE")    >> eol >> m: a_line  >> (ForceVote(m)))
    92     | do_parse!(tag_no_case!("FORCE")    >> eol >> m: a_line  >> (ForceVote(m)))
    81     | do_parse!(tag_no_case!("INFO")     >> eol >> n: a_line  >> (Info(n)))
    93     | do_parse!(tag_no_case!("INFO")     >> eol >> n: a_line  >> (Info(n)))
    82     | do_parse!(tag_no_case!("MAXTEAMS") >> eol >> n: u8_line >> (MaxTeams(n)))
    94     | do_parse!(tag_no_case!("MAXTEAMS") >> eol >> n: u8_line >> (MaxTeams(n)))
       
    95     | do_parse!(
       
    96         tag_no_case!("RND") >>
       
    97         v: str_line >>
       
    98         (Rnd(v.split_whitespace().map(String::from).collect())))
    83 )));
    99 )));
    84 
   100 
    85 named!(complex_message<&[u8], HWProtocolMessage>, alt!(
   101 named!(complex_message<&[u8], HWProtocolMessage>, alt!(
    86       do_parse!(tag!("PASSWORD")  >> eol >>
   102       do_parse!(tag!("PASSWORD")  >> eol >>
    87                     p: a_line     >> eol >>
   103                     p: a_line     >> eol >>
   220     assert_eq!(message(b"BAN\nme\nbad\n77\n\n"), IResult::Done(&b""[..], Ban("me".to_string(), "bad".to_string(), 77)));
   236     assert_eq!(message(b"BAN\nme\nbad\n77\n\n"), IResult::Done(&b""[..], Ban("me".to_string(), "bad".to_string(), 77)));
   221 
   237 
   222     assert_eq!(message(b"CMD\nPART\n\n"),      IResult::Done(&b""[..], Part(None)));
   238     assert_eq!(message(b"CMD\nPART\n\n"),      IResult::Done(&b""[..], Part(None)));
   223     assert_eq!(message(b"CMD\nPART\n_msg_\n\n"), IResult::Done(&b""[..], Part(Some("_msg_".to_string()))));
   239     assert_eq!(message(b"CMD\nPART\n_msg_\n\n"), IResult::Done(&b""[..], Part(Some("_msg_".to_string()))));
   224 
   240 
       
   241     assert_eq!(message(b"CMD\nRND\n\n"), IResult::Done(&b""[..], Rnd(vec![])));
       
   242     assert_eq!(
       
   243         message(b"CMD\nRND A B\n\n"),
       
   244         IResult::Done(&b""[..], Rnd(vec![String::from("A"), String::from("B")]))
       
   245     );
       
   246 
   225     assert_eq!(extract_messages(b"QUIT\n1\n2\n\n"),    IResult::Done(&b""[..], vec![Malformed]));
   247     assert_eq!(extract_messages(b"QUIT\n1\n2\n\n"),    IResult::Done(&b""[..], vec![Malformed]));
   226 
   248 
   227     assert_eq!(extract_messages(b"PING\n\nPING\n\nP"), IResult::Done(&b"P"[..], vec![Ping, Ping]));
   249     assert_eq!(extract_messages(b"PING\n\nPING\n\nP"), IResult::Done(&b"P"[..], vec![Ping, Ping]));
   228     assert_eq!(extract_messages(b"SING\n\nPING\n\n"),  IResult::Done(&b""[..],  vec![Malformed, Ping]));
   250     assert_eq!(extract_messages(b"SING\n\nPING\n\n"),  IResult::Done(&b""[..],  vec![Malformed, Ping]));
   229     assert_eq!(extract_messages(b"\n\n\n\nPING\n\n"),  IResult::Done(&b""[..],  vec![Empty, Empty, Ping]));
   251     assert_eq!(extract_messages(b"\n\n\n\nPING\n\n"),  IResult::Done(&b""[..],  vec![Empty, Empty, Ping]));