rust/hedgewars-engine-messages/src/parser.rs
changeset 14210 1c55c54013c4
parent 14209 ab1ef7074e07
child 14211 0f7b92397b9e
equal deleted inserted replaced
14209:ab1ef7074e07 14210:1c55c54013c4
     1 use nom::*;
     1 use nom::{*};
     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 named!(length_specifier<&[u8], u16>, alt!(
     6 
     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 
     7 
    12 named!(unrecognized_message<&[u8], EngineMessage>,
     8 named!(unrecognized_message<&[u8], EngineMessage>,
    13     do_parse!(rest >> (Unknown))
     9     do_parse!(rest >> (Unknown))
    14 );
    10 );
    15 
    11 
    16 named!(string_tail<&[u8], String>, map!(map_res!(rest, str::from_utf8), String::from));
    12 named!(string_tail<&[u8], String>, map!(map_res!(rest, str::from_utf8), String::from));
    17 
    13 
       
    14 named!(length_without_timestamp<&[u8], usize>,
       
    15     map_opt!(rest_len, |l| if l > 2 { Some(l - 2) } else { None } )
       
    16 );
       
    17 
    18 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    18 named!(synced_message<&[u8], SyncedEngineMessage>, alt!(
    19       do_parse!(tag!("+l") >> (Left(Press)))
    19       do_parse!(tag!("L") >> (Left(Press)))
    20 ));
    20 ));
       
    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 );
    21 
    28 
    22 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    29 named!(unsynced_message<&[u8], UnsyncedEngineMessage>, alt!(
    23       do_parse!(tag!("?") >> (Ping))
    30       do_parse!(tag!("?") >> (Ping))
    24     | do_parse!(tag!("!") >> (Ping))
    31     | do_parse!(tag!("!") >> (Ping))
    25     | do_parse!(tag!("esay ") >> s: string_tail  >> (Say(s)))
    32     | do_parse!(tag!("esay ") >> s: string_tail  >> (Say(s)))
    27 
    34 
    28 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    35 named!(config_message<&[u8], ConfigEngineMessage>, alt!(
    29     do_parse!(tag!("C") >> (ConfigRequest))
    36     do_parse!(tag!("C") >> (ConfigRequest))
    30 ));
    37 ));
    31 
    38 
       
    39 named!(unwrapped_message<&[u8], EngineMessage>,
       
    40     alt!(
       
    41         map!(timestamped_message, |(m, t)| Synced(m, t as u32))
       
    42         | do_parse!(tag!("#") >> (Synced(TimeWrap, 65535)))
       
    43         | map!(unsynced_message, |m| Unsynced(m))
       
    44         | map!(config_message, |m| Config(m))
       
    45         | unrecognized_message
       
    46 ));
       
    47 
       
    48 
       
    49 
       
    50 named!(length_specifier<&[u8], u16>, alt!(
       
    51     verify!(map!(take!(1), |a : &[u8]| a[0] as u16), |l| l < 64)
       
    52     | map!(take!(2), |a| (a[0] as u16 - 64) * 256 + a[1] as u16 + 64)
       
    53     )
       
    54 );
       
    55 
    32 named!(empty_message<&[u8], EngineMessage>,
    56 named!(empty_message<&[u8], EngineMessage>,
    33     do_parse!(tag!("\0") >> (Empty))
    57     do_parse!(tag!("\0") >> (Empty))
    34 );
    58 );
    35 
    59 
    36 named!(non_empty_message<&[u8], EngineMessage>, length_value!(length_specifier,
    60 named!(non_empty_message<&[u8], EngineMessage>,
    37     alt!(
    61     length_value!(length_specifier, unwrapped_message));
    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 
    62 
    45 named!(message<&[u8], EngineMessage>, alt!(
    63 named!(message<&[u8], EngineMessage>, alt!(
    46       empty_message
    64       empty_message
    47     | non_empty_message
    65     | non_empty_message
    48     )
    66     )
    59     assert_eq!(length_specifier(b"\xff\xff"), Ok((&b""[..], 49215)));
    77     assert_eq!(length_specifier(b"\xff\xff"), Ok((&b""[..], 49215)));
    60 }
    78 }
    61 
    79 
    62 #[test]
    80 #[test]
    63 fn parse_synced_messages() {
    81 fn parse_synced_messages() {
    64     assert_eq!(message(b"\x04+l\x01\x01"), Ok((&b""[..], Synced(Left(Press), 0))));
    82     assert_eq!(message(b"\x03L\x01\x02"), Ok((&b""[..], Synced(Left(Press), 258))));
    65 }
    83 }
    66 
    84 
    67 #[test]
    85 #[test]
    68 fn parse_unsynced_messages() {
    86 fn parse_unsynced_messages() {
    69     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));
    87     assert_eq!(message(b"\x0aesay hello"), Ok((&b""[..], Unsynced(Say(String::from("hello"))))));