rust/hedgewars-server/src/protocol/parser.rs
changeset 15124 824472aa4d97
parent 15122 4f31954a0b81
child 15801 f57a3d48072b
equal deleted inserted replaced
15123:1aa3b44c0441 15124:824472aa4d97
    11     bytes::complete::{tag, tag_no_case, take_until, take_while},
    11     bytes::complete::{tag, tag_no_case, take_until, take_while},
    12     character::complete::{newline, not_line_ending},
    12     character::complete::{newline, not_line_ending},
    13     combinator::{map, peek},
    13     combinator::{map, peek},
    14     error::{ErrorKind, ParseError},
    14     error::{ErrorKind, ParseError},
    15     multi::separated_list,
    15     multi::separated_list,
    16     sequence::{delimited, pair, preceded, terminated},
    16     sequence::{delimited, pair, preceded, terminated, tuple},
    17     Err, IResult,
    17     Err, IResult,
    18 };
    18 };
    19 
    19 
    20 use std::{
    20 use std::{
    21     num::ParseIntError,
    21     num::ParseIntError,
   146     ))(input)
   146     ))(input)
   147 }
   147 }
   148 
   148 
   149 fn hedgehog_array(input: &[u8]) -> HwResult<[HedgehogInfo; 8]> {
   149 fn hedgehog_array(input: &[u8]) -> HwResult<[HedgehogInfo; 8]> {
   150     fn hedgehog_line(input: &[u8]) -> HwResult<HedgehogInfo> {
   150     fn hedgehog_line(input: &[u8]) -> HwResult<HedgehogInfo> {
   151         let (i, name) = terminated(a_line, newline)(input)?;
   151         map(
   152         let (i, hat) = a_line(i)?;
   152             tuple((terminated(a_line, newline), a_line)),
   153         Ok((i, HedgehogInfo { name, hat }))
   153             |(name, hat)| HedgehogInfo { name, hat },
   154     }
   154         )(input)
   155 
   155     }
   156     let (i, h1) = terminated(hedgehog_line, newline)(input)?;
   156 
   157     let (i, h2) = terminated(hedgehog_line, newline)(i)?;
   157     let (i, (h1, h2, h3, h4, h5, h6, h7, h8)) = tuple((
   158     let (i, h3) = terminated(hedgehog_line, newline)(i)?;
   158         terminated(hedgehog_line, newline),
   159     let (i, h4) = terminated(hedgehog_line, newline)(i)?;
   159         terminated(hedgehog_line, newline),
   160     let (i, h5) = terminated(hedgehog_line, newline)(i)?;
   160         terminated(hedgehog_line, newline),
   161     let (i, h6) = terminated(hedgehog_line, newline)(i)?;
   161         terminated(hedgehog_line, newline),
   162     let (i, h7) = terminated(hedgehog_line, newline)(i)?;
   162         terminated(hedgehog_line, newline),
   163     let (i, h8) = hedgehog_line(i)?;
   163         terminated(hedgehog_line, newline),
       
   164         terminated(hedgehog_line, newline),
       
   165         hedgehog_line,
       
   166     ))(input)?;
   164 
   167 
   165     Ok((i, [h1, h2, h3, h4, h5, h6, h7, h8]))
   168     Ok((i, [h1, h2, h3, h4, h5, h6, h7, h8]))
   166 }
   169 }
   167 
   170 
   168 fn voting(input: &[u8]) -> HwResult<VoteType> {
   171 fn voting(input: &[u8]) -> HwResult<VoteType> {
   342             preceded(pair(tag("AMMO"), newline), |i| {
   345             preceded(pair(tag("AMMO"), newline), |i| {
   343                 let (i, name) = a_line(i)?;
   346                 let (i, name) = a_line(i)?;
   344                 let (i, value) = opt_arg(i)?;
   347                 let (i, value) = opt_arg(i)?;
   345                 Ok((i, GameCfg::Ammo(name, value)))
   348                 Ok((i, GameCfg::Ammo(name, value)))
   346             }),
   349             }),
   347             preceded(pair(tag("SCHEME"), newline), |i| {
   350             preceded(
   348                 let (i, name) = a_line(i)?;
   351                 pair(tag("SCHEME"), newline),
   349                 let (i, values) = alt((
   352                 map(
   350                     map(peek(end_of_message), |_| None),
   353                     pair(
   351                     map(preceded(newline, separated_list(newline, a_line)), Some),
   354                         a_line,
   352                 ))(i)?;
   355                         alt((
   353                 Ok((i, GameCfg::Scheme(name, values.unwrap_or_default())))
   356                             map(peek(end_of_message), |_| None),
   354             }),
   357                             map(preceded(newline, separated_list(newline, a_line)), Some),
       
   358                         )),
       
   359                     ),
       
   360                     |(name, values)| GameCfg::Scheme(name, values.unwrap_or_default()),
       
   361                 ),
       
   362             ),
   355         )),
   363         )),
   356     )(input)?;
   364     )(input)?;
   357     Ok((i, Cfg(cfg)))
   365     Ok((i, Cfg(cfg)))
   358 }
   366 }
   359 
   367 
   374     )(input)
   382     )(input)
   375 }
   383 }
   376 
   384 
   377 fn complex_message(input: &[u8]) -> HwResult<HwProtocolMessage> {
   385 fn complex_message(input: &[u8]) -> HwResult<HwProtocolMessage> {
   378     alt((
   386     alt((
   379         preceded(pair(tag("PASSWORD"), newline), |i| {
   387         preceded(
   380             let (i, pass) = terminated(a_line, newline)(i)?;
   388             pair(tag("PASSWORD"), newline),
   381             let (i, salt) = a_line(i)?;
   389             map(pair(terminated(a_line, newline), a_line), |(pass, salt)| {
   382             Ok((i, Password(pass, salt)))
   390                 Password(pass, salt)
   383         }),
   391             }),
   384         preceded(pair(tag("CHECKER"), newline), |i| {
   392         ),
   385             let (i, protocol) = terminated(u16_line, newline)(i)?;
   393         preceded(
   386             let (i, name) = terminated(a_line, newline)(i)?;
   394             pair(tag("CHECKER"), newline),
   387             let (i, pass) = a_line(i)?;
   395             map(
   388             Ok((i, Checker(protocol, name, pass)))
   396                 tuple((
   389         }),
   397                     terminated(u16_line, newline),
   390         preceded(pair(tag("CREATE_ROOM"), newline), |i| {
   398                     terminated(a_line, newline),
   391             let (i, name) = a_line(i)?;
   399                     a_line,
   392             let (i, pass) = opt_arg(i)?;
   400                 )),
   393             Ok((i, CreateRoom(name, pass)))
   401                 |(protocol, name, pass)| Checker(protocol, name, pass),
   394         }),
   402             ),
   395         preceded(pair(tag("JOIN_ROOM"), newline), |i| {
   403         ),
   396             let (i, name) = a_line(i)?;
   404         preceded(
   397             let (i, pass) = opt_arg(i)?;
   405             pair(tag("CREATE_ROOM"), newline),
   398             Ok((i, JoinRoom(name, pass)))
   406             map(pair(a_line, opt_arg), |(name, pass)| CreateRoom(name, pass)),
   399         }),
   407         ),
   400         preceded(pair(tag("ADD_TEAM"), newline), |i| {
   408         preceded(
   401             let (i, name) = terminated(a_line, newline)(i)?;
   409             pair(tag("JOIN_ROOM"), newline),
   402             let (i, color) = terminated(u8_line, newline)(i)?;
   410             map(pair(a_line, opt_arg), |(name, pass)| JoinRoom(name, pass)),
   403             let (i, grave) = terminated(a_line, newline)(i)?;
   411         ),
   404             let (i, fort) = terminated(a_line, newline)(i)?;
   412         preceded(
   405             let (i, voice_pack) = terminated(a_line, newline)(i)?;
   413             pair(tag("ADD_TEAM"), newline),
   406             let (i, flag) = terminated(a_line, newline)(i)?;
   414             map(
   407             let (i, difficulty) = terminated(u8_line, newline)(i)?;
   415                 tuple((
   408             let (i, hedgehogs) = hedgehog_array(i)?;
   416                     terminated(a_line, newline),
   409             Ok((
   417                     terminated(u8_line, newline),
   410                 i,
   418                     terminated(a_line, newline),
   411                 AddTeam(Box::new(TeamInfo {
   419                     terminated(a_line, newline),
   412                     owner: String::new(),
   420                     terminated(a_line, newline),
   413                     name,
   421                     terminated(a_line, newline),
   414                     color,
   422                     terminated(u8_line, newline),
   415                     grave,
   423                     hedgehog_array,
   416                     fort,
   424                 )),
   417                     voice_pack,
   425                 |(name, color, grave, fort, voice_pack, flag, difficulty, hedgehogs)| {
   418                     flag,
   426                     AddTeam(Box::new(TeamInfo {
   419                     difficulty,
   427                         owner: String::new(),
   420                     hedgehogs,
   428                         name,
   421                     hedgehogs_number: 0,
   429                         color,
   422                 })),
   430                         grave,
   423             ))
   431                         fort,
   424         }),
   432                         voice_pack,
   425         preceded(pair(tag("HH_NUM"), newline), |i| {
   433                         flag,
   426             let (i, name) = terminated(a_line, newline)(i)?;
   434                         difficulty,
   427             let (i, count) = u8_line(i)?;
   435                         hedgehogs,
   428             Ok((i, SetHedgehogsNumber(name, count)))
   436                         hedgehogs_number: 0,
   429         }),
   437                     }))
   430         preceded(pair(tag("TEAM_COLOR"), newline), |i| {
   438                 },
   431             let (i, name) = terminated(a_line, newline)(i)?;
   439             ),
   432             let (i, color) = u8_line(i)?;
   440         ),
   433             Ok((i, SetTeamColor(name, color)))
   441         preceded(
   434         }),
   442             pair(tag("HH_NUM"), newline),
   435         preceded(pair(tag("BAN"), newline), |i| {
   443             map(
   436             let (i, n) = terminated(a_line, newline)(i)?;
   444                 pair(terminated(a_line, newline), u8_line),
   437             let (i, r) = terminated(a_line, newline)(i)?;
   445                 |(name, count)| SetHedgehogsNumber(name, count),
   438             let (i, t) = u32_line(i)?;
   446             ),
   439             Ok((i, Ban(n, r, t)))
   447         ),
   440         }),
   448         preceded(
   441         preceded(pair(tag("BAN_IP"), newline), |i| {
   449             pair(tag("TEAM_COLOR"), newline),
   442             let (i, n) = terminated(a_line, newline)(i)?;
   450             map(
   443             let (i, r) = terminated(a_line, newline)(i)?;
   451                 pair(terminated(a_line, newline), u8_line),
   444             let (i, t) = u32_line(i)?;
   452                 |(name, color)| SetTeamColor(name, color),
   445             Ok((i, BanIP(n, r, t)))
   453             ),
   446         }),
   454         ),
   447         preceded(pair(tag("BAN_NICK"), newline), |i| {
   455         preceded(
   448             let (i, n) = terminated(a_line, newline)(i)?;
   456             pair(tag("BAN"), newline),
   449             let (i, r) = terminated(a_line, newline)(i)?;
   457             map(
   450             let (i, t) = u32_line(i)?;
   458                 tuple((
   451             Ok((i, BanNick(n, r, t)))
   459                     terminated(a_line, newline),
   452         }),
   460                     terminated(a_line, newline),
       
   461                     u32_line,
       
   462                 )),
       
   463                 |(name, reason, time)| Ban(name, reason, time),
       
   464             ),
       
   465         ),
       
   466         preceded(
       
   467             pair(tag("BAN_IP"), newline),
       
   468             map(
       
   469                 tuple((
       
   470                     terminated(a_line, newline),
       
   471                     terminated(a_line, newline),
       
   472                     u32_line,
       
   473                 )),
       
   474                 |(ip, reason, time)| BanIp(ip, reason, time),
       
   475             ),
       
   476         ),
       
   477         preceded(
       
   478             pair(tag("BAN_NICK"), newline),
       
   479             map(
       
   480                 tuple((
       
   481                     terminated(a_line, newline),
       
   482                     terminated(a_line, newline),
       
   483                     u32_line,
       
   484                 )),
       
   485                 |(nick, reason, time)| BanNick(nick, reason, time),
       
   486             ),
       
   487         ),
   453     ))(input)
   488     ))(input)
   454 }
   489 }
   455 
   490 
   456 pub fn malformed_message(input: &[u8]) -> HwResult<()> {
   491 pub fn malformed_message(input: &[u8]) -> HwResult<()> {
   457     map(terminated(take_until(&b"\n\n"[..]), end_of_message), |_| ())(input)
   492     map(terminated(take_until(&b"\n\n"[..]), end_of_message), |_| ())(input)