12 ops::Range, |
12 ops::Range, |
13 str, |
13 str, |
14 str::{FromStr, Utf8Error}, |
14 str::{FromStr, Utf8Error}, |
15 }; |
15 }; |
16 |
16 |
17 use super::{ |
17 use super::messages::{HwProtocolMessage, HwProtocolMessage::*}; |
18 messages::{HWProtocolMessage, HWProtocolMessage::*}, |
|
19 }; |
|
20 use crate::core::types::{ |
18 use crate::core::types::{ |
21 GameCfg, HedgehogInfo, ServerVar, TeamInfo, VoteType, MAX_HEDGEHOGS_PER_TEAM, |
19 GameCfg, HedgehogInfo, ServerVar, TeamInfo, VoteType, MAX_HEDGEHOGS_PER_TEAM, |
22 }; |
20 }; |
23 |
21 |
24 #[derive(Debug, PartialEq)] |
22 #[derive(Debug, PartialEq)] |
25 pub struct HWProtocolError {} |
23 pub struct HwProtocolError {} |
26 |
24 |
27 impl HWProtocolError { |
25 impl HwProtocolError { |
28 fn new() -> Self { |
26 fn new() -> Self { |
29 HWProtocolError {} |
27 HwProtocolError {} |
30 } |
28 } |
31 } |
29 } |
32 |
30 |
33 impl<I> ParseError<I> for HWProtocolError { |
31 impl<I> ParseError<I> for HwProtocolError { |
34 fn from_error_kind(input: I, kind: ErrorKind) -> Self { |
32 fn from_error_kind(input: I, kind: ErrorKind) -> Self { |
35 HWProtocolError::new() |
33 HwProtocolError::new() |
36 } |
34 } |
37 |
35 |
38 fn append(input: I, kind: ErrorKind, other: Self) -> Self { |
36 fn append(input: I, kind: ErrorKind, other: Self) -> Self { |
39 HWProtocolError::new() |
37 HwProtocolError::new() |
40 } |
38 } |
41 } |
39 } |
42 |
40 |
43 impl From<Utf8Error> for HWProtocolError { |
41 impl From<Utf8Error> for HwProtocolError { |
44 fn from(_: Utf8Error) -> Self { |
42 fn from(_: Utf8Error) -> Self { |
45 HWProtocolError::new() |
43 HwProtocolError::new() |
46 } |
44 } |
47 } |
45 } |
48 |
46 |
49 impl From<ParseIntError> for HWProtocolError { |
47 impl From<ParseIntError> for HwProtocolError { |
50 fn from(_: ParseIntError) -> Self { |
48 fn from(_: ParseIntError) -> Self { |
51 HWProtocolError::new() |
49 HwProtocolError::new() |
52 } |
50 } |
53 } |
51 } |
54 |
52 |
55 pub type HWResult<'a, O> = IResult<&'a [u8], O, HWProtocolError>; |
53 pub type HwResult<'a, O> = IResult<&'a [u8], O, HwProtocolError>; |
56 |
54 |
57 fn end_of_message(input: &[u8]) -> HWResult<&[u8]> { |
55 fn end_of_message(input: &[u8]) -> HwResult<&[u8]> { |
58 tag("\n\n")(input) |
56 tag("\n\n")(input) |
59 } |
57 } |
60 |
58 |
61 fn convert_utf8(input: &[u8]) -> HWResult<&str> { |
59 fn convert_utf8(input: &[u8]) -> HwResult<&str> { |
62 match str::from_utf8(input) { |
60 match str::from_utf8(input) { |
63 Ok(str) => Ok((b"", str)), |
61 Ok(str) => Ok((b"", str)), |
64 Err(utf_err) => Result::Err(Err::Failure(utf_err.into())), |
62 Err(utf_err) => Result::Err(Err::Failure(utf_err.into())), |
65 } |
63 } |
66 } |
64 } |
67 |
65 |
68 fn convert_from_str<T>(str: &str) -> HWResult<T> |
66 fn convert_from_str<T>(str: &str) -> HwResult<T> |
69 where |
67 where |
70 T: FromStr<Err = ParseIntError>, |
68 T: FromStr<Err = ParseIntError>, |
71 { |
69 { |
72 match T::from_str(str) { |
70 match T::from_str(str) { |
73 Ok(x) => Ok((b"", x)), |
71 Ok(x) => Ok((b"", x)), |
74 Err(format_err) => Result::Err(Err::Failure(format_err.into())), |
72 Err(format_err) => Result::Err(Err::Failure(format_err.into())), |
75 } |
73 } |
76 } |
74 } |
77 |
75 |
78 fn str_line(input: &[u8]) -> HWResult<&str> { |
76 fn str_line(input: &[u8]) -> HwResult<&str> { |
79 let (i, text) = not_line_ending(input)?; |
77 let (i, text) = not_line_ending(input)?; |
80 Ok((i, convert_utf8(text)?.1)) |
78 Ok((i, convert_utf8(text)?.1)) |
81 } |
79 } |
82 |
80 |
83 fn a_line(input: &[u8]) -> HWResult<String> { |
81 fn a_line(input: &[u8]) -> HwResult<String> { |
84 let (i, str) = str_line(input)?; |
82 let (i, str) = str_line(input)?; |
85 Ok((i, str.to_string())) |
83 Ok((i, str.to_string())) |
86 } |
84 } |
87 |
85 |
88 fn hw_tag<'a>(tag_str: &'a str) -> impl Fn(&'a [u8]) -> HWResult<'a, ()> { |
86 fn hw_tag<'a>(tag_str: &'a str) -> impl Fn(&'a [u8]) -> HwResult<'a, ()> { |
89 move |i| tag(tag_str)(i).map(|(i, _)| (i, ())) |
87 move |i| tag(tag_str)(i).map(|(i, _)| (i, ())) |
90 } |
88 } |
91 |
89 |
92 fn hw_tag_no_case<'a>(tag_str: &'a str) -> impl Fn(&'a [u8]) -> HWResult<'a, ()> { |
90 fn hw_tag_no_case<'a>(tag_str: &'a str) -> impl Fn(&'a [u8]) -> HwResult<'a, ()> { |
93 move |i| tag_no_case(tag_str)(i).map(|(i, _)| (i, ())) |
91 move |i| tag_no_case(tag_str)(i).map(|(i, _)| (i, ())) |
94 } |
92 } |
95 |
93 |
96 fn cmd_arg(input: &[u8]) -> HWResult<String> { |
94 fn cmd_arg(input: &[u8]) -> HwResult<String> { |
97 let delimiters = b" \n"; |
95 let delimiters = b" \n"; |
98 let (i, str) = take_while(move |c| !delimiters.contains(&c))(input)?; |
96 let (i, str) = take_while(move |c| !delimiters.contains(&c))(input)?; |
99 Ok((i, convert_utf8(str)?.1.to_string())) |
97 Ok((i, convert_utf8(str)?.1.to_string())) |
100 } |
98 } |
101 |
99 |
102 fn u8_line(input: &[u8]) -> HWResult<u8> { |
100 fn u8_line(input: &[u8]) -> HwResult<u8> { |
103 let (i, str) = str_line(input)?; |
101 let (i, str) = str_line(input)?; |
104 Ok((i, convert_from_str(str)?.1)) |
102 Ok((i, convert_from_str(str)?.1)) |
105 } |
103 } |
106 |
104 |
107 fn u16_line(input: &[u8]) -> HWResult<u16> { |
105 fn u16_line(input: &[u8]) -> HwResult<u16> { |
108 let (i, str) = str_line(input)?; |
106 let (i, str) = str_line(input)?; |
109 Ok((i, convert_from_str(str)?.1)) |
107 Ok((i, convert_from_str(str)?.1)) |
110 } |
108 } |
111 |
109 |
112 fn u32_line(input: &[u8]) -> HWResult<u32> { |
110 fn u32_line(input: &[u8]) -> HwResult<u32> { |
113 let (i, str) = str_line(input)?; |
111 let (i, str) = str_line(input)?; |
114 Ok((i, convert_from_str(str)?.1)) |
112 Ok((i, convert_from_str(str)?.1)) |
115 } |
113 } |
116 |
114 |
117 fn yes_no_line(input: &[u8]) -> HWResult<bool> { |
115 fn yes_no_line(input: &[u8]) -> HwResult<bool> { |
118 alt(( |
116 alt(( |
119 |i| tag_no_case(b"YES")(i).map(|(i, _)| (i, true)), |
117 |i| tag_no_case(b"YES")(i).map(|(i, _)| (i, true)), |
120 |i| tag_no_case(b"NO")(i).map(|(i, _)| (i, false)), |
118 |i| tag_no_case(b"NO")(i).map(|(i, _)| (i, false)), |
121 ))(input) |
119 ))(input) |
122 } |
120 } |
123 |
121 |
124 fn opt_arg<'a>(input: &'a [u8]) -> HWResult<'a, Option<String>> { |
122 fn opt_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> { |
125 alt(( |
123 alt(( |
126 |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)), |
124 |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)), |
127 |i| precededc(i, hw_tag("\n"), a_line).map(|(i, v)| (i, Some(v))), |
125 |i| precededc(i, hw_tag("\n"), a_line).map(|(i, v)| (i, Some(v))), |
128 ))(input) |
126 ))(input) |
129 } |
127 } |
130 |
128 |
131 fn spaces(input: &[u8]) -> HWResult<&[u8]> { |
129 fn spaces(input: &[u8]) -> HwResult<&[u8]> { |
132 precededc(input, hw_tag(" "), |i| take_while(|c| c == b' ')(i)) |
130 precededc(input, hw_tag(" "), |i| take_while(|c| c == b' ')(i)) |
133 } |
131 } |
134 |
132 |
135 fn opt_space_arg<'a>(input: &'a [u8]) -> HWResult<'a, Option<String>> { |
133 fn opt_space_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> { |
136 alt(( |
134 alt(( |
137 |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)), |
135 |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)), |
138 |i| precededc(i, spaces, a_line).map(|(i, v)| (i, Some(v))), |
136 |i| precededc(i, spaces, a_line).map(|(i, v)| (i, Some(v))), |
139 ))(input) |
137 ))(input) |
140 } |
138 } |
141 |
139 |
142 fn hedgehog_array(input: &[u8]) -> HWResult<[HedgehogInfo; 8]> { |
140 fn hedgehog_array(input: &[u8]) -> HwResult<[HedgehogInfo; 8]> { |
143 fn hedgehog_line(input: &[u8]) -> HWResult<HedgehogInfo> { |
141 fn hedgehog_line(input: &[u8]) -> HwResult<HedgehogInfo> { |
144 let (i, name) = terminatedc(input, a_line, eol)?; |
142 let (i, name) = terminatedc(input, a_line, eol)?; |
145 let (i, hat) = a_line(i)?; |
143 let (i, hat) = a_line(i)?; |
146 Ok((i, HedgehogInfo { name, hat })) |
144 Ok((i, HedgehogInfo { name, hat })) |
147 } |
145 } |
148 |
146 |
231 |i| messagec(i, "PROTO\n", u16_line, Proto), |
229 |i| messagec(i, "PROTO\n", u16_line, Proto), |
232 |i| messagec(i, "QUIT", opt_arg, Quit), |
230 |i| messagec(i, "QUIT", opt_arg, Quit), |
233 ))(input) |
231 ))(input) |
234 } |
232 } |
235 |
233 |
236 fn cmd_message<'a>(input: &'a [u8]) -> HWResult<'a, HWProtocolMessage> { |
234 fn cmd_message<'a>(input: &'a [u8]) -> HwResult<'a, HwProtocolMessage> { |
237 fn cmdc_no_arg<'a>( |
235 fn cmdc_no_arg<'a>( |
238 input: &'a [u8], |
236 input: &'a [u8], |
239 name: &'a str, |
237 name: &'a str, |
240 msg: HWProtocolMessage, |
238 msg: HwProtocolMessage, |
241 ) -> HWResult<'a, HWProtocolMessage> { |
239 ) -> HwResult<'a, HwProtocolMessage> { |
242 tag_no_case(name)(input).map(|(i, _)| (i, msg.clone())) |
240 tag_no_case(name)(input).map(|(i, _)| (i, msg.clone())) |
243 } |
241 } |
244 |
242 |
245 fn cmdc_single_arg<'a, T, F, G>( |
243 fn cmdc_single_arg<'a, T, F, G>( |
246 input: &'a [u8], |
244 input: &'a [u8], |
247 name: &'a str, |
245 name: &'a str, |
248 parser: F, |
246 parser: F, |
249 constructor: G, |
247 constructor: G, |
250 ) -> HWResult<'a, HWProtocolMessage> |
248 ) -> HwResult<'a, HwProtocolMessage> |
251 where |
249 where |
252 F: Fn(&'a [u8]) -> HWResult<'a, T>, |
250 F: Fn(&'a [u8]) -> HwResult<'a, T>, |
253 G: Fn(T) -> HWProtocolMessage, |
251 G: Fn(T) -> HwProtocolMessage, |
254 { |
252 { |
255 precededc(input, |i| pairc(i, hw_tag_no_case(name), spaces), parser) |
253 precededc(input, |i| pairc(i, hw_tag_no_case(name), spaces), parser) |
256 .map(|(i, v)| (i, constructor(v))) |
254 .map(|(i, v)| (i, constructor(v))) |
257 } |
255 } |
258 |
256 |
259 fn cmd_no_arg_message(input: &[u8]) -> HWResult<HWProtocolMessage> { |
257 fn cmd_no_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
260 alt(( |
258 alt(( |
261 |i| cmdc_no_arg(i, "STATS", Stats), |
259 |i| cmdc_no_arg(i, "STATS", Stats), |
262 |i| cmdc_no_arg(i, "FIX", Fix), |
260 |i| cmdc_no_arg(i, "FIX", Fix), |
263 |i| cmdc_no_arg(i, "UNFIX", Unfix), |
261 |i| cmdc_no_arg(i, "UNFIX", Unfix), |
264 |i| cmdc_no_arg(i, "REGISTERED_ONLY", ToggleServerRegisteredOnly), |
262 |i| cmdc_no_arg(i, "REGISTERED_ONLY", ToggleServerRegisteredOnly), |
265 |i| cmdc_no_arg(i, "SUPER_POWER", SuperPower), |
263 |i| cmdc_no_arg(i, "SUPER_POWER", SuperPower), |
266 ))(input) |
264 ))(input) |
267 } |
265 } |
268 |
266 |
269 fn cmd_single_arg_message(input: &[u8]) -> HWResult<HWProtocolMessage> { |
267 fn cmd_single_arg_message(input: &[u8]) -> HwResult<HwProtocolMessage> { |
270 alt(( |
268 alt(( |
271 |i| cmdc_single_arg(i, "RESTART_SERVER", |i| tag("YES")(i), |_| RestartServer), |
269 |i| cmdc_single_arg(i, "RESTART_SERVER", |i| tag("YES")(i), |_| RestartServer), |
272 |i| cmdc_single_arg(i, "DELEGATE", a_line, Delegate), |
270 |i| cmdc_single_arg(i, "DELEGATE", a_line, Delegate), |
273 |i| cmdc_single_arg(i, "DELETE", a_line, Delete), |
271 |i| cmdc_single_arg(i, "DELETE", a_line, Delete), |
274 |i| cmdc_single_arg(i, "SAVEROOM", a_line, SaveRoom), |
272 |i| cmdc_single_arg(i, "SAVEROOM", a_line, SaveRoom), |