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 } |