rust/hedgewars-engine-messages/src/parser.rs
changeset 14214 77b95406631e
parent 14211 0f7b92397b9e
child 14254 9f4d75fa4a2c
equal deleted inserted replaced
14213:09dacb61d526 14214:77b95406631e
     1 use nom::{*, Err::Error};
     1 use nom::{Err::Error, *};
     2 use std::str;
     2 use std::str;
     3 
     3 
     4 use super::messages::{*, EngineMessage::*, UnsyncedEngineMessage::*, SyncedEngineMessage::*, ConfigEngineMessage::*, KeystrokeAction::*};
     4 use super::messages::{
     5 
     5     ConfigEngineMessage::*, EngineMessage::*, KeystrokeAction::*, SyncedEngineMessage::*,
       
     6     UnorderedEngineMessage::*, UnsyncedEngineMessage::*, *,
       
     7 };
     6 
     8 
     7 macro_rules! eof_slice (
     9 macro_rules! eof_slice (
     8   ($i:expr,) => (
    10   ($i:expr,) => (
     9     {
    11     {
    10       if ($i).input_len() == 0 {
    12       if ($i).input_len() == 0 {
    25 named!(length_without_timestamp<&[u8], usize>,
    27 named!(length_without_timestamp<&[u8], usize>,
    26     map_opt!(rest_len, |l| if l > 2 { Some(l - 2) } else { None } )
    28     map_opt!(rest_len, |l| if l > 2 { Some(l - 2) } else { None } )
    27 );
    29 );
    28 
    30 
    29 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    31 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    30       do_parse!(tag!("L") >> (Left(Press)))
    32         do_parse!(tag!("L") >> (Left(Press)))
    31       | do_parse!(tag!("l") >> ( Left(Release) ))
    33       | do_parse!(tag!("l") >> ( Left(Release) ))
    32       | do_parse!(tag!("R") >> ( Right(Press) ))
    34       | do_parse!(tag!("R") >> ( Right(Press) ))
    33       | do_parse!(tag!("r") >> ( Right(Release) ))
    35       | do_parse!(tag!("r") >> ( Right(Release) ))
    34       | do_parse!(tag!("U") >> ( Up(Press) ))
    36       | do_parse!(tag!("U") >> ( Up(Press) ))
    35       | do_parse!(tag!("u") >> ( Up(Release) ))
    37       | do_parse!(tag!("u") >> ( Up(Release) ))
    51       | do_parse!(tag!("5") >> ( Timer(5) ))
    53       | do_parse!(tag!("5") >> ( Timer(5) ))
    52       | do_parse!(tag!("p") >> x: be_i24 >> y: be_i24 >> ( Put(x, y) ))
    54       | do_parse!(tag!("p") >> x: be_i24 >> y: be_i24 >> ( Put(x, y) ))
    53       | do_parse!(tag!("P") >> x: be_i24 >> y: be_i24 >> ( CursorMove(x, y) ))
    55       | do_parse!(tag!("P") >> x: be_i24 >> y: be_i24 >> ( CursorMove(x, y) ))
    54       | do_parse!(tag!("f") >> s: string_tail >> ( SyncedEngineMessage::TeamControlLost(s) ))
    56       | do_parse!(tag!("f") >> s: string_tail >> ( SyncedEngineMessage::TeamControlLost(s) ))
    55       | do_parse!(tag!("g") >> s: string_tail >> ( SyncedEngineMessage::TeamControlGained(s) ))
    57       | do_parse!(tag!("g") >> s: string_tail >> ( SyncedEngineMessage::TeamControlGained(s) ))
    56       /*
    58       | do_parse!(tag!("h") >> s: string_tail >> ( HogSay(s) ))
    57     Slot(u8),
    59       | do_parse!(tag!("t") >> t: be_u8 >> ( Taunt(t) ))
    58     SetWeapon(u8),
    60       | do_parse!(tag!("w") >> w: be_u8 >> ( SetWeapon(w) ))
    59           */
    61       | do_parse!(tag!("~") >> s: be_u8 >> ( Slot(s) ))
       
    62       | do_parse!(tag!("+") >> ( Heartbeat ))
    60 ));
    63 ));
    61 
    64 
    62 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    65 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    63       do_parse!(tag!("?") >> (Ping))
    66         do_parse!(tag!("F") >> s: string_tail >> ( UnsyncedEngineMessage::TeamControlLost(s) ))
    64     | do_parse!(tag!("!") >> (Ping))
    67       | do_parse!(tag!("G") >> s: string_tail >> ( UnsyncedEngineMessage::TeamControlGained(s) ))
    65     | do_parse!(tag!("esay ") >> s: string_tail >> (Say(s)))
    68 ));
       
    69 
       
    70 named!(unordered_message<&[u8], UnorderedEngineMessage>, alt!(
       
    71       do_parse!(tag!("?") >> ( Ping ))
       
    72     | do_parse!(tag!("!") >> ( Ping ))
       
    73     | do_parse!(tag!("s") >> s: string_tail >> ( ChatMessage(s)) )
       
    74     | do_parse!(tag!("b") >> s: string_tail >> ( TeamMessage(s)) ) // TODO: wtf is the format
       
    75     | do_parse!(tag!("M") >> s: string_tail >> ( GameSetupChecksum(s)) )
       
    76     | do_parse!(tag!("o") >> ( StopSyncing ))
       
    77     | do_parse!(tag!("I") >> ( PauseToggled ))
    66 ));
    78 ));
    67 
    79 
    68 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    80 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    69     do_parse!(tag!("C") >> (ConfigRequest))
    81     do_parse!(tag!("C") >> (ConfigRequest))
    70 ));
    82 ));
    78 
    90 
    79 named!(unwrapped_message<&[u8], EngineMessage>,
    91 named!(unwrapped_message<&[u8], EngineMessage>,
    80     alt!(
    92     alt!(
    81         map!(timestamped_message, |(m, t)| Synced(m, t as u32))
    93         map!(timestamped_message, |(m, t)| Synced(m, t as u32))
    82         | do_parse!(tag!("#") >> (Synced(TimeWrap, 65535)))
    94         | do_parse!(tag!("#") >> (Synced(TimeWrap, 65535)))
       
    95         | map!(unordered_message, |m| Unordered(m))
    83         | map!(unsynced_message, |m| Unsynced(m))
    96         | map!(unsynced_message, |m| Unsynced(m))
    84         | map!(config_message, |m| Config(m))
    97         | map!(config_message, |m| Config(m))
    85         | unrecognized_message
    98         | unrecognized_message
    86 ));
    99 ));
    87 
       
    88 
       
    89 
   100 
    90 named!(length_specifier<&[u8], u16>, alt!(
   101 named!(length_specifier<&[u8], u16>, alt!(
    91     verify!(map!(take!(1), |a : &[u8]| a[0] as u16), |l| l < 64)
   102     verify!(map!(take!(1), |a : &[u8]| a[0] as u16), |l| l < 64)
    92     | map!(take!(2), |a| (a[0] as u16 - 64) * 256 + a[1] as u16 + 64)
   103     | map!(take!(2), |a| (a[0] as u16 - 64) * 256 + a[1] as u16 + 64)
    93     )
   104     )
   112 fn parse_length() {
   123 fn parse_length() {
   113     assert_eq!(length_specifier(b"\x01"), Ok((&b""[..], 1)));
   124     assert_eq!(length_specifier(b"\x01"), Ok((&b""[..], 1)));
   114     assert_eq!(length_specifier(b"\x00"), Ok((&b""[..], 0)));
   125     assert_eq!(length_specifier(b"\x00"), Ok((&b""[..], 0)));
   115     assert_eq!(length_specifier(b"\x3f"), Ok((&b""[..], 63)));
   126     assert_eq!(length_specifier(b"\x3f"), Ok((&b""[..], 63)));
   116     assert_eq!(length_specifier(b"\x40\x00"), Ok((&b""[..], 64)));
   127     assert_eq!(length_specifier(b"\x40\x00"), Ok((&b""[..], 64)));
   117     assert_eq!(length_specifier(b"\xff\xff"), Ok((&b""[..], 49215)));
   128     assert_eq!(
       
   129         length_specifier(b"\xff\xff"),
       
   130         Ok((&b""[..], EngineMessage::MAX_LEN))
       
   131     );
   118 }
   132 }
   119 
   133 
   120 #[test]
   134 #[test]
   121 fn parse_synced_messages() {
   135 fn parse_synced_messages() {
   122     assert_eq!(message(b"\x03L\x01\x02"), Ok((&b""[..], Synced(Left(Press), 258))));
   136     assert_eq!(
       
   137         message(b"\x03L\x01\x02"),
       
   138         Ok((&b""[..], Synced(Left(Press), 258)))
       
   139     );
   123     assert_eq!(message(b"\x01#"), Ok((&b""[..], Synced(TimeWrap, 65535))));
   140     assert_eq!(message(b"\x01#"), Ok((&b""[..], Synced(TimeWrap, 65535))));
   124 }
   141 }
   125 
   142 
   126 #[test]
   143 #[test]
   127 fn parse_unsynced_messages() {
   144 fn parse_unsynced_messages() {
   128     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));
   145     assert_eq!(
       
   146         message(b"\x06shello"),
       
   147         Ok((&b""[..], Unordered(ChatMessage(String::from("hello")))))
       
   148     );
   129 }
   149 }
   130 
   150 
   131 #[test]
   151 #[test]
   132 fn parse_incorrect_messages() {
   152 fn parse_incorrect_messages() {
   133     assert_eq!(message(b"\x00"), Ok((&b""[..], Empty)));
   153     assert_eq!(message(b"\x00"), Ok((&b""[..], Empty)));
   137     assert_eq!(message(b"\x04La\x01\x02"), Ok((&b""[..], Unknown)));
   157     assert_eq!(message(b"\x04La\x01\x02"), Ok((&b""[..], Unknown)));
   138 }
   158 }
   139 
   159 
   140 #[test]
   160 #[test]
   141 fn parse_config_messages() {
   161 fn parse_config_messages() {
   142     assert_eq!(
   162     assert_eq!(message(b"\x01C"), Ok((&b""[..], Config(ConfigRequest))));
   143         message(b"\x01C"),
       
   144         Ok((
       
   145             &b""[..],
       
   146             Config(ConfigRequest)
       
   147         ))
       
   148     );
       
   149 }
   163 }
       
   164 
   150 #[test]
   165 #[test]
   151 fn parse_test_general() {
   166 fn parse_test_general() {
   152     assert_eq!(string_tail(b"abc"), Ok((&b""[..], String::from("abc"))));
   167     assert_eq!(string_tail(b"abc"), Ok((&b""[..], String::from("abc"))));
   153 }
   168 }