rust/hedgewars-engine-messages/src/parser.rs
changeset 14211 0f7b92397b9e
parent 14210 1c55c54013c4
child 14214 77b95406631e
equal deleted inserted replaced
14210:1c55c54013c4 14211:0f7b92397b9e
     1 use nom::{*};
     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::{*, EngineMessage::*, UnsyncedEngineMessage::*, SyncedEngineMessage::*, ConfigEngineMessage::*, KeystrokeAction::*};
     5 
     5 
     6 
     6 
       
     7 macro_rules! eof_slice (
       
     8   ($i:expr,) => (
       
     9     {
       
    10       if ($i).input_len() == 0 {
       
    11         Ok(($i, $i))
       
    12       } else {
       
    13         Err(Error(error_position!($i, ErrorKind::Eof::<u32>)))
       
    14       }
       
    15     }
       
    16   );
       
    17 );
     7 
    18 
     8 named!(unrecognized_message<&[u8], EngineMessage>,
    19 named!(unrecognized_message<&[u8], EngineMessage>,
     9     do_parse!(rest >> (Unknown))
    20     do_parse!(rest >> (Unknown))
    10 );
    21 );
    11 
    22 
    15     map_opt!(rest_len, |l| if l > 2 { Some(l - 2) } else { None } )
    26     map_opt!(rest_len, |l| if l > 2 { Some(l - 2) } else { None } )
    16 );
    27 );
    17 
    28 
    18 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    29 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    19       do_parse!(tag!("L") >> (Left(Press)))
    30       do_parse!(tag!("L") >> (Left(Press)))
       
    31       | do_parse!(tag!("l") >> ( Left(Release) ))
       
    32       | do_parse!(tag!("R") >> ( Right(Press) ))
       
    33       | do_parse!(tag!("r") >> ( Right(Release) ))
       
    34       | do_parse!(tag!("U") >> ( Up(Press) ))
       
    35       | do_parse!(tag!("u") >> ( Up(Release) ))
       
    36       | do_parse!(tag!("D") >> ( Down(Press) ))
       
    37       | do_parse!(tag!("d") >> ( Down(Release) ))
       
    38       | do_parse!(tag!("Z") >> ( Precise(Press) ))
       
    39       | do_parse!(tag!("z") >> ( Precise(Release) ))
       
    40       | do_parse!(tag!("A") >> ( Attack(Press) ))
       
    41       | do_parse!(tag!("a") >> ( Attack(Release) ))
       
    42       | do_parse!(tag!("N") >> ( NextTurn ))
       
    43       | do_parse!(tag!("j") >> ( LongJump ))
       
    44       | do_parse!(tag!("J") >> ( HighJump ))
       
    45       | do_parse!(tag!("S") >> ( Switch ))
       
    46       | do_parse!(tag!(",") >> ( Skip ))
       
    47       | do_parse!(tag!("1") >> ( Timer(1) ))
       
    48       | do_parse!(tag!("2") >> ( Timer(2) ))
       
    49       | do_parse!(tag!("3") >> ( Timer(3) ))
       
    50       | do_parse!(tag!("4") >> ( Timer(4) ))
       
    51       | do_parse!(tag!("5") >> ( Timer(5) ))
       
    52       | 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) ))
       
    54       | do_parse!(tag!("f") >> s: string_tail >> ( SyncedEngineMessage::TeamControlLost(s) ))
       
    55       | do_parse!(tag!("g") >> s: string_tail >> ( SyncedEngineMessage::TeamControlGained(s) ))
       
    56       /*
       
    57     Slot(u8),
       
    58     SetWeapon(u8),
       
    59           */
    20 ));
    60 ));
    21 
       
    22 named!(timestamped_message<&[u8], (SyncedEngineMessage, u16)>,
       
    23     do_parse!(msg: length_value!(length_without_timestamp, synced_message)
       
    24         >> timestamp: be_u16
       
    25         >> ((msg, timestamp))
       
    26     )
       
    27 );
       
    28 
    61 
    29 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    62 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    30       do_parse!(tag!("?") >> (Ping))
    63       do_parse!(tag!("?") >> (Ping))
    31     | do_parse!(tag!("!") >> (Ping))
    64     | do_parse!(tag!("!") >> (Ping))
    32     | do_parse!(tag!("esay ") >> s: string_tail  >> (Say(s)))
    65     | do_parse!(tag!("esay ") >> s: string_tail >> (Say(s)))
    33 ));
    66 ));
    34 
    67 
    35 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    68 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    36     do_parse!(tag!("C") >> (ConfigRequest))
    69     do_parse!(tag!("C") >> (ConfigRequest))
    37 ));
    70 ));
       
    71 
       
    72 named!(timestamped_message<&[u8], (SyncedEngineMessage, u16)>,
       
    73     do_parse!(msg: length_value!(length_without_timestamp, terminated!(synced_message, eof_slice!()))
       
    74         >> timestamp: be_u16
       
    75         >> ((msg, timestamp))
       
    76     )
       
    77 );
    38 
    78 
    39 named!(unwrapped_message<&[u8], EngineMessage>,
    79 named!(unwrapped_message<&[u8], EngineMessage>,
    40     alt!(
    80     alt!(
    41         map!(timestamped_message, |(m, t)| Synced(m, t as u32))
    81         map!(timestamped_message, |(m, t)| Synced(m, t as u32))
    42         | do_parse!(tag!("#") >> (Synced(TimeWrap, 65535)))
    82         | do_parse!(tag!("#") >> (Synced(TimeWrap, 65535)))
    56 named!(empty_message<&[u8], EngineMessage>,
    96 named!(empty_message<&[u8], EngineMessage>,
    57     do_parse!(tag!("\0") >> (Empty))
    97     do_parse!(tag!("\0") >> (Empty))
    58 );
    98 );
    59 
    99 
    60 named!(non_empty_message<&[u8], EngineMessage>,
   100 named!(non_empty_message<&[u8], EngineMessage>,
    61     length_value!(length_specifier, unwrapped_message));
   101     length_value!(length_specifier, terminated!(unwrapped_message, eof_slice!())));
    62 
   102 
    63 named!(message<&[u8], EngineMessage>, alt!(
   103 named!(message<&[u8], EngineMessage>, alt!(
    64       empty_message
   104       empty_message
    65     | non_empty_message
   105     | non_empty_message
    66     )
   106     )
    78 }
   118 }
    79 
   119 
    80 #[test]
   120 #[test]
    81 fn parse_synced_messages() {
   121 fn parse_synced_messages() {
    82     assert_eq!(message(b"\x03L\x01\x02"), Ok((&b""[..], Synced(Left(Press), 258))));
   122     assert_eq!(message(b"\x03L\x01\x02"), Ok((&b""[..], Synced(Left(Press), 258))));
       
   123     assert_eq!(message(b"\x01#"), Ok((&b""[..], Synced(TimeWrap, 65535))));
    83 }
   124 }
    84 
   125 
    85 #[test]
   126 #[test]
    86 fn parse_unsynced_messages() {
   127 fn parse_unsynced_messages() {
    87     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));
   128     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));
    89 
   130 
    90 #[test]
   131 #[test]
    91 fn parse_incorrect_messages() {
   132 fn parse_incorrect_messages() {
    92     assert_eq!(message(b"\x00"), Ok((&b""[..], Empty)));
   133     assert_eq!(message(b"\x00"), Ok((&b""[..], Empty)));
    93     assert_eq!(message(b"\x01\x00"), Ok((&b""[..], Unknown)));
   134     assert_eq!(message(b"\x01\x00"), Ok((&b""[..], Unknown)));
       
   135 
       
   136     // garbage after correct message
       
   137     assert_eq!(message(b"\x04La\x01\x02"), Ok((&b""[..], Unknown)));
    94 }
   138 }
    95 
   139 
    96 #[test]
   140 #[test]
    97 fn parse_config_messages() {
   141 fn parse_config_messages() {
    98     assert_eq!(
   142     assert_eq!(