125 map(tag_no_case(b"YES"), |_| true), |
125 map(tag_no_case(b"YES"), |_| true), |
126 map(tag_no_case(b"NO"), |_| false), |
126 map(tag_no_case(b"NO"), |_| false), |
127 ))(input) |
127 ))(input) |
128 } |
128 } |
129 |
129 |
130 fn opt_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> { |
130 fn opt_arg(input: &[u8]) -> HwResult<Option<String>> { |
131 alt(( |
131 alt(( |
132 map(peek(end_of_message), |_| None), |
132 map(peek(end_of_message), |_| None), |
133 map(preceded(tag("\n"), a_line), Some), |
133 map(preceded(tag("\n"), a_line), Some), |
134 ))(input) |
134 ))(input) |
135 } |
135 } |
136 |
136 |
137 fn spaces(input: &[u8]) -> HwResult<&[u8]> { |
137 fn spaces(input: &[u8]) -> HwResult<&[u8]> { |
138 preceded(tag(" "), take_while(|c| c == b' '))(input) |
138 preceded(tag(" "), take_while(|c| c == b' '))(input) |
139 } |
139 } |
140 |
140 |
141 fn opt_space_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> { |
141 fn opt_space_arg(input: &[u8]) -> HwResult<Option<String>> { |
142 alt(( |
142 alt(( |
143 map(peek(end_of_message), |_| None), |
143 map(peek(end_of_message), |_| None), |
144 map(preceded(spaces, a_line), Some), |
144 map(preceded(spaces, a_line), Some), |
145 ))(input) |
145 ))(input) |
146 } |
146 } |
182 map(preceded(tag_no_case("MAP"), opt_space_arg), VoteType::Map), |
182 map(preceded(tag_no_case("MAP"), opt_space_arg), VoteType::Map), |
183 ))(input) |
183 ))(input) |
184 } |
184 } |
185 |
185 |
186 fn no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
186 fn no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
187 fn message<'a>( |
187 fn message( |
188 name: &'a str, |
188 name: &str, |
189 msg: HwProtocolMessage, |
189 msg: HwProtocolMessage, |
190 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
190 ) -> impl Fn(&[u8]) -> HwResult<HwProtocolMessage> { |
191 move |i| map(tag(name), |_| msg.clone())(i) |
191 move |i| map(tag(name), |_| msg.clone())(i) |
192 } |
192 } |
193 |
193 |
194 alt(( |
194 alt(( |
195 message("PING", Ping), |
195 message("PING", Ping), |
205 message("READY", CheckerReady), |
205 message("READY", CheckerReady), |
206 ))(input) |
206 ))(input) |
207 } |
207 } |
208 |
208 |
209 fn single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
209 fn single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
210 fn message<'a, T, F, G>( |
210 fn message<T, F, G>( |
211 name: &'a str, |
211 name: &str, |
212 parser: F, |
212 parser: F, |
213 constructor: G, |
213 constructor: G, |
214 ) -> impl FnMut(&'a [u8]) -> HwResult<'a, HwProtocolMessage> |
214 ) -> impl FnMut(&[u8]) -> HwResult<HwProtocolMessage> |
215 where |
215 where |
216 F: Fn(&[u8]) -> HwResult<T>, |
216 F: Fn(&[u8]) -> HwResult<T>, |
217 G: Fn(T) -> HwProtocolMessage, |
217 G: Fn(T) -> HwProtocolMessage, |
218 { |
218 { |
219 map(preceded(tag(name), parser), constructor) |
219 map(preceded(tag(name), parser), constructor) |
237 message("CHECKED\nFAIL\n", a_line, CheckedFail), |
237 message("CHECKED\nFAIL\n", a_line, CheckedFail), |
238 ))(input) |
238 ))(input) |
239 } |
239 } |
240 |
240 |
241 fn cmd_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
241 fn cmd_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
242 fn cmd_no_arg<'a>( |
242 fn cmd_no_arg( |
243 name: &'a str, |
243 name: &str, |
244 msg: HwProtocolMessage, |
244 msg: HwProtocolMessage, |
245 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
245 ) -> impl Fn(&[u8]) -> HwResult<HwProtocolMessage> { |
246 move |i| map(tag_no_case(name), |_| msg.clone())(i) |
246 move |i| map(tag_no_case(name), |_| msg.clone())(i) |
247 } |
247 } |
248 |
248 |
249 fn cmd_single_arg<'a, T, F, G>( |
249 fn cmd_single_arg<'a, T, F, G>( |
250 name: &'a str, |
250 name: &'a str, |
317 )), |
317 )), |
318 )(input) |
318 )(input) |
319 } |
319 } |
320 |
320 |
321 fn config_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
321 fn config_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
322 fn cfg_single_arg<'a, T, F, G>( |
322 fn cfg_single_arg<T, F, G>( |
323 name: &'a str, |
323 name: &str, |
324 parser: F, |
324 parser: F, |
325 constructor: G, |
325 constructor: G, |
326 ) -> impl FnMut(&'a [u8]) -> HwResult<'a, GameCfg> |
326 ) -> impl FnMut(&[u8]) -> HwResult<GameCfg> |
327 where |
327 where |
328 F: Fn(&[u8]) -> HwResult<T>, |
328 F: Fn(&[u8]) -> HwResult<T>, |
329 G: Fn(T) -> GameCfg, |
329 G: Fn(T) -> GameCfg, |
330 { |
330 { |
331 map(preceded(pair(tag(name), newline), parser), constructor) |
331 map(preceded(pair(tag(name), newline), parser), constructor) |
519 } |
519 } |
520 |
520 |
521 pub fn server_message(input: &[u8]) -> HwResult<HwServerMessage> { |
521 pub fn server_message(input: &[u8]) -> HwResult<HwServerMessage> { |
522 use HwServerMessage::*; |
522 use HwServerMessage::*; |
523 |
523 |
524 fn single_arg_message<'a, T, F, G>( |
524 fn single_arg_message<T, F, G>( |
525 name: &'a str, |
525 name: &str, |
526 parser: F, |
526 parser: F, |
527 constructor: G, |
527 constructor: G, |
528 ) -> impl FnMut(&'a [u8]) -> HwResult<'a, HwServerMessage> |
528 ) -> impl FnMut(&[u8]) -> HwResult<HwServerMessage> |
529 where |
529 where |
530 F: Fn(&[u8]) -> HwResult<T>, |
530 F: Fn(&[u8]) -> HwResult<T>, |
531 G: Fn(T) -> HwServerMessage, |
531 G: Fn(T) -> HwServerMessage, |
532 { |
532 { |
533 map( |
533 map( |
534 preceded(terminated(tag(name), newline), parser), |
534 preceded(terminated(tag(name), newline), parser), |
535 constructor, |
535 constructor, |
536 ) |
536 ) |
537 } |
537 } |
538 |
538 |
539 fn list_message<'a, G>( |
539 fn list_message<G>( |
540 name: &'a str, |
540 name: &str, |
541 constructor: G, |
541 constructor: G, |
542 ) -> impl FnMut(&'a [u8]) -> HwResult<'a, HwServerMessage> |
542 ) -> impl FnMut(&[u8]) -> HwResult<HwServerMessage> |
543 where |
543 where |
544 G: Fn(Vec<String>) -> HwServerMessage, |
544 G: Fn(Vec<String>) -> HwServerMessage, |
545 { |
545 { |
546 map( |
546 map( |
547 preceded( |
547 preceded( |
553 ), |
553 ), |
554 move |values| constructor(values.unwrap_or_default()), |
554 move |values| constructor(values.unwrap_or_default()), |
555 ) |
555 ) |
556 } |
556 } |
557 |
557 |
558 fn string_and_list_message<'a, G>( |
558 fn string_and_list_message<G>( |
559 name: &'a str, |
559 name: &str, |
560 constructor: G, |
560 constructor: G, |
561 ) -> impl FnMut(&'a [u8]) -> HwResult<'a, HwServerMessage> |
561 ) -> impl FnMut(&[u8]) -> HwResult<HwServerMessage> |
562 where |
562 where |
563 G: Fn(String, Vec<String>) -> HwServerMessage, |
563 G: Fn(String, Vec<String>) -> HwServerMessage, |
564 { |
564 { |
565 preceded( |
565 preceded( |
566 pair(tag(name), newline), |
566 pair(tag(name), newline), |
575 move |(name, values)| constructor(name, values.unwrap_or_default()), |
575 move |(name, values)| constructor(name, values.unwrap_or_default()), |
576 ), |
576 ), |
577 ) |
577 ) |
578 } |
578 } |
579 |
579 |
580 fn message<'a>( |
580 fn message( |
581 name: &'a str, |
581 name: &str, |
582 msg: HwServerMessage, |
582 msg: HwServerMessage, |
583 ) -> impl Fn(&'a [u8]) -> HwResult<'a, HwServerMessage> { |
583 ) -> impl Fn(&[u8]) -> HwResult<HwServerMessage> { |
584 move |i| map(tag(name), |_| msg.clone())(i) |
584 move |i| map(tag(name), |_| msg.clone())(i) |
585 } |
585 } |
586 |
586 |
587 delimited( |
587 delimited( |
588 take_while(|c| c == b'\n'), |
588 take_while(|c| c == b'\n'), |