faster raw subject

This commit is contained in:
Robin Appelman 2021-08-29 13:54:22 +02:00
commit c215ca3987
3 changed files with 40 additions and 69 deletions

View file

@ -213,9 +213,7 @@ impl TryFrom<&RawSubject<'_>> for SubjectId {
return Err(SubjectError::InvalidSteamId); return Err(SubjectError::InvalidSteamId);
} }
} }
RawSubject::Team(team) => { RawSubject::Team(team) => SubjectId::Team(*team),
SubjectId::Team(team.parse().map_err(|_| SubjectError::InvalidTeam)?)
}
RawSubject::System(_) => SubjectId::System, RawSubject::System(_) => SubjectId::System,
RawSubject::Console => SubjectId::Console, RawSubject::Console => SubjectId::Console,
RawSubject::World => SubjectId::World, RawSubject::World => SubjectId::World,
@ -275,7 +273,7 @@ impl TryFrom<&RawSubject<'_>> for SubjectData {
team: team.parse().map_err(|_| SubjectError::InvalidTeam)?, team: team.parse().map_err(|_| SubjectError::InvalidTeam)?,
} }
} }
RawSubject::Team(team) => SubjectData::Team(team.parse().unwrap()), RawSubject::Team(team) => SubjectData::Team(*team),
RawSubject::System(name) => SubjectData::System(name.to_string()), RawSubject::System(name) => SubjectData::System(name.to_string()),
RawSubject::Console => SubjectData::Console, RawSubject::Console => SubjectData::Console,
RawSubject::World => SubjectData::World, RawSubject::World => SubjectData::World,

View file

@ -87,14 +87,16 @@ impl<Head: EventHandler, Tail: EventHandler> EventHandler for HandlerStack<Head,
} }
} }
#[macro_export]
macro_rules! replace_expr { macro_rules! replace_expr {
($_t:tt $sub:expr) => { ($_t:tt $sub:expr) => {
$sub $sub
}; };
} }
#[macro_export]
macro_rules! count_tts { macro_rules! count_tts {
($($tts:tt)*) => {0usize $(+ replace_expr!($tts 1usize))*}; ($($tts:tt)*) => {0usize $(+ $crate::replace_expr!($tts 1usize))*};
} }
#[macro_export] #[macro_export]
@ -119,7 +121,7 @@ macro_rules! handler {
S: serde::Serializer, S: serde::Serializer,
{ {
use serde::ser::SerializeStruct; use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct(concat!(stringify!($name), "output"), count_tts!($($child)*))?; let mut state = serializer.serialize_struct(concat!(stringify!($name), "output"), $crate::count_tts!($($child)*))?;
$( $(
if self.$child != <<$ty as $crate::EventHandler>::GlobalOutput>::default() { if self.$child != <<$ty as $crate::EventHandler>::GlobalOutput>::default() {
state.serialize_field(stringify!($child), &self.$child)?; state.serialize_field(stringify!($child), &self.$child)?;
@ -151,7 +153,7 @@ macro_rules! handler {
S: serde::Serializer, S: serde::Serializer,
{ {
use serde::ser::SerializeStruct; use serde::ser::SerializeStruct;
let mut state = serializer.serialize_struct(concat!(stringify!($name), "output"), count_tts!($($child)*))?; let mut state = serializer.serialize_struct(concat!(stringify!($name), "output"), $crate::count_tts!($($child)*))?;
$( $(
if self.$child != <<$ty as $crate::EventHandler>::PerSubjectOutput>::default() { if self.$child != <<$ty as $crate::EventHandler>::PerSubjectOutput>::default() {
state.serialize_field(stringify!($child), &self.$child)?; state.serialize_field(stringify!($child), &self.$child)?;

View file

@ -1,10 +1,11 @@
use crate::common::Team;
use crate::{SubjectError, SubjectId}; use crate::{SubjectError, SubjectId};
use chrono::{NaiveDate, NaiveDateTime}; use chrono::{NaiveDate, NaiveDateTime};
use logos::{Lexer, Logos}; use logos::{Lexer, Logos};
use nom::branch::alt; use nom::bytes::complete::{tag, take, take_while};
use nom::bytes::complete::{tag, tag_no_case, take, take_while};
use nom::character::complete::{digit1, one_of}; use nom::character::complete::{digit1, one_of};
use nom::{Finish, IResult}; use nom::combinator::opt;
use nom::{Finish, IResult, Needed};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::num::ParseIntError; use std::num::ParseIntError;
@ -18,13 +19,6 @@ pub struct RawEvent<'a> {
pub params: &'a str, pub params: &'a str,
} }
// pub enum RawEventToken {
// #[error]
// Error,
// #[regex(r"\d{2}/\d{2}/\d{4} - \d{2}:\d{2}:\d{2}"), |raw| NaiveDateTime::parse_from_str(raw, "%m/$d/%Y - %H:%M%S")]
// Date(NaiveDateTime),
// }
impl<'a> RawEvent<'a> { impl<'a> RawEvent<'a> {
pub fn parse(line: &'a str) -> Result<Self, nom::error::Error<&'a str>> { pub fn parse(line: &'a str) -> Result<Self, nom::error::Error<&'a str>> {
let (_, event) = event_parser(line).finish()?; let (_, event) = event_parser(line).finish()?;
@ -38,7 +32,7 @@ fn event_parser(input: &str) -> IResult<&str, RawEvent> {
let (input, _) = tag(": ")(input)?; let (input, _) = tag(": ")(input)?;
let (input, subject) = subject_parser(input)?; let (input, subject) = subject_parser(input)?;
let (input, _) = tag(" ")(input)?; let (input, _) = opt(tag(" "))(input)?;
let (input, ty) = event_type_parser(input)?; let (input, ty) = event_type_parser(input)?;
Ok(( Ok((
@ -87,7 +81,7 @@ fn test_parse_date() {
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum RawSubject<'a> { pub enum RawSubject<'a> {
Player(&'a str), Player(&'a str),
Team(&'a str), Team(Team),
System(&'a str), System(&'a str),
Console, Console,
World, World,
@ -99,39 +93,6 @@ impl<'a> RawSubject<'a> {
} }
} }
fn subject_parser_world(input: &str) -> IResult<&str, RawSubject> {
let (input, _) = tag("World")(input)?;
Ok((input, RawSubject::World))
}
fn subject_parser_console(input: &str) -> IResult<&str, RawSubject> {
let (input, _) = tag(r#""Console<0><Console><Console>""#)(input)?;
Ok((input, RawSubject::Console))
}
fn subject_parser_team(input: &str) -> IResult<&str, RawSubject> {
let (input, _) = tag(r#"Team ""#)(input)?;
let (input, team) = alt((tag_no_case("red"), tag_no_case("blue")))(input)?;
let (input, _) = one_of("\"")(input)?;
Ok((input, RawSubject::Team(team)))
}
fn subject_parser_system_bracket(input: &str) -> IResult<&str, &str> {
let (input, _) = tag("[")(input)?;
let (input, name) = take_while(|c| c != ']')(input)?;
let (input, _) = tag("]")(input)?;
IResult::Ok((input, name))
}
fn subject_parser_system(input: &str) -> IResult<&str, RawSubject> {
let (input, name) = alt((subject_parser_system_bracket, tag("Log"), tag("Tournament")))(input)?;
Ok((input, RawSubject::System(name)))
}
pub fn split_player_subject(input: &str) -> IResult<&str, (&str, &str, &str, &str)> { pub fn split_player_subject(input: &str) -> IResult<&str, (&str, &str, &str, &str)> {
let (input, name) = take_while(|c| c != '<')(input)?; let (input, name) = take_while(|c| c != '<')(input)?;
@ -150,24 +111,34 @@ pub fn split_player_subject(input: &str) -> IResult<&str, (&str, &str, &str, &st
Ok((input, (name, user_id, steam_id, team))) Ok((input, (name, user_id, steam_id, team)))
} }
fn subject_parser_player(input: &str) -> IResult<&str, RawSubject> {
let (input, _) = one_of("\"")(input)?;
let (input, subject) = take_while(|c| c != '"')(input)?;
let (input, _) = one_of("\"")(input)?;
Ok((input, RawSubject::Player(subject)))
}
pub fn subject_parser(input: &str) -> IResult<&str, RawSubject> { pub fn subject_parser(input: &str) -> IResult<&str, RawSubject> {
alt(( if input.starts_with('"') {
subject_parser_console, let (player, input) = input[1..]
subject_parser_player, .split_once('"')
subject_parser_world, .ok_or_else(|| nom::Err::Incomplete(Needed::Unknown))?;
subject_parser_team, if player.ends_with("e>") {
subject_parser_system, Ok((input, RawSubject::Console))
))(input) } else {
Ok((input, RawSubject::Player(player)))
}
} else if input.starts_with("Te") {
// Team "red" or Team "blue"
if &input[6..7] == "r" {
Ok((&input[10..], RawSubject::Team(Team::Red)))
} else if &input[6..7] == "b" {
Ok((&input[11..], RawSubject::Team(Team::Blue)))
} else {
let (_, input) = input[7..]
.split_once('"')
.ok_or_else(|| nom::Err::Incomplete(Needed::Unknown))?;
Ok((input, RawSubject::Team(Team::Spectator)))
}
} else {
let (system, input) = input
.split_once(' ')
.ok_or_else(|| nom::Err::Incomplete(Needed::Unknown))?;
Ok((input, RawSubject::System(system)))
}
} }
#[derive(Copy, Clone, Debug, PartialEq, Logos)] #[derive(Copy, Clone, Debug, PartialEq, Logos)]