rust/hedgewars-engine-messages/src/parser.rs
changeset 14214 ab1ef7074e07
child 14215 1c55c54013c4
equal deleted inserted replaced
14213:87f1054c2333 14214:ab1ef7074e07
       
     1 use nom::*;
       
     2 use std::str;
       
     3 
       
     4 use super::messages::{*, EngineMessage::*, UnsyncedEngineMessage::*, SyncedEngineMessage::*, ConfigEngineMessage::*, KeystrokeAction::*};
       
     5 
       
     6 named!(length_specifier<&[u8], u16>, alt!(
       
     7     verify!(map!(take!(1), |a : &[u8]| a[0] as u16), |l| l < 64)
       
     8     | map!(take!(2), |a| (a[0] as u16 - 64) * 256 + a[1] as u16 + 64)
       
     9     )
       
    10 );
       
    11 
       
    12 named!(unrecognized_message<&[u8], EngineMessage>,
       
    13     do_parse!(rest >> (Unknown))
       
    14 );
       
    15 
       
    16 named!(string_tail<&[u8], String>, map!(map_res!(rest, str::from_utf8), String::from));
       
    17 
       
    18 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
       
    19       do_parse!(tag!("+l") >> (Left(Press)))
       
    20 ));
       
    21 
       
    22 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
       
    23       do_parse!(tag!("?") >> (Ping))
       
    24     | do_parse!(tag!("!") >> (Ping))
       
    25     | do_parse!(tag!("esay ") >> s: string_tail  >> (Say(s)))
       
    26 ));
       
    27 
       
    28 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
       
    29     do_parse!(tag!("C") >> (ConfigRequest))
       
    30 ));
       
    31 
       
    32 named!(empty_message<&[u8], EngineMessage>,
       
    33     do_parse!(tag!("\0") >> (Empty))
       
    34 );
       
    35 
       
    36 named!(non_empty_message<&[u8], EngineMessage>, length_value!(length_specifier,
       
    37     alt!(
       
    38           map!(synced_message, |m| Synced(m, 0))
       
    39         | map!(unsynced_message, |m| Unsynced(m))
       
    40         | map!(config_message, |m| Config(m))
       
    41         | unrecognized_message
       
    42     )
       
    43 ));
       
    44 
       
    45 named!(message<&[u8], EngineMessage>, alt!(
       
    46       empty_message
       
    47     | non_empty_message
       
    48     )
       
    49 );
       
    50 
       
    51 named!(pub extract_messages<&[u8], Vec<EngineMessage> >, many0!(complete!(message)));
       
    52 
       
    53 #[test]
       
    54 fn parse_length() {
       
    55     assert_eq!(length_specifier(b"\x01"), Ok((&b""[..], 1)));
       
    56     assert_eq!(length_specifier(b"\x00"), Ok((&b""[..], 0)));
       
    57     assert_eq!(length_specifier(b"\x3f"), Ok((&b""[..], 63)));
       
    58     assert_eq!(length_specifier(b"\x40\x00"), Ok((&b""[..], 64)));
       
    59     assert_eq!(length_specifier(b"\xff\xff"), Ok((&b""[..], 49215)));
       
    60 }
       
    61 
       
    62 #[test]
       
    63 fn parse_synced_messages() {
       
    64     assert_eq!(message(b"\x04+l\x01\x01"), Ok((&b""[..], Synced(Left(Press), 0))));
       
    65 }
       
    66 
       
    67 #[test]
       
    68 fn parse_unsynced_messages() {
       
    69     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));
       
    70 }
       
    71 
       
    72 #[test]
       
    73 fn parse_incorrect_messages() {
       
    74     assert_eq!(message(b"\x00"), Ok((&b""[..], Empty)));
       
    75     assert_eq!(message(b"\x01\x00"), Ok((&b""[..], Unknown)));
       
    76 }
       
    77 
       
    78 #[test]
       
    79 fn parse_config_messages() {
       
    80     assert_eq!(
       
    81         message(b"\x01C"),
       
    82         Ok((
       
    83             &b""[..],
       
    84             Config(ConfigRequest)
       
    85         ))
       
    86     );
       
    87 }
       
    88 #[test]
       
    89 fn parse_test_general() {
       
    90     assert_eq!(string_tail(b"abc"), Ok((&b""[..], String::from("abc"))));
       
    91 }