1
0
Fork 0
mirror of https://codeberg.org/demostf/parser.git synced 2026-06-03 10:14:06 +02:00

allow changing analyser

This commit is contained in:
Robin Appelman 2019-03-23 17:45:56 +01:00
commit 86be659513
7 changed files with 56 additions and 54 deletions

View file

@ -13,8 +13,7 @@ fn bench_file(input_file: &str, b: &mut Bencher) {
let stream: Stream = demo.get_stream();
b.iter(|| {
let parser = DemoParser::new(stream.clone());
let (_, state) = parser.parse_demo().unwrap();
let (_, state) = DemoParser::parse_demo(stream.clone()).unwrap();
test::black_box(state);
})
}

View file

@ -11,9 +11,7 @@ fn main() -> std::result::Result<(), Box<ParseError>> {
let path = args[1].clone();
let file = fs::read(path).expect("Unable to read file");
let demo = Demo::new(file);
let stream: Stream = demo.get_stream();
let parser = DemoParser::new(stream);
let (_, state) = parser.parse_demo()?;
let (_, state) = DemoParser::parse_demo(demo.get_stream())?;
let json = serde_json::to_string(&state).unwrap_or("err".to_string());
println!("{}", json);
Ok(())

View file

@ -1,18 +1,18 @@
use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use serde_repr::{Serialize_repr, Deserialize_repr};
use serde::{Deserialize, Serialize};
use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::{ParserState, ReadResult, Stream};
use crate::demo::gameevent_gen::{
GameEvent, PlayerDeathEvent, PlayerSpawnEvent, TeamPlayRoundWinEvent,
};
use crate::demo::message::{Message, MessageType};
use crate::demo::message::packetentities::EntityId;
use crate::demo::message::usermessage::{ChatMessageKind, SayText2Message, UserMessage};
use crate::demo::message::{Message, MessageType};
use crate::demo::packet::stringtable::StringTableEntry;
use crate::demo::parser::handler::{MessageHandler, StringTableEntryHandler};
use crate::demo::parser::handler::MessageHandler;
use crate::demo::vector::Vector;
use crate::{ParserState, ReadResult, Stream};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ChatMassage {
@ -176,6 +176,8 @@ pub struct Analyser {
}
impl MessageHandler for Analyser {
type Output = MatchState;
fn does_handle(message_type: MessageType) -> bool {
match message_type {
MessageType::GameEvent | MessageType::UserMessage => true,
@ -193,9 +195,7 @@ impl MessageHandler for Analyser {
_ => {}
}
}
}
impl StringTableEntryHandler for Analyser {
fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {
match table.as_str() {
"userinfo" => {
@ -211,6 +211,17 @@ impl StringTableEntryHandler for Analyser {
_ => {}
}
}
fn get_output(self, state: ParserState) -> MatchState {
MatchState {
start_tick: self.start_tick,
interval_per_tick: state.demo_meta.interval_per_tick,
chat: self.chat,
deaths: self.deaths,
rounds: self.rounds,
users: UserState::from_users_and_spawn(self.users, self.user_spawns),
}
}
}
impl Analyser {
@ -274,17 +285,6 @@ impl Analyser {
}
Ok(())
}
pub fn get_match_state(self, state: ParserState) -> MatchState {
MatchState {
start_tick: self.start_tick,
interval_per_tick: state.demo_meta.interval_per_tick,
chat: self.chat,
deaths: self.deaths,
rounds: self.rounds,
users: UserState::from_users_and_spawn(self.users, self.user_spawns),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq)]

View file

@ -2,30 +2,37 @@ use crate::demo::message::{Message, MessageType};
use crate::demo::packet::datatable::{SendTable, ServerClass};
use crate::demo::packet::stringtable::{StringTable, StringTableEntry};
use crate::demo::packet::Packet;
use crate::demo::parser::analyser::{Analyser, MatchState};
use crate::demo::parser::analyser::{Analyser};
use crate::ParserState;
pub trait MessageHandler {
type Output;
fn does_handle(message_type: MessageType) -> bool;
fn handle_message(&mut self, message: Message, tick: u32);
}
pub trait StringTableEntryHandler {
fn handle_string_entry(&mut self, table: &String, index: usize, entries: &StringTableEntry);
fn get_output(self, state: ParserState) -> Self::Output;
}
#[derive(Default)]
pub struct DemoHandler {
pub struct DemoHandler<T: MessageHandler> {
tick: u32,
string_table_names: Vec<String>,
analyser: Analyser,
analyser: T,
state_handler: ParserState,
}
impl DemoHandler {
impl DemoHandler<Analyser> {
pub fn new() -> Self {
let analyser = Analyser::new();
Self::with_analyser(Analyser::new())
}
}
impl<T: MessageHandler> DemoHandler<T> {
pub fn with_analyser(analyser: T) -> Self {
let state_handler = ParserState::new();
DemoHandler {
@ -110,8 +117,8 @@ impl DemoHandler {
}
}
pub fn get_match_state(self) -> MatchState {
self.analyser.get_match_state(self.state_handler)
pub fn get_output(self) -> T::Output {
self.analyser.get_output(self.state_handler)
}
pub fn get_parser_state(&self) -> &ParserState {

View file

@ -3,8 +3,9 @@ use bitstream_reader::{BitRead, BitSkip, LittleEndian, ReadError};
use crate::demo::gamevent::{GameEventValue, GameEventValueType};
use crate::demo::header::Header;
use crate::demo::packet::Packet;
use crate::demo::parser::analyser::Analyser;
pub use crate::demo::parser::analyser::MatchState;
use crate::demo::parser::handler::DemoHandler;
use crate::demo::parser::handler::{DemoHandler, MessageHandler};
pub use crate::demo::parser::state::ParserState;
use crate::Stream;
@ -85,28 +86,23 @@ impl<T: BitSkip<LittleEndian>> ParseBitSkip for T {
}
}
pub struct DemoParser {
stream: Stream,
handler: DemoHandler,
}
pub struct DemoParser {}
impl DemoParser {
pub fn new(stream: Stream) -> Self {
DemoParser {
stream,
handler: DemoHandler::new(),
}
pub fn parse_demo(stream: Stream) -> Result<(Header, MatchState)> {
Self::parse_with_analyser(stream, Analyser::new())
}
pub fn parse_demo(mut self) -> Result<(Header, MatchState)> {
let header = Header::read(&mut self.stream)?;
pub fn parse_with_analyser<T: MessageHandler>(mut stream: Stream, analyser: T) -> Result<(Header, T::Output)> {
let mut handler = DemoHandler::with_analyser(analyser);
let header = Header::read(&mut stream)?;
loop {
let packet = Packet::parse(&mut self.stream, self.handler.get_parser_state())?;
let packet = Packet::parse(&mut stream, handler.get_parser_state())?;
match packet {
Packet::Stop(_) => break,
packet => self.handler.handle_packet(packet),
packet => handler.handle_packet(packet),
};
}
Ok((header, self.handler.get_match_state()))
Ok((header, handler.get_output()))
}
}

View file

@ -7,7 +7,7 @@ use crate::demo::message::packetentities::EntityId;
use crate::demo::message::stringtable::StringTableMeta;
use crate::demo::packet::datatable::{SendTable, ServerClass};
use crate::demo::packet::stringtable::StringTableEntry;
use crate::demo::parser::handler::{MessageHandler, StringTableEntryHandler};
use crate::demo::parser::handler::{MessageHandler};
use crate::demo::sendprop::SendProp;
use crate::Stream;
use crate::demo::parser::analyser::Analyser;
@ -73,6 +73,8 @@ impl ParserState {
}
impl MessageHandler for ParserState {
type Output = Self;
fn does_handle(message_type: MessageType) -> bool {
match message_type {
MessageType::ServerInfo
@ -96,9 +98,7 @@ impl MessageHandler for ParserState {
_ => {}
}
}
}
impl StringTableEntryHandler for ParserState {
fn handle_string_entry(&mut self, table: &String, _index: usize, entry: &StringTableEntry) {
match table.as_str() {
"instancebaseline" => match &entry.extra_data {
@ -114,4 +114,8 @@ impl StringTableEntryHandler for ParserState {
_ => {}
}
}
fn get_output(self, _state: ParserState) -> Self {
self
}
}

View file

@ -1,14 +1,12 @@
use std::fs;
use pretty_assertions::assert_eq;
use tf_demo_parser::{Demo, DemoParser, Stream, MatchState};
use tf_demo_parser::{Demo, DemoParser, MatchState};
fn snapshot_test(input_file: &str, snapshot_file: &str) {
let file = fs::read(input_file).expect("Unable to read file");
let demo = Demo::new(file);
let stream: Stream = demo.get_stream();
let parser = DemoParser::new(stream);
let (_, state) = parser.parse_demo().unwrap();
let (_, state) = DemoParser::parse_demo(demo.get_stream()).unwrap();
let expected: MatchState = serde_json::from_slice(fs::read(snapshot_file).expect("Unable to read file").as_slice()).unwrap();
assert_eq!(expected, state);