rust/hedgewars-server/src/protocol/parser.rs
changeset 15114 a7841105493e
parent 15112 6a1ba3540fa0
child 15116 cce6e707172f
equal deleted inserted replaced
15113:7d6e519a88c5 15114:a7841105493e
     4  * indicated by a double newline - `\n\n`.
     4  * indicated by a double newline - `\n\n`.
     5  *
     5  *
     6  * For example, a nullary command like PING will be actually sent as `PING\n\n`.
     6  * For example, a nullary command like PING will be actually sent as `PING\n\n`.
     7  * A unary command, such as `START_GAME nick` will be actually sent as `START_GAME\nnick\n\n`.
     7  * A unary command, such as `START_GAME nick` will be actually sent as `START_GAME\nnick\n\n`.
     8  */
     8  */
     9 use nom::*;
     9 use nom::{
       
    10     branch::alt,
       
    11     bytes::complete::{tag, tag_no_case, take_until, take_while},
       
    12     character::complete::{newline, not_line_ending},
       
    13     combinator::peek,
       
    14     error::{ErrorKind, ParseError},
       
    15     multi::separated_list,
       
    16     sequence::{pairc, precededc, terminatedc},
       
    17     Err, IResult,
       
    18 };
       
    19 
    10 use std::{
    20 use std::{
    11     num::ParseIntError,
    21     num::ParseIntError,
    12     ops::Range,
    22     ops::Range,
    13     str,
    23     str,
    14     str::{FromStr, Utf8Error},
    24     str::{FromStr, Utf8Error},
   119     ))(input)
   129     ))(input)
   120 }
   130 }
   121 
   131 
   122 fn opt_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> {
   132 fn opt_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> {
   123     alt((
   133     alt((
   124         |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)),
   134         |i| peek(end_of_message)(i).map(|(i, _)| (i, None)),
   125         |i| precededc(i, hw_tag("\n"), a_line).map(|(i, v)| (i, Some(v))),
   135         |i| precededc(i, hw_tag("\n"), a_line).map(|(i, v)| (i, Some(v))),
   126     ))(input)
   136     ))(input)
   127 }
   137 }
   128 
   138 
   129 fn spaces(input: &[u8]) -> HwResult<&[u8]> {
   139 fn spaces(input: &[u8]) -> HwResult<&[u8]> {
   130     precededc(input, hw_tag(" "), |i| take_while(|c| c == b' ')(i))
   140     precededc(input, hw_tag(" "), |i| take_while(|c| c == b' ')(i))
   131 }
   141 }
   132 
   142 
   133 fn opt_space_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> {
   143 fn opt_space_arg<'a>(input: &'a [u8]) -> HwResult<'a, Option<String>> {
   134     alt((
   144     alt((
   135         |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)),
   145         |i| peek(end_of_message)(i).map(|(i, _)| (i, None)),
   136         |i| precededc(i, spaces, a_line).map(|(i, v)| (i, Some(v))),
   146         |i| precededc(i, spaces, a_line).map(|(i, v)| (i, Some(v))),
   137     ))(input)
   147     ))(input)
   138 }
   148 }
   139 
   149 
   140 fn hedgehog_array(input: &[u8]) -> HwResult<[HedgehogInfo; 8]> {
   150 fn hedgehog_array(input: &[u8]) -> HwResult<[HedgehogInfo; 8]> {
   141     fn hedgehog_line(input: &[u8]) -> HwResult<HedgehogInfo> {
   151     fn hedgehog_line(input: &[u8]) -> HwResult<HedgehogInfo> {
   142         let (i, name) = terminatedc(input, a_line, eol)?;
   152         let (i, name) = terminatedc(input, a_line, newline)?;
   143         let (i, hat) = a_line(i)?;
   153         let (i, hat) = a_line(i)?;
   144         Ok((i, HedgehogInfo { name, hat }))
   154         Ok((i, HedgehogInfo { name, hat }))
   145     }
   155     }
   146 
   156 
   147     let (i, h1) = terminatedc(input, hedgehog_line, eol)?;
   157     let (i, h1) = terminatedc(input, hedgehog_line, newline)?;
   148     let (i, h2) = terminatedc(i, hedgehog_line, eol)?;
   158     let (i, h2) = terminatedc(i, hedgehog_line, newline)?;
   149     let (i, h3) = terminatedc(i, hedgehog_line, eol)?;
   159     let (i, h3) = terminatedc(i, hedgehog_line, newline)?;
   150     let (i, h4) = terminatedc(i, hedgehog_line, eol)?;
   160     let (i, h4) = terminatedc(i, hedgehog_line, newline)?;
   151     let (i, h5) = terminatedc(i, hedgehog_line, eol)?;
   161     let (i, h5) = terminatedc(i, hedgehog_line, newline)?;
   152     let (i, h6) = terminatedc(i, hedgehog_line, eol)?;
   162     let (i, h6) = terminatedc(i, hedgehog_line, newline)?;
   153     let (i, h7) = terminatedc(i, hedgehog_line, eol)?;
   163     let (i, h7) = terminatedc(i, hedgehog_line, newline)?;
   154     let (i, h8) = hedgehog_line(i)?;
   164     let (i, h8) = hedgehog_line(i)?;
   155 
   165 
   156     Ok((i, [h1, h2, h3, h4, h5, h6, h7, h8]))
   166     Ok((i, [h1, h2, h3, h4, h5, h6, h7, h8]))
   157 }
   167 }
   158 
   168 
   304                 })
   314                 })
   305                 .map(|(i, (n, l))| (i, Save(n, l)))
   315                 .map(|(i, (n, l))| (i, Save(n, l)))
   306             },
   316             },
   307             |i| {
   317             |i| {
   308                 let (i, _) = tag_no_case("RND")(i)?;
   318                 let (i, _) = tag_no_case("RND")(i)?;
   309                 let (i, _) = alt((spaces, |i: &'a [u8]| peek!(i, end_of_message)))(i)?;
   319                 let (i, _) = alt((spaces, peek(end_of_message)))(i)?;
   310                 let (i, v) = str_line(i)?;
   320                 let (i, v) = str_line(i)?;
   311                 Ok((i, Rnd(v.split_whitespace().map(String::from).collect())))
   321                 Ok((i, Rnd(v.split_whitespace().map(String::from).collect())))
   312             },
   322             },
   313         )),
   323         )),
   314     )
   324     )
   323     ) -> HwResult<'a, GameCfg>
   333     ) -> HwResult<'a, GameCfg>
   324     where
   334     where
   325         F: Fn(&[u8]) -> HwResult<T>,
   335         F: Fn(&[u8]) -> HwResult<T>,
   326         G: Fn(T) -> GameCfg,
   336         G: Fn(T) -> GameCfg,
   327     {
   337     {
   328         precededc(input, |i| terminatedc(i, hw_tag(name), eol), parser)
   338         precededc(input, |i| terminatedc(i, hw_tag(name), newline), parser)
   329             .map(|(i, v)| (i, constructor(v)))
   339             .map(|(i, v)| (i, constructor(v)))
   330     }
   340     }
   331 
   341 
   332     let (i, cfg) = precededc(
   342     let (i, cfg) = precededc(
   333         input,
   343         input,
   343             |i| cfgc_single_arg(i, "SEED", a_line, GameCfg::Seed),
   353             |i| cfgc_single_arg(i, "SEED", a_line, GameCfg::Seed),
   344             |i| cfgc_single_arg(i, "DRAWNMAP", a_line, GameCfg::DrawnMap),
   354             |i| cfgc_single_arg(i, "DRAWNMAP", a_line, GameCfg::DrawnMap),
   345             |i| {
   355             |i| {
   346                 precededc(
   356                 precededc(
   347                     i,
   357                     i,
   348                     |i| terminatedc(i, hw_tag("AMMO"), eol),
   358                     |i| terminatedc(i, hw_tag("AMMO"), newline),
   349                     |i| {
   359                     |i| {
   350                         let (i, name) = a_line(i)?;
   360                         let (i, name) = a_line(i)?;
   351                         let (i, value) = opt_arg(i)?;
   361                         let (i, value) = opt_arg(i)?;
   352                         Ok((i, GameCfg::Ammo(name, value)))
   362                         Ok((i, GameCfg::Ammo(name, value)))
   353                     },
   363                     },
   354                 )
   364                 )
   355             },
   365             },
   356             |i| {
   366             |i| {
   357                 precededc(
   367                 precededc(
   358                     i,
   368                     i,
   359                     |i| terminatedc(i, hw_tag("SCHEME"), eol),
   369                     |i| terminatedc(i, hw_tag("SCHEME"), newline),
   360                     |i| {
   370                     |i| {
   361                         let (i, name) = a_line(i)?;
   371                         let (i, name) = a_line(i)?;
   362                         let (i, values) = alt((
   372                         let (i, values) = alt((
   363                             |i: &'a [u8]| peek!(i, end_of_message).map(|(i, _)| (i, None)),
   373                             |i| peek(end_of_message)(i).map(|(i, _)| (i, None)),
   364                             |i| {
   374                             |i| {
   365                                 precededc(i, eol, |i| separated_list(eol, a_line)(i))
   375                                 precededc(i, newline, |i| separated_list(newline, a_line)(i))
   366                                     .map(|(i, v)| (i, Some(v)))
   376                                     .map(|(i, v)| (i, Some(v)))
   367                             },
   377                             },
   368                         ))(i)?;
   378                         ))(i)?;
   369                         Ok((i, GameCfg::Scheme(name, values.unwrap_or_default())))
   379                         Ok((i, GameCfg::Scheme(name, values.unwrap_or_default())))
   370                     },
   380                     },
   399 fn complex_message(input: &[u8]) -> HwResult<HwProtocolMessage> {
   409 fn complex_message(input: &[u8]) -> HwResult<HwProtocolMessage> {
   400     alt((
   410     alt((
   401         |i| {
   411         |i| {
   402             precededc(
   412             precededc(
   403                 i,
   413                 i,
   404                 |i| terminatedc(i, hw_tag("PASSWORD"), eol),
   414                 |i| terminatedc(i, hw_tag("PASSWORD"), newline),
   405                 |i| {
   415                 |i| {
   406                     let (i, pass) = terminatedc(i, a_line, eol)?;
   416                     let (i, pass) = terminatedc(i, a_line, newline)?;
   407                     let (i, salt) = a_line(i)?;
   417                     let (i, salt) = a_line(i)?;
   408                     Ok((i, Password(pass, salt)))
   418                     Ok((i, Password(pass, salt)))
   409                 },
   419                 },
   410             )
   420             )
   411         },
   421         },
   412         |i| {
   422         |i| {
   413             precededc(
   423             precededc(
   414                 i,
   424                 i,
   415                 |i| terminatedc(i, hw_tag("CHECKER"), eol),
   425                 |i| terminatedc(i, hw_tag("CHECKER"), newline),
   416                 |i| {
   426                 |i| {
   417                     let (i, protocol) = terminatedc(i, u16_line, eol)?;
   427                     let (i, protocol) = terminatedc(i, u16_line, newline)?;
   418                     let (i, name) = terminatedc(i, a_line, eol)?;
   428                     let (i, name) = terminatedc(i, a_line, newline)?;
   419                     let (i, pass) = a_line(i)?;
   429                     let (i, pass) = a_line(i)?;
   420                     Ok((i, Checker(protocol, name, pass)))
   430                     Ok((i, Checker(protocol, name, pass)))
   421                 },
   431                 },
   422             )
   432             )
   423         },
   433         },
   424         |i| {
   434         |i| {
   425             precededc(
   435             precededc(
   426                 i,
   436                 i,
   427                 |i| terminatedc(i, hw_tag("CREATE_ROOM"), eol),
   437                 |i| terminatedc(i, hw_tag("CREATE_ROOM"), newline),
   428                 |i| {
   438                 |i| {
   429                     let (i, name) = a_line(i)?;
   439                     let (i, name) = a_line(i)?;
   430                     let (i, pass) = opt_arg(i)?;
   440                     let (i, pass) = opt_arg(i)?;
   431                     Ok((i, CreateRoom(name, pass)))
   441                     Ok((i, CreateRoom(name, pass)))
   432                 },
   442                 },
   433             )
   443             )
   434         },
   444         },
   435         |i| {
   445         |i| {
   436             precededc(
   446             precededc(
   437                 i,
   447                 i,
   438                 |i| terminatedc(i, hw_tag("JOIN_ROOM"), eol),
   448                 |i| terminatedc(i, hw_tag("JOIN_ROOM"), newline),
   439                 |i| {
   449                 |i| {
   440                     let (i, name) = a_line(i)?;
   450                     let (i, name) = a_line(i)?;
   441                     let (i, pass) = opt_arg(i)?;
   451                     let (i, pass) = opt_arg(i)?;
   442                     Ok((i, JoinRoom(name, pass)))
   452                     Ok((i, JoinRoom(name, pass)))
   443                 },
   453                 },
   444             )
   454             )
   445         },
   455         },
   446         |i| {
   456         |i| {
   447             precededc(
   457             precededc(
   448                 i,
   458                 i,
   449                 |i| terminatedc(i, hw_tag("ADD_TEAM"), eol),
   459                 |i| terminatedc(i, hw_tag("ADD_TEAM"), newline),
   450                 |i| {
   460                 |i| {
   451                     let (i, name) = terminatedc(i, a_line, eol)?;
   461                     let (i, name) = terminatedc(i, a_line, newline)?;
   452                     let (i, color) = terminatedc(i, u8_line, eol)?;
   462                     let (i, color) = terminatedc(i, u8_line, newline)?;
   453                     let (i, grave) = terminatedc(i, a_line, eol)?;
   463                     let (i, grave) = terminatedc(i, a_line, newline)?;
   454                     let (i, fort) = terminatedc(i, a_line, eol)?;
   464                     let (i, fort) = terminatedc(i, a_line, newline)?;
   455                     let (i, voice_pack) = terminatedc(i, a_line, eol)?;
   465                     let (i, voice_pack) = terminatedc(i, a_line, newline)?;
   456                     let (i, flag) = terminatedc(i, a_line, eol)?;
   466                     let (i, flag) = terminatedc(i, a_line, newline)?;
   457                     let (i, difficulty) = terminatedc(i, u8_line, eol)?;
   467                     let (i, difficulty) = terminatedc(i, u8_line, newline)?;
   458                     let (i, hedgehogs) = hedgehog_array(i)?;
   468                     let (i, hedgehogs) = hedgehog_array(i)?;
   459                     Ok((
   469                     Ok((
   460                         i,
   470                         i,
   461                         AddTeam(Box::new(TeamInfo {
   471                         AddTeam(Box::new(TeamInfo {
   462                             owner: String::new(),
   472                             owner: String::new(),
   475             )
   485             )
   476         },
   486         },
   477         |i| {
   487         |i| {
   478             precededc(
   488             precededc(
   479                 i,
   489                 i,
   480                 |i| terminatedc(i, hw_tag("HH_NUM"), eol),
   490                 |i| terminatedc(i, hw_tag("HH_NUM"), newline),
   481                 |i| {
   491                 |i| {
   482                     let (i, name) = terminatedc(i, a_line, eol)?;
   492                     let (i, name) = terminatedc(i, a_line, newline)?;
   483                     let (i, count) = u8_line(i)?;
   493                     let (i, count) = u8_line(i)?;
   484                     Ok((i, SetHedgehogsNumber(name, count)))
   494                     Ok((i, SetHedgehogsNumber(name, count)))
   485                 },
   495                 },
   486             )
   496             )
   487         },
   497         },
   488         |i| {
   498         |i| {
   489             precededc(
   499             precededc(
   490                 i,
   500                 i,
   491                 |i| terminatedc(i, hw_tag("TEAM_COLOR"), eol),
   501                 |i| terminatedc(i, hw_tag("TEAM_COLOR"), newline),
   492                 |i| {
   502                 |i| {
   493                     let (i, name) = terminatedc(i, a_line, eol)?;
   503                     let (i, name) = terminatedc(i, a_line, newline)?;
   494                     let (i, color) = u8_line(i)?;
   504                     let (i, color) = u8_line(i)?;
   495                     Ok((i, SetTeamColor(name, color)))
   505                     Ok((i, SetTeamColor(name, color)))
   496                 },
   506                 },
   497             )
   507             )
   498         },
   508         },
   499         |i| {
   509         |i| {
   500             precededc(
   510             precededc(
   501                 i,
   511                 i,
   502                 |i| terminatedc(i, hw_tag("BAN"), eol),
   512                 |i| terminatedc(i, hw_tag("BAN"), newline),
   503                 |i| {
   513                 |i| {
   504                     let (i, n) = terminatedc(i, a_line, eol)?;
   514                     let (i, n) = terminatedc(i, a_line, newline)?;
   505                     let (i, r) = terminatedc(i, a_line, eol)?;
   515                     let (i, r) = terminatedc(i, a_line, newline)?;
   506                     let (i, t) = u32_line(i)?;
   516                     let (i, t) = u32_line(i)?;
   507                     Ok((i, Ban(n, r, t)))
   517                     Ok((i, Ban(n, r, t)))
   508                 },
   518                 },
   509             )
   519             )
   510         },
   520         },
   511         |i| {
   521         |i| {
   512             precededc(
   522             precededc(
   513                 i,
   523                 i,
   514                 |i| terminatedc(i, hw_tag("BAN_IP"), eol),
   524                 |i| terminatedc(i, hw_tag("BAN_IP"), newline),
   515                 |i| {
   525                 |i| {
   516                     let (i, n) = terminatedc(i, a_line, eol)?;
   526                     let (i, n) = terminatedc(i, a_line, newline)?;
   517                     let (i, r) = terminatedc(i, a_line, eol)?;
   527                     let (i, r) = terminatedc(i, a_line, newline)?;
   518                     let (i, t) = u32_line(i)?;
   528                     let (i, t) = u32_line(i)?;
   519                     Ok((i, BanIP(n, r, t)))
   529                     Ok((i, BanIP(n, r, t)))
   520                 },
   530                 },
   521             )
   531             )
   522         },
   532         },
   523         |i| {
   533         |i| {
   524             precededc(
   534             precededc(
   525                 i,
   535                 i,
   526                 |i| terminatedc(i, hw_tag("BAN_NICK"), eol),
   536                 |i| terminatedc(i, hw_tag("BAN_NICK"), newline),
   527                 |i| {
   537                 |i| {
   528                     let (i, n) = terminatedc(i, a_line, eol)?;
   538                     let (i, n) = terminatedc(i, a_line, newline)?;
   529                     let (i, r) = terminatedc(i, a_line, eol)?;
   539                     let (i, r) = terminatedc(i, a_line, newline)?;
   530                     let (i, t) = u32_line(i)?;
   540                     let (i, t) = u32_line(i)?;
   531                     Ok((i, BanNick(n, r, t)))
   541                     Ok((i, BanNick(n, r, t)))
   532                 },
   542                 },
   533             )
   543             )
   534         },
   544         },