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")))))); |